improving authentication code (tidyup).
authorLuke Leighton <lkcl@samba.org>
Tue, 29 Jun 1999 18:47:06 +0000 (18:47 +0000)
committerLuke Leighton <lkcl@samba.org>
Tue, 29 Jun 1999 18:47:06 +0000 (18:47 +0000)
19 files changed:
source/include/client.h
source/include/proto.h
source/include/rpc_dce.h
source/lib/hmacmd5.c
source/lib/util.c
source/libsmb/clientgen.c
source/libsmb/pwd_cache.c
source/libsmb/smbencrypt.c
source/param/loadparm.c
source/passdb/sampassdb.c
source/rpc_client/cli_pipe.c
source/rpc_parse/parse_rpc.c
source/rpc_server/srv_netlog.c
source/rpc_server/srv_pipe.c
source/rpcclient/rpcclient.c
source/smbd/password.c
source/smbd/reply.c
source/smbd/service.c
source/utils/rpctorture.c

index 89bcf49248b7dffd61c5cc0c77addf367bac4576..b06d87718154477b60ff4a927a8870328bcb2b68 100644 (file)
@@ -58,17 +58,22 @@ struct print_job_info
 
 struct pwd_info
 {
-    BOOL null_pwd;
-    BOOL cleartext;
-    BOOL crypted;
+       BOOL null_pwd;
+       BOOL cleartext;
+       BOOL crypted;
 
-    fstring password;
+       fstring password;
 
-    uchar smb_lm_pwd[16];
-    uchar smb_nt_pwd[16];
+       uchar smb_lm_pwd[16];
+       uchar smb_nt_pwd[16];
 
-    uchar smb_lm_owf[24];
-    uchar smb_nt_owf[24];
+       uchar smb_lm_owf[24];
+       uchar smb_nt_owf[128];
+       size_t nt_owf_len;
+
+       uchar lm_cli_chal[8];
+       uchar nt_cli_chal[128];
+       size_t nt_cli_chal_len;
 };
 
 struct cli_state {
@@ -106,6 +111,12 @@ struct cli_state {
 
        struct pwd_info pwd;
        unsigned char cryptkey[8];
+       unsigned char lm_cli_chal[8];
+       unsigned char nt_cli_chal[128];
+       size_t nt_cli_chal_len;
+
+       BOOL use_ntlmv2;
+
        uint32 sesskey;
        int serverzone;
        uint32 servertime;
index 361eda72b5d8f3837dd67253ac4eb55cba067ece..7673fc2ed55bf349a464cea0389ae8ab6b4df0dd 100644 (file)
@@ -229,8 +229,9 @@ char *getsmbpass(char *prompt)    ;
 /*The following definitions come from  lib/hmacmd5.c  */
 
 void hmac_md5_init_rfc2104(uchar*  key, int key_len, HMACMD5Context *ctx);
-void hmac_md5_init_limK_to_64(uchar*  key, int key_len, HMACMD5Context *ctx);
-void hmac_md5_update(uchar* text, int text_len, HMACMD5Context *ctx);
+void hmac_md5_init_limK_to_64(const uchar* key, int key_len,
+                       HMACMD5Context *ctx);
+void hmac_md5_update(const uchar* text, int text_len, HMACMD5Context *ctx);
 void hmac_md5_final(caddr_t digest, HMACMD5Context *ctx);
 
 /*The following definitions come from  lib/interface.c  */
@@ -466,8 +467,8 @@ char *align4(char *q, char *base);
 char *align2(char *q, char *base);
 void out_ascii(FILE *f, unsigned char *buf,int len);
 void out_data(FILE *f,char *buf1,int len, int per_line);
-void print_asc(int level, unsigned char *buf,int len);
-void dump_data(int level,char *buf1, int len);
+void print_asc(int level, unsigned char const *buf,int len);
+void dump_data(int level, const char *buf1, int len);
 char *tab_depth(int depth);
 int str_checksum(const char *s);
 void zero_free(void *p, size_t size);
@@ -621,11 +622,16 @@ BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation);
 BOOL cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *));
 BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
                       void (*fn)(const char *, uint32, const char *));
+BOOL cli_session_setup_x(struct cli_state *cli, 
+                               char *user, 
+                               char *pass, int passlen,
+                               char *ntpass, int ntpasslen,
+                               char *user_domain);
 BOOL cli_session_setup(struct cli_state *cli, 
-                      char *user, 
-                      char *pass, int passlen,
-                      char *ntpass, int ntpasslen,
-                      char *workgroup);
+                               char *user, 
+                               char *pass, int passlen,
+                               char *ntpass, int ntpasslen,
+                               char *user_domain);
 BOOL cli_ulogoff(struct cli_state *cli);
 BOOL cli_send_tconX(struct cli_state *cli, 
                    char *share, char *dev, char *pass, int passlen);
@@ -754,8 +760,11 @@ void pwd_get_cleartext(struct pwd_info *pwd, char *clr);
 void pwd_set_lm_nt_16(struct pwd_info *pwd, uchar lm_pwd[16], uchar nt_pwd[16]);
 void pwd_get_lm_nt_16(struct pwd_info *pwd, uchar lm_pwd[16], uchar nt_pwd[16]);
 void pwd_make_lm_nt_16(struct pwd_info *pwd, char *clr);
+void pwd_make_lm_nt_owf2(struct pwd_info *pwd, const uchar srv_key[8],
+               const char *user, const char *server, const char *domain);
 void pwd_make_lm_nt_owf(struct pwd_info *pwd, uchar cryptkey[8]);
-void pwd_get_lm_nt_owf(struct pwd_info *pwd, uchar lm_owf[24], uchar nt_owf[24]);
+void pwd_get_lm_nt_owf(struct pwd_info *pwd, uchar lm_owf[24],
+                               uchar *nt_owf, size_t *nt_owf_len);
 
 /*The following definitions come from  libsmb/smbdes.c  */
 
@@ -772,11 +781,24 @@ void SamOEMhash( unsigned char *data, unsigned char *key, int val);
 /*The following definitions come from  libsmb/smbencrypt.c  */
 
 void SMBencrypt(uchar *passwd, uchar *c8, uchar *p24);
+void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24);
 void E_md4hash(uchar *passwd, uchar *p16);
-void nt_lm_owf_gen(const char *pwd, uchar nt_p16[16], uchar p16[16]);
+void lm_owf_gen(const char *pwd, uchar p16[16]);
+void nt_owf_gen(const char *pwd, uchar nt_p16[16]);
+void nt_lm_owf_gen(const char *pwd, uchar nt_p16[16], uchar lm_p16[16]);
 void SMBOWFencrypt(uchar passwd[16], uchar *c8, uchar p24[24]);
+void SMBOWFencrypt_ntv2(const uchar kr[16], 
+                               const uchar *srv_chal, int srv_chal_len,
+                               const uchar *cli_chal, int cli_chal_len,
+                               char resp_buf[16]);
+void SMBgenclientchals(char *lm_cli_chal,
+                               char *nt_cli_chal, int *nt_cli_chal_len,
+                               const char *srv, const char *domain);
+void ntv2_owf_gen(const uchar owf[16], 
+                               const char *user_n,
+                               const char *domain_n,
+                               uchar kr_buf[16]);
 void NTLMSSPOWFencrypt(uchar passwd[8], uchar *ntlmchalresp, uchar p24[24]);
-void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24);
 BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[16], BOOL unicode);
 BOOL nt_decrypt_string2(STRING2 *out, const STRING2 *in, char nt_hash[16]);
 
@@ -1259,6 +1281,7 @@ BOOL lp_null_passwords(void);
 BOOL lp_strip_dot(void);
 BOOL lp_encrypted_passwords(void);
 BOOL lp_update_encrypted(void);
+BOOL lp_client_ntlmv2(void);
 BOOL lp_server_ntlmv2(void);
 BOOL lp_syslog_only(void);
 BOOL lp_timestamp_logs(void);
@@ -2360,7 +2383,8 @@ void make_rpc_auth_ntlmssp_chal(RPC_AUTH_NTLMSSP_CHAL *chl,
                                uint8 challenge[8]);
 void smb_io_rpc_auth_ntlmssp_chal(char *desc, RPC_AUTH_NTLMSSP_CHAL *chl, prs_struct *ps, int depth);
 void make_rpc_auth_ntlmssp_resp(RPC_AUTH_NTLMSSP_RESP *rsp,
-                               uchar lm_resp[24], uchar nt_resp[24],
+                               uchar lm_resp[24],
+                               uchar *nt_resp, size_t nt_len,
                                char *domain, char *user, char *wks,
                                uint32 neg_flags);
 void smb_io_rpc_auth_ntlmssp_resp(char *desc, RPC_AUTH_NTLMSSP_RESP *rsp, prs_struct *ps, int depth);
@@ -3429,11 +3453,13 @@ void invalidate_vuid(uint16 vuid);
 char *validated_username(uint16 vuid);
 uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, BOOL guest, uchar user_sess_key[16]);
 void add_session_user(char *user);
-BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned char *c8);
 BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8],
-                     uchar lm_pass[24], uchar nt_pass[24]);
-BOOL pass_check_smb(char *user, char *domain,
-               uchar *chal, uchar *lm_pwd, uchar *nt_pwd,
+                               const char *user, const char *domain,
+                               uchar *lm_pass, size_t lm_pwd_len,
+                               uchar *nt_pass, size_t nt_pwd_len);
+BOOL pass_check_smb(char *user, char *domain, uchar *chal,
+               uchar *lm_pwd, size_t lm_pwd_len,
+               uchar *nt_pwd, size_t nt_pwd_len,
                struct passwd *pwd, uchar user_sess_key[16]);
 BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd,
                uchar user_sess_key[16]);
index b8647fda0f8e0804d13a6400a914364feca1f1a0..3a2956cb6d45288f43fe6ce104b5ca82f0a12202 100644 (file)
@@ -259,8 +259,8 @@ typedef struct rpc_auth_ntlmssp_chal_info
 /* RPC_AUTH_NTLMSSP_RESP */
 typedef struct rpc_auth_ntlmssp_resp_info
 {
-       STRHDR hdr_lm_resp; /* 24 byte response */
-       STRHDR hdr_nt_resp; /* 24 byte response */
+       STRHDR hdr_lm_resp; /* LM response (NULL or 24 bytes) */
+       STRHDR hdr_nt_resp; /* NT response (NULL, 24 or variable-length) */
        STRHDR hdr_domain;
        STRHDR hdr_usr;
        STRHDR hdr_wks;
index 9821afdc1da1de5797e18cc3067b2ceb2a122ded..d3c0d42d972912a0f24e5ed201f61df43cd05d0f 100644 (file)
@@ -67,7 +67,8 @@ void hmac_md5_init_rfc2104(uchar*  key, int key_len, HMACMD5Context *ctx)
 /***********************************************************************
  the microsoft version of hmac_md5 initialisation.
 ***********************************************************************/
-void hmac_md5_init_limK_to_64(uchar*  key, int key_len, HMACMD5Context *ctx)
+void hmac_md5_init_limK_to_64(const uchar* key, int key_len,
+                       HMACMD5Context *ctx)
 {
         int i;
 
@@ -97,7 +98,7 @@ void hmac_md5_init_limK_to_64(uchar*  key, int key_len, HMACMD5Context *ctx)
 /***********************************************************************
  update hmac_md5 "inner" buffer
 ***********************************************************************/
-void hmac_md5_update(uchar* text, int text_len, HMACMD5Context *ctx)
+void hmac_md5_update(const uchar* text, int text_len, HMACMD5Context *ctx)
 {
         MD5Update(&ctx->ctx, text, text_len); /* then text of datagram */
 }
index 3211c6687ad5214cb3b2bdce886cde2ec9360bd3..9266e988d8372442c483ffdbe9edee62b1d2e0ea 100644 (file)
@@ -2972,7 +2972,7 @@ void out_data(FILE *f,char *buf1,int len, int per_line)
        }
 }
 
-void print_asc(int level, unsigned char *buf,int len)
+void print_asc(int level, unsigned char const *buf,int len)
 {
        int i;
        for (i=0;i<len;i++)
@@ -2981,9 +2981,9 @@ void print_asc(int level, unsigned char *buf,int len)
        }
 }
 
-void dump_data(int level,char *buf1, int len)
+void dump_data(int level, const char *buf1, int len)
 {
-       unsigned char *buf = (unsigned char *)buf1;
+       unsigned char const *buf = (unsigned char const *)buf1;
        int i=0;
        if (len<=0) return;
 
index 4f73b6e51b6c69f144f73e6d26d15803d6c87b17..8d3508d98fe92a10a7caa468e841cfaf911fca50 100644 (file)
@@ -2,7 +2,8 @@
    Unix SMB/Netbios implementation.
    Version 1.9.
    SMB client generic functions
-   Copyright (C) Andrew Tridgell 1994-1998
+   Copyright (C) Andrew Tridgell 1994-1999
+   Copyright (C) Luke Kenneth Casson Leighton 1996-1999
    
    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
@@ -690,70 +691,25 @@ prots[] =
 /****************************************************************************
 send a session setup 
 ****************************************************************************/
-BOOL cli_session_setup(struct cli_state *cli, 
-                      char *user, 
-                      char *pass, int passlen,
-                      char *ntpass, int ntpasslen,
-                      char *workgroup)
+BOOL cli_session_setup_x(struct cli_state *cli, 
+                               char *user, 
+                               char *pass, int passlen,
+                               char *ntpass, int ntpasslen,
+                               char *user_domain)
 {
        char *p;
-       fstring pword, ntpword;
+
+#ifdef DEBUG_PASSWORD
+       DEBUG(100,("cli_session_setup.  pass, ntpass\n"));
+       dump_data(100, pass, passlen);
+       dump_data(100, ntpass, ntpasslen);
+#endif
 
        if (cli->protocol < PROTOCOL_LANMAN1)
        {
                return True;
        }
 
-       if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1)
-       {
-               return False;
-       }
-
-       if (!IS_BITS_SET_ALL(cli->sec_mode, 1))
-       {
-               /* if in share level security then don't send a password now */
-               fstrcpy(pword, "");
-               passlen=1;
-               fstrcpy(ntpword, "");
-               ntpasslen=1;
-       } 
-       else if ((passlen == 0 || passlen == 1) && (pass[0] == '\0'))
-       {
-               /* Null session connect. */
-               pword  [0] = '\0';
-               ntpword[0] = '\0';
-       }
-       else if (passlen == 24 && ntpasslen == 24)
-       {
-               if (IS_BITS_SET_ALL(cli->sec_mode, 2))
-               {
-                       /* encrypted password, implicit from 24-byte lengths */
-                       memcpy(pword  , pass  , 24);
-                       memcpy(ntpword, ntpass, 24);
-               }
-               else
-               {
-                       DEBUG(0,("cli_session_setup: encrypted passwords not supported by server\n"));
-                       return False;
-               }
-       }
-       else if (ntpasslen == 0 || !IS_BITS_SET_ALL(cli->sec_mode, 2))
-       {
-               /* plain-text password: server doesn't support encrypted. */
-               fstrcpy(pword, pass);
-               fstrcpy(ntpword, "");
-               ntpasslen = 0;
-       }
-       else /* passlen != 0 && ntpasslen != 0 && server supports encryption */
-       {
-               /* plain-text password requesting to be encrypted */
-               uchar *key = (uchar *)cli->cryptkey;
-               SMBencrypt  ((uchar *)pass  , key,(uchar *)pword  );
-               SMBNTencrypt((uchar *)ntpass, key,(uchar *)ntpword);
-               passlen = 24;
-               ntpasslen = 24;
-       }
-
        /* send a session setup command */
        bzero(cli->outbuf,smb_size);
 
@@ -770,7 +726,7 @@ BOOL cli_session_setup(struct cli_state *cli,
                SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
                SSVAL(cli->outbuf,smb_vwv7,passlen);
                p = smb_buf(cli->outbuf);
-               memcpy(p,pword,passlen);
+               memcpy(p,pass,passlen);
                p += passlen;
                pstrcpy(p,user);
                strupper(p);
@@ -790,17 +746,17 @@ BOOL cli_session_setup(struct cli_state *cli,
                SSVAL(cli->outbuf,smb_vwv8,ntpasslen);
                SSVAL(cli->outbuf,smb_vwv11,0);
                p = smb_buf(cli->outbuf);
-               memcpy(p,pword,passlen); 
+               memcpy(p,pass,passlen); 
                p += SVAL(cli->outbuf,smb_vwv7);
-               memcpy(p,ntpword,ntpasslen); 
+               memcpy(p,ntpass,ntpasslen); 
                p += SVAL(cli->outbuf,smb_vwv8);
                pstrcpy(p,user);
                strupper(p);
                p = skip_string(p,1);
-               pstrcpy(p,workgroup);
-               strupper(p);
+               pstrcpy(p,user_domain);
                p = skip_string(p,1);
                pstrcpy(p,"Unix");p = skip_string(p,1);
+               CVAL(p, 0) = 0; p++;
                pstrcpy(p,"Samba");p = skip_string(p,1);
                set_message(cli->outbuf,13,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
        }
@@ -833,11 +789,127 @@ BOOL cli_session_setup(struct cli_state *cli,
         fstrcpy(cli->server_domain, server_domain);
       }
 
-      fstrcpy(cli->user_name, user);
-
       return True;
 }
 
+static BOOL cli_calc_session_pwds(struct cli_state *cli,
+                               char *pword, char *ntpword,
+                               char *pass, int *passlen,
+                               char *ntpass, int *ntpasslen,
+                               BOOL ntlmv2)
+{
+#ifdef DEBUG_PASSWORD
+       DEBUG(100,("cli_calc_session_pwds.  pass, ntpass\n"));
+       dump_data(100, pass, *passlen);
+       dump_data(100, ntpass, *ntpasslen);
+#endif
+       if (!IS_BITS_SET_ALL(cli->sec_mode, 1))
+       {
+               /* if in share level security then don't send a password now */
+               fstrcpy(pword, "");
+               *passlen=1;
+               fstrcpy(ntpword, "");
+               *ntpasslen=1;
+       } 
+       else if ((*passlen == 0 || *passlen == 1) && (pass[0] == '\0'))
+       {
+               /* Null session connect. */
+               pword  [0] = '\0';
+               ntpword[0] = '\0';
+       }
+       else if (*passlen == 24 && *ntpasslen >= 24)
+       {
+               if (IS_BITS_SET_ALL(cli->sec_mode, 2))
+               {
+                       /* encrypted password, implicit from 24-byte lengths */
+                       memcpy(pword  , pass  , *passlen);
+                       memcpy(ntpword, ntpass, *ntpasslen);
+               }
+               else
+               {
+                       DEBUG(0,("cli_session_setup: encrypted passwords not supported by server\n"));
+                       return False;
+               }
+       }
+       else if (*ntpasslen == 0 || !IS_BITS_SET_ALL(cli->sec_mode, 2))
+       {
+               /* plain-text password: server doesn't support encrypted. */
+               fstrcpy(pword, pass);
+               fstrcpy(ntpword, "");
+               *ntpasslen = 0;
+       }
+       else /* passlen != 0 && ntpasslen != 0 && server supports encryption */
+       {
+               if (ntlmv2)
+               {
+                       /* plain-text password requesting to be encrypted */
+                       uchar *srv_key = (uchar *)cli->cryptkey;
+                       uchar nt_owf[16];
+                       uchar kr[16];
+
+                       SMBgenclientchals(cli->lm_cli_chal,
+                                         cli->nt_cli_chal,
+                                         &cli->nt_cli_chal_len,
+                                         cli->calling.name,
+                                         cli->domain);
+                       
+                       nt_owf_gen(pword, nt_owf);
+                       ntv2_owf_gen(nt_owf, cli->user_name, cli->domain, kr);
+
+                       /* lm # */
+                       memcpy(pword, cli->lm_cli_chal, 8);
+                       SMBOWFencrypt_ntv2(kr,
+                                          srv_key, 8,
+                                          cli->lm_cli_chal, 8,
+                                          &pword[8]);
+                       *passlen = 24;
+
+                       /* nt # */
+                       memcpy(ntpword, cli->lm_cli_chal, cli->nt_cli_chal_len);
+                       SMBOWFencrypt_ntv2(kr,
+                                      srv_key, 8,
+                                      cli->nt_cli_chal, cli->nt_cli_chal_len,
+                                      &ntpword[cli->nt_cli_chal_len]);
+                       *ntpasslen = cli->nt_cli_chal_len + 16;
+               }
+               else
+               {
+                       /* plain-text password requesting to be encrypted */
+                       uchar *key = (uchar *)cli->cryptkey;
+                       SMBencrypt  ((uchar *)pass  , key,(uchar *)pword  );
+                       SMBNTencrypt((uchar *)ntpass, key,(uchar *)ntpword);
+                       *passlen = 24;
+                       *ntpasslen = 24;
+               }
+       }
+       return True;
+}
+
+/****************************************************************************
+send a session setup 
+****************************************************************************/
+BOOL cli_session_setup(struct cli_state *cli, 
+                               char *user, 
+                               char *pass, int passlen,
+                               char *ntpass, int ntpasslen,
+                               char *user_domain)
+{
+       fstring pword, ntpword;
+
+       if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1)
+       {
+               return False;
+       }
+
+       fstrcpy(cli->user_name, user);
+
+       return cli_calc_session_pwds(cli, pword, ntpword,
+                               pass, &passlen,
+                               ntpass, &ntpasslen, cli->use_ntlmv2) &&
+              cli_session_setup_x(cli, user, pass, passlen, ntpass, ntpasslen,
+                               user_domain);
+}
+
 /****************************************************************************
  Send a uloggoff.
 *****************************************************************************/
@@ -2614,9 +2686,12 @@ BOOL cli_reestablish_connection(struct cli_state *cli)
        if (cli_establish_connection(cli,
                                     dest_host, &cli->dest_ip,
                                     &calling, &called,
-                                    share, dev, False, do_tcon)) {
-               if (cli->fd != oldfd) {
-                       if (dup2(cli->fd, oldfd) == oldfd) {
+                                    share, dev, False, do_tcon))
+       {
+               if (cli->fd != oldfd)
+               {
+                       if (dup2(cli->fd, oldfd) == oldfd)
+                       {
                                close(cli->fd);
                        }
                }
@@ -2640,9 +2715,10 @@ BOOL cli_establish_connection(struct cli_state *cli,
        nmb_safe_namestr(calling, callingstr, sizeof(callingstr));
        nmb_safe_namestr(called , calledstr , sizeof(calledstr ));
 
-       DEBUG(5,("cli_establish_connection: %s connecting to %s (%s) - %s [%s]\n",
+       DEBUG(5,("cli_establish_connection: %s connecting to %s (%s) - %s [%s] with NTLM%s\n",
                          callingstr, calledstr, inet_ntoa(*dest_ip),
-                     cli->user_name, cli->domain));
+                     cli->user_name, cli->domain,
+                       cli->use_ntlmv2 ? "v2" : "v1"));
 
        /* establish connection */
 
@@ -2665,7 +2741,9 @@ BOOL cli_establish_connection(struct cli_state *cli,
        {
                DEBUG(1,("failed session request\n"));
                if (do_shutdown)
-          cli_shutdown(cli);
+               {
+                       cli_shutdown(cli);
+               }
                return False;
        }
 
@@ -2673,7 +2751,9 @@ BOOL cli_establish_connection(struct cli_state *cli,
        {
                DEBUG(1,("failed negprot\n"));
                if (do_shutdown)
-          cli_shutdown(cli);
+               {
+                       cli_shutdown(cli);
+               }
                return False;
        }
 
@@ -2725,20 +2805,45 @@ BOOL cli_establish_connection(struct cli_state *cli,
        else
        {
                /* attempt encrypted session */
-               unsigned char nt_sess_pwd[24];
                unsigned char lm_sess_pwd[24];
+               unsigned char nt_sess_pwd[128];
+               size_t nt_sess_pwd_len;
+               extern pstring global_myname;
+
+               if (cli->use_ntlmv2 != False)
+               {
+                       DEBUG(10,("cli_establish_connection: NTLMv2\n"));
+                       pwd_make_lm_nt_owf2(&(cli->pwd), cli->cryptkey,
+                                  cli->user_name, global_myname, cli->domain);
+               }
+               else
+               {
+                       DEBUG(10,("cli_establish_connection: NTLMv1\n"));
+                       pwd_make_lm_nt_owf(&(cli->pwd), cli->cryptkey);
+               }
 
-               /* creates (storing a copy of) and then obtains a 24 byte password OWF */
-               pwd_make_lm_nt_owf(&(cli->pwd), cli->cryptkey);
-               pwd_get_lm_nt_owf(&(cli->pwd), lm_sess_pwd, nt_sess_pwd);
+               pwd_get_lm_nt_owf(&(cli->pwd), lm_sess_pwd, nt_sess_pwd,
+                                 &nt_sess_pwd_len);
 
                /* attempt encrypted session */
-               if (!cli_session_setup(cli, cli->user_name,
+               if (!cli_session_setup_x(cli, cli->user_name,
                               (char*)lm_sess_pwd, sizeof(lm_sess_pwd),
-                              (char*)nt_sess_pwd, sizeof(nt_sess_pwd),
+                              (char*)nt_sess_pwd, nt_sess_pwd_len,
                               cli->domain))
                {
                        DEBUG(1,("failed session setup\n"));
+
+                       if (cli->use_ntlmv2 == Auto)
+                       {
+                               DEBUG(10,("NTLMv2 failed.  Using NTLMv1\n"));
+                               cli->use_ntlmv2 = False;
+                               return cli_establish_connection(cli, 
+                                       dest_host, dest_ip,
+                                       calling, called,
+                                       service, service_type,
+                                       do_shutdown, do_tcon);
+                       }
+                       
                        if (do_shutdown)
                        {
                                cli_shutdown(cli);
index bbd5f63d4b7dd6ac905133b09ce2ebbbcd90d96a..655df5be8ab0897095a1d717e46fdfaa7ab5d2ea 100644 (file)
@@ -197,27 +197,83 @@ void pwd_make_lm_nt_16(struct pwd_info *pwd, char *clr)
 /****************************************************************************
  makes lm and nt OWF crypts
  ****************************************************************************/
-void pwd_make_lm_nt_owf(struct pwd_info *pwd, uchar cryptkey[8])
+void pwd_make_lm_nt_owf2(struct pwd_info *pwd, const uchar srv_key[8],
+               const char *user, const char *server, const char *domain)
 {
+       uchar kr[16];
+
+       DEBUG(10,("pwd_make_lm_nt_owf2: user %s, srv %s, dom %s\n",
+               user, server, domain));
+
        pwd_deobfuscate(pwd);
 
+       SMBgenclientchals(pwd->lm_cli_chal,
+                         pwd->nt_cli_chal,
+                         &pwd->nt_cli_chal_len,
+                         server, domain);
+       
+       ntv2_owf_gen(pwd->smb_nt_pwd, user, domain, kr);
+
+       /* lm # */
+       SMBOWFencrypt_ntv2(kr,
+                          srv_key, 8,
+                          pwd->lm_cli_chal, 8,
+                          pwd->smb_lm_owf);
+       memcpy(&pwd->smb_lm_owf[16], pwd->lm_cli_chal, 8);
+
+       /* nt # */
+       SMBOWFencrypt_ntv2(kr,
+                      srv_key, 8,
+                      pwd->nt_cli_chal, pwd->nt_cli_chal_len,
+                      pwd->smb_nt_owf);
+       memcpy(&pwd->smb_nt_owf[16], pwd->nt_cli_chal, pwd->nt_cli_chal_len);
+       pwd->nt_owf_len = pwd->nt_cli_chal_len + 16;
+
 #ifdef DEBUG_PASSWORD
-       DEBUG(100,("client cryptkey: "));
-       dump_data(100, cryptkey, 8);
-#endif
+       DEBUG(100,("server cryptkey: "));
+       dump_data(100, srv_key, 8);
 
-       SMBOWFencrypt(pwd->smb_nt_pwd, cryptkey, pwd->smb_nt_owf);
+       DEBUG(100,("client lmv2 cryptkey: "));
+       dump_data(100, pwd->lm_cli_chal, 8);
 
-#ifdef DEBUG_PASSWORD
-       DEBUG(100,("nt_owf_passwd: "));
-       dump_data(100, pwd->smb_nt_owf, sizeof(pwd->smb_nt_owf));
+       DEBUG(100,("client ntv2 cryptkey: "));
+       dump_data(100, pwd->nt_cli_chal, pwd->nt_cli_chal_len);
+
+       DEBUG(100,("ntv2_owf_passwd: "));
+       dump_data(100, pwd->smb_nt_owf, pwd->nt_owf_len);
        DEBUG(100,("nt_sess_pwd: "));
        dump_data(100, pwd->smb_nt_pwd, sizeof(pwd->smb_nt_pwd));
+
+       DEBUG(100,("lmv2_owf_passwd: "));
+       dump_data(100, pwd->smb_lm_owf, sizeof(pwd->smb_lm_owf));
+       DEBUG(100,("lm_sess_pwd: "));
+       dump_data(100, pwd->smb_lm_pwd, sizeof(pwd->smb_lm_pwd));
 #endif
+       pwd->crypted = True;
+
+       pwd_obfuscate(pwd);
+}
+
+/****************************************************************************
+ makes lm and nt OWF crypts
+ ****************************************************************************/
+void pwd_make_lm_nt_owf(struct pwd_info *pwd, uchar cryptkey[8])
+{
+       pwd_deobfuscate(pwd);
 
        SMBOWFencrypt(pwd->smb_lm_pwd, cryptkey, pwd->smb_lm_owf);
+       SMBOWFencrypt(pwd->smb_nt_pwd, cryptkey, pwd->smb_nt_owf);
+       pwd->nt_owf_len = 24;
 
 #ifdef DEBUG_PASSWORD
+       DEBUG(100,("client cryptkey: "));
+       dump_data(100, cryptkey, 8);
+
+       DEBUG(100,("nt_owf_passwd: "));
+       dump_data(100, pwd->smb_nt_owf, pwd->nt_owf_len);
+       DEBUG(100,("nt_sess_pwd: "));
+       dump_data(100, pwd->smb_nt_pwd, sizeof(pwd->smb_nt_pwd));
+
        DEBUG(100,("lm_owf_passwd: "));
        dump_data(100, pwd->smb_lm_owf, sizeof(pwd->smb_lm_owf));
        DEBUG(100,("lm_sess_pwd: "));
@@ -232,7 +288,8 @@ void pwd_make_lm_nt_owf(struct pwd_info *pwd, uchar cryptkey[8])
 /****************************************************************************
  gets lm and nt crypts
  ****************************************************************************/
-void pwd_get_lm_nt_owf(struct pwd_info *pwd, uchar lm_owf[24], uchar nt_owf[24])
+void pwd_get_lm_nt_owf(struct pwd_info *pwd, uchar lm_owf[24],
+                               uchar *nt_owf, size_t *nt_owf_len)
 {
        pwd_deobfuscate(pwd);
        if (lm_owf != NULL)
@@ -241,7 +298,12 @@ void pwd_get_lm_nt_owf(struct pwd_info *pwd, uchar lm_owf[24], uchar nt_owf[24])
        }
        if (nt_owf != NULL)
        {
-               memcpy(nt_owf, pwd->smb_nt_owf, 24);
+               memcpy(nt_owf, pwd->smb_nt_owf, pwd->nt_owf_len);
+       }
+       if (nt_owf_len != NULL)
+       {
+               *nt_owf_len = pwd->nt_owf_len;
        }
        pwd_obfuscate(pwd);
 }
+
index f0bfbd9b843d0efd40517621186d12f89683f02f..852e5327cfa262b6f9c385db441f22e3567defad 100644 (file)
@@ -32,19 +32,30 @@ extern int DEBUGLEVEL;
    encrypted password into p24 */
 void SMBencrypt(uchar *passwd, uchar *c8, uchar *p24)
 {
-       uchar p14[15], p21[21];
+       uchar p21[21];
 
-       memset(p21,'\0',21);
-       memset(p14,'\0',14);
-       StrnCpy((char *)p14,(char *)passwd,14);
+       lm_owf_gen(passwd, p21);
+       SMBOWFencrypt(p21, c8, p24);
 
-       strupper((char *)p14);
-       E_P16(p14, p21); 
+#ifdef DEBUG_PASSWORD
+       DEBUG(100,("SMBencrypt: lm#, challenge, response\n"));
+       dump_data(100, p21, 16);
+       dump_data(100, c8, 8);
+       dump_data(100, p24, 24);
+#endif
+}
 
+void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24)
+{
+       uchar p21[21];
+       memset(p21,'\0',21);
+       nt_owf_gen(passwd, p21);    
        SMBOWFencrypt(p21, c8, p24);
 
 #ifdef DEBUG_PASSWORD
-       DEBUG(100,("SMBencrypt: lm#, challenge, response\n"));
+       DEBUG(100,("SMBNTencrypt: nt#, challenge, response\n"));
        dump_data(100, p21, 16);
        dump_data(100, c8, 8);
        dump_data(100, p24, 24);
@@ -67,7 +78,23 @@ static int _my_wcslen(int16 *str)
  * format.
  */
  
-static int _my_mbstowcs(int16 *dst, uchar *src, int len)
+static int _my_mbstowcsupper(int16 *dst, const uchar *src, int len)
+{
+       int i;
+       int16 val;
+       for(i = 0; i < len; i++) {
+               val = toupper(*src);
+               SSVAL(dst,0,val);
+               dst++;
+               src++;
+               if(val == 0)
+                       break;
+       }
+       return i;
+}
+
+static int _my_mbstowcs(int16 *dst, const uchar *src, int len)
 {
        int i;
        int16 val;
@@ -105,27 +132,17 @@ void E_md4hash(uchar *passwd, uchar *p16)
        mdfour(p16, (unsigned char *)wpwd, len);
 }
 
-/* Does both the NT and LM owfs of a user's password */
-void nt_lm_owf_gen(const char *pwd, uchar nt_p16[16], uchar p16[16])
+/* Does the LM owf of a user's password */
+void lm_owf_gen(const char *pwd, uchar p16[16])
 {
-       char passwd[130];
+       char passwd[15];
 
-       memset(passwd,'\0',130);
+       memset(passwd,'\0',15);
        if (pwd != NULL)
        {
                safe_strcpy( passwd, pwd, sizeof(passwd)-1);
        }
 
-       /* Calculate the MD4 hash (NT compatible) of the password */
-       memset(nt_p16, '\0', 16);
-       E_md4hash((uchar *)passwd, nt_p16);
-
-#ifdef DEBUG_PASSWORD
-       DEBUG(100,("nt_lm_owf_gen: pwd, nt#\n"));
-       dump_data(120, passwd, strlen(passwd));
-       dump_data(100, nt_p16, 16);
-#endif
-
        /* Mangle the passwords into Lanman format */
        passwd[14] = '\0';
        strupper(passwd);
@@ -144,6 +161,37 @@ void nt_lm_owf_gen(const char *pwd, uchar nt_p16[16], uchar p16[16])
        bzero(passwd, sizeof(passwd));
 }
 
+/* Does both the NT and LM owfs of a user's password */
+void nt_owf_gen(const char *pwd, uchar nt_p16[16])
+{
+       char passwd[130];
+
+       memset(passwd,'\0',130);
+       if (pwd != NULL)
+       {
+               safe_strcpy( passwd, pwd, sizeof(passwd)-1);
+       }
+
+       /* Calculate the MD4 hash (NT compatible) of the password */
+       memset(nt_p16, '\0', 16);
+       E_md4hash((uchar *)passwd, nt_p16);
+
+#ifdef DEBUG_PASSWORD
+       DEBUG(100,("nt_lm_owf_gen: pwd, nt#\n"));
+       dump_data(120, passwd, strlen(passwd));
+       dump_data(100, nt_p16, 16);
+#endif
+       /* clear out local copy of user's password (just being paranoid). */
+       bzero(passwd, sizeof(passwd));
+}
+
+/* Does both the NT and LM owfs of a user's password */
+void nt_lm_owf_gen(const char *pwd, uchar nt_p16[16], uchar lm_p16[16])
+{
+       nt_owf_gen(pwd, nt_p16);
+       lm_owf_gen(pwd, lm_p16);
+}
+
 /* Does the des encryption from the NT or LM MD4 hash. */
 void SMBOWFencrypt(uchar passwd[16], uchar *c8, uchar p24[24])
 {
@@ -155,6 +203,165 @@ void SMBOWFencrypt(uchar passwd[16], uchar *c8, uchar p24[24])
        E_P24(p21, c8, p24);
 }
 
+void SMBOWFencrypt_ntv2(const uchar kr[16], 
+                               const uchar *srv_chal, int srv_chal_len,
+                               const uchar *cli_chal, int cli_chal_len,
+                               char resp_buf[16])
+{
+       HMACMD5Context ctx;
+
+       hmac_md5_init_limK_to_64(kr, 16, &ctx);
+       hmac_md5_update(srv_chal, srv_chal_len, &ctx);
+       hmac_md5_update(cli_chal, cli_chal_len, &ctx);
+       hmac_md5_final(resp_buf, &ctx);
+
+#ifdef DEBUG_PASSWORD
+       DEBUG(100,("SMBOWFencrypt_ntv2: srv_chal, cli_chal, resp_buf\n"));
+       dump_data(100, srv_chal, srv_chal_len);
+       dump_data(100, cli_chal, cli_chal_len);
+       dump_data(100, resp_buf, 16);
+#endif
+}
+
+#if 0
+static char np_cli_chal[58] = 
+{
+       0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0xf0, 0x20, 0xd0, 0xb6, 0xc2, 0x92, 0xBE, 0x01,
+       0x05, 0x83, 0x32, 0xec, 0xfa, 0xe4, 0xf3, 0x6d,
+       0x6f, 0x00, 0x6e, 0x00, 0x02, 0x00, 0x12, 0x00,
+       0x52, 0x00, 0x4f, 0x00, 0x43, 0x00, 0x4b, 0x00,
+       0x4e, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x4c, 0x00,
+       0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00,
+       0x00, 0x00
+};
+#endif
+
+void SMBgenclientchals(char *lm_cli_chal,
+                               char *nt_cli_chal, int *nt_cli_chal_len,
+                               const char *srv, const char *domain)
+{
+       NTTIME nt_time;
+       int srv_len = strlen(srv);
+       int dom_len = strlen(domain);
+
+       generate_random_buffer(lm_cli_chal, 8, False);
+       unix_to_nt_time(&nt_time, time(NULL));
+
+       CVAL(nt_cli_chal,0) = 0x1;
+       CVAL(nt_cli_chal,1) = 0x1;
+       SSVAL(nt_cli_chal, 2, 0x0);
+       SIVAL(nt_cli_chal, 4, 0x0);
+       SIVAL(nt_cli_chal, 8, nt_time.low);
+       SIVAL(nt_cli_chal, 12, nt_time.high);
+       memcpy(nt_cli_chal+16, lm_cli_chal, 8);
+       /* fill in offset 24, size of structure, later */
+
+       *nt_cli_chal_len = 28;
+
+       SSVAL(nt_cli_chal, *nt_cli_chal_len, 2);
+       *nt_cli_chal_len += 2;
+       SSVAL(nt_cli_chal, *nt_cli_chal_len, dom_len*2);
+       *nt_cli_chal_len += 2;
+       ascii_to_unibuf(nt_cli_chal+(*nt_cli_chal_len), domain, dom_len*2);
+       *nt_cli_chal_len += dom_len*2;
+       *nt_cli_chal_len += 4 - ((*nt_cli_chal_len) % 4);
+
+       SSVAL(nt_cli_chal, *nt_cli_chal_len, 2);
+       *nt_cli_chal_len += 2;
+       SSVAL(nt_cli_chal, 30, srv_len*2);
+       *nt_cli_chal_len += 2;
+       ascii_to_unibuf(nt_cli_chal+(*nt_cli_chal_len), srv, srv_len*2);
+       *nt_cli_chal_len += srv_len*2;
+
+       SSVAL(nt_cli_chal, 24, (*nt_cli_chal_len)+16);
+       SSVAL(nt_cli_chal, 26, (*nt_cli_chal_len)+15);
+
+       DEBUG(100,("SMBgenclientchals: srv %s, dom %s\n", srv, domain));
+       dump_data(100, nt_cli_chal, *nt_cli_chal_len);
+}
+
+void ntv2_owf_gen(const uchar owf[16], 
+                               const char *user_n,
+                               const char *domain_n,
+                               uchar kr_buf[16])
+{
+       pstring user_u;
+       pstring dom_u;
+       HMACMD5Context ctx;
+
+       int user_l   = strlen(user_n  );
+       int domain_l = strlen(domain_n);
+
+       _my_mbstowcsupper((int16*)user_u, user_n  , user_l*2  );
+       _my_mbstowcs((int16*)dom_u , domain_n, domain_l*2);
+
+       hmac_md5_init_limK_to_64(owf, 16, &ctx);
+       hmac_md5_update(user_u, user_l*2, &ctx);
+       hmac_md5_update(dom_u, domain_l*2, &ctx);
+       hmac_md5_final(kr_buf, &ctx);
+
+#ifdef DEBUG_PASSWORD
+       DEBUG(100,("ntv2_owf_gen: user, domain, owfkey, kr\n"));
+       dump_data(100, user_u, user_l*2);
+       dump_data(100, dom_u, domain_l*2);
+       dump_data(100, owf, 16);
+       dump_data(100, kr_buf, 16);
+#endif
+}
+
+#if 0
+static void main()
+{
+       char *kr;
+       int kr_len;
+       char *cli_chal;
+       int cli_chal_len;
+       char *resp;
+       int resp_len;
+       char *k_x;
+       int k_x_len;
+
+       char k_u[16];
+       int k_u_len = sizeof(k_u);
+
+       char sesk[16];
+       int sesk_len;
+
+       char buf[1024];
+
+       int flgs = NTLMSSP_NP | NTLMSSP_N2;
+
+       gen_client_chal(flgs, "BROOKFIELDS1", "TEST1", &cli_chal, &cli_chal_len);
+       gen_owf(flgs, "test", "ADMINISTRATOR", "BROOKFIELDS1", &kr, &kr_len);
+       gen_resp(flgs, kr, kr_len, srv_chal, 8, cli_chal, cli_chal_len,
+                               &resp, &resp_len);
+
+       gen_sesskey(flgs, kr, kr_len, resp, resp_len, &k_x, &k_x_len);
+
+       printf("lm_resp:\n"); dump_data(lm_resp, 16); printf("\n");
+       printf("np_resp:\n"); dump_data(np_resp, 16); printf("\n");
+       printf("resp:\n"); dump_data(resp, 16); printf("\n");
+
+#if 0
+       printf("np_sesk:\n"); dump_data(np_sess_key, 16); printf("\n");
+       if (flgs & NTLMSSP_NP)
+       {
+               oem_hash(k_x, k_x_len, k_u, np_sess_key, k_u_len);
+               sesk_len = k_u_len;
+       }
+       else
+       {
+               memcpy(sesk, k_x, k_x_len);
+               sesk_len = k_x_len;
+       }
+
+       oem_hash(sesk, sesk_len, buf, cli_req, sizeof(cli_req));
+       printf("cli_req:\n"); dump_data(buf, sizeof(cli_req)); printf("\n");
+#endif
+}
+#endif
+
 /* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
 void NTLMSSPOWFencrypt(uchar passwd[8], uchar *ntlmchalresp, uchar p24[24])
 {
@@ -173,26 +380,6 @@ void NTLMSSPOWFencrypt(uchar passwd[8], uchar *ntlmchalresp, uchar p24[24])
 #endif
 }
 
-
-/* Does the NT MD4 hash then des encryption. */
-void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24)
-{
-       uchar p21[21];
-       memset(p21,'\0',21);
-       E_md4hash(passwd, p21);    
-       SMBOWFencrypt(p21, c8, p24);
-
-#ifdef DEBUG_PASSWORD
-       DEBUG(100,("SMBNTencrypt: nt#, challenge, response\n"));
-       dump_data(100, p21, 16);
-       dump_data(100, c8, 8);
-       dump_data(100, p24, 24);
-#endif
-}
-
 BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[16], BOOL unicode)
 {
        int new_pw_len = strlen(passwd) * (unicode ? 2 : 1);
index 34c405dd5024a6bea96e1c1b32b96aaa4d640841..7811d58afb44b500fb849a4d31b3370ac5d06771 100644 (file)
@@ -212,6 +212,7 @@ typedef struct
   BOOL bEncryptPasswords;
   BOOL bUpdateEncrypt;
   BOOL bServerNTLMv2;
+  BOOL bClientNTLMv2;
   BOOL bStripDot;
   BOOL bNullPasswords;
   BOOL bLoadPrinters;
@@ -530,7 +531,8 @@ static struct parm_struct parm_table[] =
   {"security",         P_ENUM,    P_GLOBAL, &Globals.security,          NULL,   enum_security, FLAG_BASIC},
   {"encrypt passwords",P_BOOL,    P_GLOBAL, &Globals.bEncryptPasswords, NULL,   NULL,  FLAG_BASIC},
   {"update encrypted", P_BOOL,    P_GLOBAL, &Globals.bUpdateEncrypt,    NULL,   NULL,  FLAG_BASIC},
-  {"server ntlmv2",    P_BOOL,    P_GLOBAL, &Globals.bServerNTLMv2,     NULL,   enum_bool_auto,  FLAG_BASIC},
+  {"server ntlmv2",    P_ENUM,    P_GLOBAL, &Globals.bServerNTLMv2,     NULL,   enum_bool_auto,  FLAG_BASIC},
+  {"client ntlmv2",    P_ENUM,    P_GLOBAL, &Globals.bClientNTLMv2,     NULL,   enum_bool_auto,  FLAG_BASIC},
   {"use rhosts",       P_BOOL,    P_GLOBAL, &Globals.bUseRhosts,        NULL,   NULL,  0},
   {"map to guest",     P_ENUM,    P_GLOBAL, &Globals.map_to_guest,      NULL,   enum_map_to_guest, 0},
   {"null passwords",   P_BOOL,    P_GLOBAL, &Globals.bNullPasswords,    NULL,   NULL,  0},
@@ -974,6 +976,7 @@ static void init_globals(void)
 
 /* NTLMv2 */
 
+  Globals.bClientNTLMv2 = False; 
   Globals.bServerNTLMv2 = False; 
 
 /* these parameters are set to defaults that are more appropriate
@@ -1250,7 +1253,8 @@ FN_GLOBAL_BOOL(lp_null_passwords,&Globals.bNullPasswords)
 FN_GLOBAL_BOOL(lp_strip_dot,&Globals.bStripDot)
 FN_GLOBAL_BOOL(lp_encrypted_passwords,&Globals.bEncryptPasswords)
 FN_GLOBAL_BOOL(lp_update_encrypted,&Globals.bUpdateEncrypt)
-FN_GLOBAL_BOOL(lp_server_ntlmv2,&Globals.bUpdateEncrypt)
+FN_GLOBAL_BOOL(lp_client_ntlmv2,&Globals.bClientNTLMv2)
+FN_GLOBAL_BOOL(lp_server_ntlmv2,&Globals.bServerNTLMv2)
 FN_GLOBAL_BOOL(lp_syslog_only,&Globals.bSyslogOnly)
 FN_GLOBAL_BOOL(lp_timestamp_logs,&Globals.bTimestampLogs)
 FN_GLOBAL_BOOL(lp_browse_list,&Globals.bBrowseList)
index d5b395a0a180ba35bd6bfb5923824f82b1154363..497ea344d14a387ee66988c543a8303ed5d57dba 100644 (file)
@@ -531,7 +531,6 @@ void copy_sam_passwd(struct sam_passwd *to, const struct sam_passwd *from)
 /*************************************************************
  converts a sam_passwd structure to a smb_passwd structure.
  **************************************************************/
-
 struct smb_passwd *pwdb_sam_to_smb(struct sam_passwd *user)
 {
        static struct smb_passwd pw_buf;
index 482dbe71cebd9df9ad37b4519de5a37ad6a41311..3ced2362818bf473c7864c62e87f1a7ad99d7ae3 100644 (file)
@@ -502,7 +502,8 @@ static BOOL create_rpc_bind_resp(struct pwd_info *pwd,
                                 prs_struct *auth_resp)
 {
        unsigned char lm_owf[24];
-       unsigned char nt_owf[24];
+       unsigned char nt_owf[128];
+       size_t nt_owf_len;
        RPC_HDR               hdr;
        RPC_HDR_AUTHA         hdr_autha;
        RPC_AUTH_VERIFIER     auth_verifier;
@@ -518,10 +519,10 @@ static BOOL create_rpc_bind_resp(struct pwd_info *pwd,
        smb_io_rpc_auth_verifier("auth_verifier", &auth_verifier, auth_resp, 0);
        mem_realloc_data(auth_resp->data, auth_resp->offset);
 
-       pwd_get_lm_nt_owf(pwd, lm_owf, nt_owf);
+       pwd_get_lm_nt_owf(pwd, lm_owf, nt_owf, &nt_owf_len);
                        
        make_rpc_auth_ntlmssp_resp(&ntlmssp_resp,
-                                lm_owf, nt_owf,
+                                lm_owf, nt_owf, nt_owf_len,
                                 domain, user_name, my_name,
                                 ntlmssp_cli_flgs);
 
@@ -947,7 +948,7 @@ static BOOL rpc_pipe_bind(struct cli_state *cli, uint16 nt_pipe_fnum,
                                             rpc_call_id,
                                             &hdra, &hdr_autha, &auth_resp);
                                            
-                       pwd_get_lm_nt_owf(&cli->pwd, lm_owf, NULL);
+                       pwd_get_lm_nt_owf(&cli->pwd, lm_owf, NULL, NULL);
                        pwd_get_lm_nt_16(&cli->pwd, lm_hash, NULL);
                        NTLMSSPOWFencrypt(lm_hash, lm_owf, p24);
                        {
index 524c4201ad57d442e420fdc06478071eebe15782..3066d94decf17aa150f99f39cf467b607542f693 100644 (file)
@@ -692,7 +692,8 @@ creates an RPC_AUTH_NTLMSSP_RESP structure.
 
 ********************************************************************/
 void make_rpc_auth_ntlmssp_resp(RPC_AUTH_NTLMSSP_RESP *rsp,
-                               uchar lm_resp[24], uchar nt_resp[24],
+                               uchar lm_resp[24],
+                               uchar *nt_resp, size_t nt_len,
                                char *domain, char *user, char *wks,
                                uint32 neg_flags)
 {
@@ -701,7 +702,6 @@ void make_rpc_auth_ntlmssp_resp(RPC_AUTH_NTLMSSP_RESP *rsp,
        int wks_len = strlen(wks   );
        int usr_len = strlen(user  );
        int lm_len  = lm_resp != NULL ? 24 : 0;
-       int nt_len  = nt_resp != NULL ? 24 : 0;
 
        DEBUG(5,("make_rpc_auth_ntlmssp_resp\n"));
 
@@ -709,9 +709,9 @@ void make_rpc_auth_ntlmssp_resp(RPC_AUTH_NTLMSSP_RESP *rsp,
 
 #ifdef DEBUG_PASSWORD
        DEBUG(100,("lm_resp\n"));
-       dump_data(100, lm_resp, 24);
+       dump_data(100, lm_resp, lm_len);
        DEBUG(100,("nt_resp\n"));
-       dump_data(100, nt_resp, 24);
+       dump_data(100, nt_resp, nt_len);
 #endif
 
        DEBUG(6,("dom: %s user: %s wks: %s neg_flgs: 0x%x\n",
@@ -745,8 +745,8 @@ void make_rpc_auth_ntlmssp_resp(RPC_AUTH_NTLMSSP_RESP *rsp,
 
        rsp->neg_flags = neg_flags;
 
-       memcpy(rsp->lm_resp, lm_resp, 24);
-       memcpy(rsp->nt_resp, nt_resp, 24);
+       memcpy(rsp->lm_resp, lm_resp, lm_len);
+       memcpy(rsp->nt_resp, nt_resp, nt_len);
 
        if (IS_BITS_SET_ALL(neg_flags, NTLMSSP_NEGOTIATE_UNICODE))
        {
index 7ee45ada16ca4bec7aa27e12fdf692d40b09b173..9c260d57591ad675f5d4565047b9c9596764ed6b 100644 (file)
@@ -630,43 +630,26 @@ static uint32 net_login_network(NET_ID_INFO_2 *id2,
                                struct sam_passwd *smb_pass,
                                user_struct *vuser)
 {
-       DEBUG(5,("net_login_network: lm_len: %d nt_len: %d\n",
-               id2->hdr_lm_chal_resp.str_str_len, 
-               id2->hdr_nt_chal_resp.str_str_len));
+       fstring user;
+       fstring domain;
 
-       /* JRA. Check the NT password first if it exists - this is a higher quality 
-           password, if it exists and it doesn't match - fail. */
+       int nt_pw_len = id2->hdr_nt_chal_resp.str_str_len >= 24;
+       int lm_pw_len = id2->hdr_lm_chal_resp.str_str_len >= 24;
 
-       if (id2->hdr_nt_chal_resp.str_str_len == 24 && 
-               smb_pass->smb_nt_passwd != NULL)
-       {
-               if(smb_password_check((char *)id2->nt_chal_resp.buffer,
-                                  smb_pass->smb_nt_passwd,
-                           id2->lm_chal)) 
-                  return 0x0;
-                else
-                 return 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
-       }
+       unistr2_to_ascii(user  , &id2->uni_user_name, sizeof(user)-1);
+       unistr2_to_ascii(domain, &id2->uni_domain_name, sizeof(domain)-1);
+
+       DEBUG(5,("net_login_network: lm_len:%d nt_len:%d user:%s domain:%s\n",
+               lm_pw_len, nt_pw_len, user, domain));
 
-       /* lkclXXXX this is not a good place to put disabling of LM hashes in.
-          if that is to be done, first move this entire function into a
-          library routine that calls the two smb_password_check() functions.
-          if disabling LM hashes (which nt can do for security reasons) then
-          an attempt should be made to disable them everywhere (which nt does
-          not do, for various security-hole reasons).
-        */
-
-       if (id2->hdr_lm_chal_resp.str_str_len == 24 &&
-               smb_password_check((char *)id2->lm_chal_resp.buffer,
-                                  smb_pass->smb_passwd,
-                                  id2->lm_chal))
+       if (smb_password_ok(pwdb_sam_to_smb(smb_pass), id2->lm_chal, 
+                           user, domain,
+                           (uchar *)id2->lm_chal_resp.buffer, lm_pw_len, 
+                           (uchar *)id2->nt_chal_resp.buffer, nt_pw_len)) 
        {
-               return 0x0;
+                  return 0x0;
        }
 
-
-       /* oops! neither password check succeeded */
-
        return 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
 }
 
index d98fecbc1fab0c1f88ba4a6557b225535615f727..3e5d98693513c5c462460f482e61be8f61cdf725 100644 (file)
@@ -208,7 +208,9 @@ BOOL create_rpc_reply(pipes_struct *p,
 static BOOL api_pipe_ntlmssp_verify(pipes_struct *p)
 {
        uchar lm_owf[24];
-       uchar nt_owf[24];
+       uchar nt_owf[128];
+       size_t lm_owf_len;
+       size_t nt_owf_len;
        struct smb_passwd *smb_pass = NULL;
        
        user_struct *vuser = get_valid_user_struct(p->vuid);
@@ -221,12 +223,29 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p)
                return False;
        }
 
-       if (p->ntlmssp_resp.hdr_lm_resp.str_str_len == 0) return False;
-       if (p->ntlmssp_resp.hdr_nt_resp.str_str_len == 0) return False;
+       lm_owf_len = p->ntlmssp_resp.hdr_lm_resp.str_str_len;
+       nt_owf_len = p->ntlmssp_resp.hdr_nt_resp.str_str_len;
+
+
+       if (lm_owf_len == 0) return False;
+       if (nt_owf_len == 0) return False;
        if (p->ntlmssp_resp.hdr_usr    .str_str_len == 0) return False;
        if (p->ntlmssp_resp.hdr_domain .str_str_len == 0) return False;
        if (p->ntlmssp_resp.hdr_wks    .str_str_len == 0) return False;
 
+       if (lm_owf_len > sizeof(lm_owf)) return False;
+       if (nt_owf_len > sizeof(nt_owf)) return False;
+
+       memcpy(lm_owf, p->ntlmssp_resp.lm_resp, sizeof(lm_owf));
+       memcpy(nt_owf, p->ntlmssp_resp.nt_resp, sizeof(nt_owf));
+
+#ifdef DEBUG_PASSWORD
+       DEBUG(100,("lm, nt owfs, chal\n"));
+       dump_data(100, lm_owf, sizeof(lm_owf));
+       dump_data(100, nt_owf, sizeof(nt_owf));
+       dump_data(100, p->ntlmssp_chal.challenge, 8);
+#endif
+
        memset(p->user_name, 0, sizeof(p->user_name));
        memset(p->domain   , 0, sizeof(p->domain   ));
        memset(p->wks      , 0, sizeof(p->wks      ));
@@ -252,19 +271,12 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p)
 
        DEBUG(5,("user: %s domain: %s wks: %s\n", p->user_name, p->domain, p->wks));
 
-       memcpy(lm_owf, p->ntlmssp_resp.lm_resp, sizeof(lm_owf));
-       memcpy(nt_owf, p->ntlmssp_resp.nt_resp, sizeof(nt_owf));
-
-#ifdef DEBUG_PASSWORD
-       DEBUG(100,("lm, nt owfs, chal\n"));
-       dump_data(100, lm_owf, sizeof(lm_owf));
-       dump_data(100, nt_owf, sizeof(nt_owf));
-       dump_data(100, p->ntlmssp_chal.challenge, 8);
-#endif
        become_root(True);
        p->ntlmssp_validated = pass_check_smb(p->user_name, p->domain,
                              (uchar*)p->ntlmssp_chal.challenge,
-                             lm_owf, nt_owf, NULL, vuser->dc.user_sess_key);
+                             lm_owf, lm_owf_len,
+                             nt_owf, nt_owf_len,
+                             NULL, vuser->dc.user_sess_key);
        smb_pass = getsmbpwnam(p->user_name);
        unbecome_root(True);
 
index 259c10d11f3a32e4c5ed772e52a216ace064add5..25308697a63eb54064580e8c2a053f8a36a2916d 100644 (file)
@@ -72,6 +72,8 @@ static BOOL rpcclient_connect(struct client_info *info)
        make_nmb_name(&called , dns_to_netbios_name(info->dest_host ), info->name_type, scope);
        make_nmb_name(&calling, dns_to_netbios_name(info->myhostname), 0x0            , scope);
 
+       smb_cli->use_ntlmv2 = lp_client_ntlmv2();
+
        if (!cli_establish_connection(smb_cli, 
                                  info->dest_host, &info->dest_ip, 
                                  &calling, &called,
index c05b82ef1503a6b72c0c283c8cd33982608a00f3..14a63c6ef43b26d52d0162f435cbe9327935b223 100644 (file)
@@ -292,51 +292,78 @@ static BOOL update_smbpassword_file(char *user, char *password)
 /****************************************************************************
 core of smb password checking routine.
 ****************************************************************************/
-BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned char *c8)
+static BOOL smb_pwd_check_ntlmv1(char *password, unsigned char *part_passwd,
+                               unsigned char *c8)
 {
   /* Finish the encryption of part_passwd. */
-  unsigned char p21[21];
   unsigned char p24[24];
 
   if (part_passwd == NULL)
     DEBUG(10,("No password set - allowing access\n"));
   /* No password set - always true ! */
   if (part_passwd == NULL)
-    return 1;
+    return True;
 
-  memset(p21,'\0',21);
-  memcpy(p21,part_passwd,16);
-  E_P24(p21, c8, p24);
+  SMBOWFencrypt(part_passwd, c8, p24);
 #if DEBUG_PASSWORD
-  {
-    int i;
-    DEBUG(100,("Part password (P16) was |"));
-    for(i = 0; i < 16; i++)
-      DEBUG(100,("%X ", (unsigned char)part_passwd[i]));
-    DEBUG(100,("|\n"));
-    DEBUG(100,("Password from client was |"));
-    for(i = 0; i < 24; i++)
-      DEBUG(100,("%X ", (unsigned char)password[i]));
-    DEBUG(100,("|\n"));
-    DEBUG(100,("Given challenge was |"));
-    for(i = 0; i < 8; i++)
-      DEBUG(100,("%X ", (unsigned char)c8[i]));
-    DEBUG(100,("|\n"));
-    DEBUG(100,("Value from encryption was |"));
-    for(i = 0; i < 24; i++)
-      DEBUG(100,("%X ", (unsigned char)p24[i]));
-    DEBUG(100,("|\n"));
-  }
+       DEBUG(100,("Part password (P16) was |"));
+       dump_data(100, part_passwd, 16);
+       DEBUG(100,("Password from client was |"));
+       dump_data(100, password, 24);
+       DEBUG(100,("Given challenge was |"));
+       dump_data(100, c8, 8);
+       DEBUG(100,("Value from encryption was |"));
+       dump_data(100, p24, 24);
 #endif
   return (memcmp(p24, password, 24) == 0);
 }
 
+/****************************************************************************
+core of smb password checking routine.
+****************************************************************************/
+static BOOL smb_pwd_check_ntlmv2(char *password, size_t pwd_len,
+                               unsigned char *part_passwd,
+                               unsigned char const *c8,
+                               const char *user, const char *domain)
+{
+       /* Finish the encryption of part_passwd. */
+       unsigned char kr[16];
+
+       if (part_passwd == NULL)
+       {
+               DEBUG(10,("No password set - allowing access\n"));
+       }
+       /* No password set - always true ! */
+       if (part_passwd == NULL)
+       {
+               return True;
+       }
+
+       ntv2_owf_gen(part_passwd, user, domain, kr);
+       SMBOWFencrypt_ntv2(kr, c8, 8, password+16, pwd_len-16, kr);
+
+#if DEBUG_PASSWORD
+       DEBUG(100,("Part password (P16) was |"));
+       dump_data(100, part_passwd, 16);
+       DEBUG(100,("Password from client was |"));
+       dump_data(100, password, pwd_len);
+       DEBUG(100,("Given challenge was |"));
+       dump_data(100, c8, 8);
+       DEBUG(100,("Value from encryption was |"));
+       dump_data(100, kr, 16);
+#endif
+
+       return (memcmp(kr, password, 16) == 0);
+}
+
 /****************************************************************************
  Do a specific test for an smb password being correct, given a smb_password and
  the lanman and NT responses.
 ****************************************************************************/
 BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8],
-                     uchar lm_pass[24], uchar nt_pass[24])
+                               const char *user, const char *domain,
+                               uchar *lm_pass, size_t lm_pwd_len,
+                               uchar *nt_pass, size_t nt_pwd_len)
 {
        uchar challenge[8];
 
@@ -345,7 +372,8 @@ BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8],
        DEBUG(4,("Checking SMB password for user %s\n", 
                 smb_pass->unix_name));
 
-       if(smb_pass->acct_ctrl & ACB_DISABLED) {
+       if (smb_pass->acct_ctrl & ACB_DISABLED)
+       {
                DEBUG(3,("account for user %s was disabled.\n", 
                         smb_pass->unix_name));
                return(False);
@@ -366,35 +394,59 @@ BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8],
                memcpy(challenge, chal, 8);
        }
 
-       if ((Protocol >= PROTOCOL_NT1) && (smb_pass->smb_nt_passwd != NULL)) {
+       if ((Protocol >= PROTOCOL_NT1) && (smb_pass->smb_nt_passwd != NULL))
+       {
                /* We have the NT MD4 hash challenge available - see if we can
                   use it (ie. does it exist in the smbpasswd file).
                */
-               DEBUG(4,("smb_password_ok: Checking NT MD4 password\n"));
-               if (smb_password_check((char *)nt_pass, 
+               if (lp_server_ntlmv2())
+               {
+                       DEBUG(4,("smb_password_ok: Check NTLMv2 password\n"));
+                       if (smb_pwd_check_ntlmv2(nt_pass, nt_pwd_len,
+                                      (uchar *)smb_pass->smb_nt_passwd, 
+                                       challenge, user, domain))
+                       {
+                               return True;
+                       }
+               }
+               if (lp_server_ntlmv2() != True && nt_pwd_len == 24)
+               {
+                       DEBUG(4,("smb_password_ok: Check NT MD4 password\n"));
+                       if (smb_pwd_check_ntlmv1((char *)nt_pass, 
                                       (uchar *)smb_pass->smb_nt_passwd, 
-                                      challenge)) {
-                       DEBUG(4,("NT MD4 password check succeeded\n"));
-                       return(True);
+                                      challenge))
+                       {
+                               DEBUG(4,("NT MD4 password check succeeded\n"));
+                               return True;
+                       }
                }
                DEBUG(4,("NT MD4 password check failed\n"));
        }
 
+       if (lp_server_ntlmv2() == False)
+       {
+               DEBUG(4,("Not checking LM MD4 password\n"));
+               return False;
+       }
+
        /* Try against the lanman password. smb_pass->smb_passwd == NULL means
           no password, allow access. */
 
        DEBUG(4,("Checking LM MD4 password\n"));
 
-       if((smb_pass->smb_passwd == NULL) && 
-          (smb_pass->acct_ctrl & ACB_PWNOTREQ)) {
+       if ((smb_pass->smb_passwd == NULL) && 
+          (smb_pass->acct_ctrl & ACB_PWNOTREQ))
+       {
                DEBUG(4,("no password required for user %s\n",
                         smb_pass->unix_name));
                return True;
        }
 
-       if((smb_pass->smb_passwd != NULL) && 
-          smb_password_check((char *)lm_pass, 
-                             (uchar *)smb_pass->smb_passwd, challenge)) {
+       if ((smb_pass->smb_passwd != NULL) && 
+          smb_pwd_check_ntlmv1((char *)lm_pass, 
+                             (uchar *)smb_pass->smb_passwd,
+                               challenge))
+       {
                DEBUG(4,("LM MD4 password check succeeded\n"));
                return(True);
        }
@@ -411,8 +463,9 @@ SMB hash
 return True if the password is correct, False otherwise
 ****************************************************************************/
 
-BOOL pass_check_smb(char *user, char *domain,
-               uchar *chal, uchar *lm_pwd, uchar *nt_pwd,
+BOOL pass_check_smb(char *user, char *domain, uchar *chal,
+               uchar *lm_pwd, size_t lm_pwd_len,
+               uchar *nt_pwd, size_t nt_pwd_len,
                struct passwd *pwd, uchar user_sess_key[16])
 {
        const struct passwd *pass;
@@ -466,7 +519,9 @@ BOOL pass_check_smb(char *user, char *domain,
                return(True);
        }
 
-       if (smb_password_ok(smb_pass, chal, lm_pwd, nt_pwd))
+       if (smb_password_ok(smb_pass, chal, user, domain,
+                                           lm_pwd, lm_pwd_len,
+                                           nt_pwd, nt_pwd_len))
        {
                if (user_sess_key != NULL)
                {
@@ -479,7 +534,7 @@ BOOL pass_check_smb(char *user, char *domain,
                return(True);
        }
        
-       DEBUG(3,("Error smb_password_check failed\n"));
+       DEBUG(3,("Error pass_check_smb failed\n"));
        return False;
 }
 
@@ -491,9 +546,9 @@ return True if the password is correct, False otherwise
 BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd,
                uchar user_sess_key[16])
 {
-       if (pwlen == 24 || (lp_encrypted_passwords() && (pwlen == 0) && lp_null_passwords()))
+       if (pwlen >= 24 || (lp_encrypted_passwords() && (pwlen == 0) && lp_null_passwords()))
        {
-               /* if 24 bytes long assume it is an encrypted password */
+               /* if 24 bytes or longer assume it is an encrypted password */
                uchar challenge[8];
 
                if (!last_challenge(challenge))
@@ -503,7 +558,9 @@ BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd,
                }
 
                return pass_check_smb(user, global_myworkgroup,
-                                     challenge, (uchar *)password, (uchar *)password, pwd, user_sess_key);
+                                     challenge, (uchar *)password,
+                                       pwlen, (uchar *)password, pwlen,
+                                       pwd, user_sess_key);
        } 
 
        return pass_check(user, password, pwlen, pwd, 
index 58f327771d66474850542d164670d17271f50d41..c44cf069a9a93632ad18fcf96ed9d86d402a8096 100644 (file)
@@ -441,7 +441,9 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out
       return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
     }
 
-    if (!smb_password_ok(smb_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd))
+    if (!smb_password_ok(smb_trust_acct, NULL, NULL, NULL,
+       (unsigned char *)smb_passwd, smb_passlen,
+       (unsigned char *)smb_nt_passwd, smb_nt_passlen))
     {
       DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
       SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
@@ -570,7 +572,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int
         set_remote_arch( RA_WIN95);
     }
 
-    if (passlen1 != 24 && passlen2 != 24)
+    if (passlen1 != 24 && passlen2 <= 24)
       doencrypt = False;
 
     if (passlen1 > MAX_PASS_LEN) {
@@ -593,7 +595,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int
           setting passlen2 to some random value which really stuffs
           things up. we need to fix that one.  */
 
-      if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
+      if (passlen1 > 0 && passlen2 > 0 && passlen2 <= 24 && passlen2 != 1)
         passlen2 = 0;
     }
 
index becfd01504d92017e4861c59ca659d7e73c1b25d..232579a0f160f5117938ca02d54da5925a11533f 100644 (file)
@@ -390,10 +390,10 @@ connection_struct *make_connection(char *service,char *user,char *password, int
 #endif
        
        if (*lp_force_user(snum)) {
-               struct passwd *pass2;
+               const struct passwd *pass2;
                fstring fuser;
                fstrcpy(fuser,lp_force_user(snum));
-               pass2 = (struct passwd *)Get_Pwnam(fuser,True);
+               pass2 = (const struct passwd *)Get_Pwnam(fuser,True);
                if (pass2) {
                        conn->uid = pass2->pw_uid;
                        string_set(&conn->user,fuser);
index 86729c3d106fdb407b18d5e27538f9d7585158b8..ff98c0a837ee368d9ffd74bfc134da7c69b64b01 100644 (file)
@@ -113,6 +113,8 @@ static BOOL rpcclient_connect(struct client_info *info)
 {
        rpcclient_init();
 
+       smb_cli->use_ntlmv2 = lp_client_ntlmv2();
+
        if (!cli_establish_connection(smb_cli, 
                                  info->dest_host, &info->dest_ip, 
                                  &calling, &called,