s3-credentials: protect netlogon_creds_server_step() against NULL creds.
[ira/wip.git] / source3 / libsmb / credentials.c
index 975f9bca499e37e4d1f2777534028b27fb3faf2e..9dc0b9f01b24214323b87899e79e6202fbd57b08 100644 (file)
@@ -6,7 +6,7 @@
    
    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
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    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.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
+#include "../lib/crypto/crypto.h"
+#include "libcli/auth/libcli_auth.h"
 
 /****************************************************************************
  Represent a credential as a string.
 
 char *credstr(const unsigned char *cred)
 {
-       static fstring buf;
-       slprintf(buf, sizeof(buf) - 1, "%02X%02X%02X%02X%02X%02X%02X%02X",
-               cred[0], cred[1], cred[2], cred[3], 
-               cred[4], cred[5], cred[6], cred[7]);
-       return buf;
+       char *result;
+       result = talloc_asprintf(talloc_tos(),
+                                "%02X%02X%02X%02X%02X%02X%02X%02X",
+                                cred[0], cred[1], cred[2], cred[3],
+                                cred[4], cred[5], cred[6], cred[7]);
+       SMB_ASSERT(result != NULL);
+       return result;
 }
 
 /****************************************************************************
@@ -41,9 +44,9 @@ char *credstr(const unsigned char *cred)
 ****************************************************************************/
 
 static void creds_init_128(struct dcinfo *dc,
-                               const DOM_CHAL *clnt_chal_in,
-                               const DOM_CHAL *srv_chal_in,
-                               const char mach_pw[16])
+                          const struct netr_Credential *clnt_chal_in,
+                          const struct netr_Credential *srv_chal_in,
+                          const unsigned char mach_pw[16])
 {
        unsigned char zero[4], tmp[16];
        HMACMD5Context ctx;
@@ -93,15 +96,17 @@ static void creds_init_128(struct dcinfo *dc,
 ****************************************************************************/
 
 static void creds_init_64(struct dcinfo *dc,
-                       const DOM_CHAL *clnt_chal_in,
-                       const DOM_CHAL *srv_chal_in,
-                       const char mach_pw[16])
+                         const struct netr_Credential *clnt_chal_in,
+                         const struct netr_Credential *srv_chal_in,
+                         const unsigned char mach_pw[16])
 {
        uint32 sum[2];
        unsigned char sum2[8];
 
        /* Just in case this isn't already there */
-       memcpy(dc->mach_pw, mach_pw, 16);
+       if (dc->mach_pw != mach_pw) {
+               memcpy(dc->mach_pw, mach_pw, 16);
+       }
 
        sum[0] = IVAL(clnt_chal_in->data, 0) + IVAL(srv_chal_in->data, 0);
        sum[1] = IVAL(clnt_chal_in->data, 4) + IVAL(srv_chal_in->data, 4);
@@ -143,7 +148,7 @@ static void creds_init_64(struct dcinfo *dc,
 
 static void creds_step(struct dcinfo *dc)
 {
-       DOM_CHAL time_chal;
+       struct netr_Credential time_chal;
 
        DEBUG(5,("\tsequence = 0x%x\n", (unsigned int)dc->sequence ));
 
@@ -174,15 +179,15 @@ static void creds_step(struct dcinfo *dc)
 
 void creds_server_init(uint32 neg_flags,
                        struct dcinfo *dc,
-                       DOM_CHAL *clnt_chal,
-                       DOM_CHAL *srv_chal,
-                       const char mach_pw[16],
-                       DOM_CHAL *init_chal_out)
+                       struct netr_Credential *clnt_chal,
+                       struct netr_Credential *srv_chal,
+                       const unsigned char mach_pw[16],
+                       struct netr_Credential *init_chal_out)
 {
        DEBUG(10,("creds_server_init: neg_flags : %x\n", (unsigned int)neg_flags));
        DEBUG(10,("creds_server_init: client chal : %s\n", credstr(clnt_chal->data) ));
        DEBUG(10,("creds_server_init: server chal : %s\n", credstr(srv_chal->data) ));
-       dump_data_pw("creds_server_init: machine pass", (const unsigned char *)mach_pw, 16);
+       dump_data_pw("creds_server_init: machine pass", mach_pw, 16);
 
        /* Generate the session key and the next client and server creds. */
        if (neg_flags & NETLOGON_NEG_128BIT) {
@@ -210,25 +215,28 @@ void creds_server_init(uint32 neg_flags,
  Check a credential sent by the client.
 ****************************************************************************/
 
-BOOL creds_server_check(const struct dcinfo *dc, const DOM_CHAL *rcv_cli_chal_in)
+bool netlogon_creds_server_check(const struct dcinfo *dc,
+                                const struct netr_Credential *rcv_cli_chal_in)
 {
        if (memcmp(dc->clnt_chal.data, rcv_cli_chal_in->data, 8)) {
-               DEBUG(5,("creds_server_check: challenge : %s\n", credstr(rcv_cli_chal_in->data)));
+               DEBUG(5,("netlogon_creds_server_check: challenge : %s\n",
+                       credstr(rcv_cli_chal_in->data)));
                DEBUG(5,("calculated: %s\n", credstr(dc->clnt_chal.data)));
-               DEBUG(2,("creds_server_check: credentials check failed.\n"));
-               return False;
+               DEBUG(2,("netlogon_creds_server_check: credentials check failed.\n"));
+               return false;
        }
-       DEBUG(10,("creds_server_check: credentials check OK.\n"));
-       return True;
-}
 
+       DEBUG(10,("netlogon_creds_server_check: credentials check OK.\n"));
+
+       return true;
+}
 /****************************************************************************
  Replace current seed chal. Internal function - due to split server step below.
 ****************************************************************************/
 
 static void creds_reseed(struct dcinfo *dc)
 {
-       DOM_CHAL time_chal;
+       struct netr_Credential time_chal;
 
        SIVAL(time_chal.data, 0, IVAL(dc->seed_chal.data, 0) + dc->sequence + 1);
        SIVAL(time_chal.data, 4, IVAL(dc->seed_chal.data, 4));
@@ -242,103 +250,46 @@ static void creds_reseed(struct dcinfo *dc)
  Step the server credential chain one forward. 
 ****************************************************************************/
 
-BOOL creds_server_step(struct dcinfo *dc, const DOM_CRED *received_cred, DOM_CRED *cred_out)
+bool netlogon_creds_server_step(struct dcinfo *dc,
+                               const struct netr_Authenticator *received_cred,
+                               struct netr_Authenticator *cred_out)
 {
-       BOOL ret;
+       bool ret;
        struct dcinfo tmp_dc = *dc;
 
+       if (!received_cred || !cred_out) {
+               return false;
+       }
+
        /* Do all operations on a temporary copy of the dc,
           which we throw away if the checks fail. */
 
-       tmp_dc.sequence = received_cred->timestamp.time;
+       tmp_dc.sequence = received_cred->timestamp;
 
        creds_step(&tmp_dc);
 
        /* Create the outgoing credentials */
-       cred_out->timestamp.time = tmp_dc.sequence + 1;
-       cred_out->challenge = tmp_dc.srv_chal;
+       cred_out->timestamp = tmp_dc.sequence + 1;
+       memcpy(&cred_out->cred, &tmp_dc.srv_chal, sizeof(cred_out->cred));
 
        creds_reseed(&tmp_dc);
 
-       ret = creds_server_check(&tmp_dc, &received_cred->challenge);
+       ret = netlogon_creds_server_check(&tmp_dc, &received_cred->cred);
        if (!ret) {
-               return False;
+               return false;
        }
 
        /* creds step succeeded - replace the current creds. */
        *dc = tmp_dc;
-       return True;
-}
-
-/****************************************************************************
- Create a client credential struct.
-****************************************************************************/
-
-void creds_client_init(uint32 neg_flags,
-                       struct dcinfo *dc,
-                       DOM_CHAL *clnt_chal,
-                       DOM_CHAL *srv_chal,
-                       const unsigned char mach_pw[16],
-                       DOM_CHAL *init_chal_out)
-{
-       dc->sequence = time(NULL);
-
-       DEBUG(10,("creds_client_init: neg_flags : %x\n", (unsigned int)neg_flags));
-       DEBUG(10,("creds_client_init: client chal : %s\n", credstr(clnt_chal->data) ));
-       DEBUG(10,("creds_client_init: server chal : %s\n", credstr(srv_chal->data) ));
-       dump_data_pw("creds_client_init: machine pass", (const unsigned char *)mach_pw, 16);
-
-       /* Generate the session key and the next client and server creds. */
-       if (neg_flags & NETLOGON_NEG_128BIT) {
-               creds_init_128(dc,
-                               clnt_chal,
-                               srv_chal,
-                               mach_pw);
-       } else {
-               creds_init_64(dc,
-                       clnt_chal,
-                       srv_chal,
-                       mach_pw);
-       }
-
-       dump_data_pw("creds_client_init: session key", dc->sess_key, 16);
-
-       DEBUG(10,("creds_client_init: clnt : %s\n", credstr(dc->clnt_chal.data) ));
-       DEBUG(10,("creds_client_init: server : %s\n", credstr(dc->srv_chal.data) ));
-       DEBUG(10,("creds_client_init: seed : %s\n", credstr(dc->seed_chal.data) ));
-
-       memcpy(init_chal_out->data, dc->clnt_chal.data, 8);
+       return true;
 }
 
-/****************************************************************************
- Check a credential returned by the server.
-****************************************************************************/
-
-BOOL creds_client_check(const struct dcinfo *dc, const DOM_CHAL *rcv_srv_chal_in)
-{
-       if (memcmp(dc->srv_chal.data, rcv_srv_chal_in->data, 8)) {
-               DEBUG(5,("creds_client_check: challenge : %s\n", credstr(rcv_srv_chal_in->data)));
-               DEBUG(5,("calculated: %s\n", credstr(dc->srv_chal.data)));
-               DEBUG(0,("creds_client_check: credentials check failed.\n"));
-               return False;
-       }
-       DEBUG(10,("creds_client_check: credentials check OK.\n"));
-       return True;
-}
-
-/****************************************************************************
-  Step the client credentials to the next element in the chain, updating the
-  current client and server credentials and the seed
-  produce the next authenticator in the sequence ready to send to
-  the server
-****************************************************************************/
-
-void creds_client_step(struct dcinfo *dc, DOM_CRED *next_cred_out)
+void cred_hash3(unsigned char *out, const unsigned char *in, const unsigned char *key, int forw)
 {
-        dc->sequence += 2;
-       creds_step(dc);
-       creds_reseed(dc);
+        unsigned char key2[8];
 
-       next_cred_out->challenge = dc->clnt_chal;
-       next_cred_out->timestamp.time = dc->sequence;
+       memset(key2,'\0',8);
+        des_crypt56(out, in, key, forw);
+        key2[0] = key[7];
+        des_crypt56(out + 8, in + 8, key2, forw);
 }