s3-credentials: protect netlogon_creds_server_step() against NULL creds.
[ira/wip.git] / source3 / libsmb / credentials.c
index 973bb6ad28cd89b2ea86bf7f29822a338dd90893..9dc0b9f01b24214323b87899e79e6202fbd57b08 100644 (file)
@@ -19,6 +19,8 @@
 */
 
 #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;
 }
 
 /****************************************************************************
@@ -40,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 unsigned 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;
@@ -92,9 +96,9 @@ 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 unsigned 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];
@@ -144,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 ));
 
@@ -175,10 +179,10 @@ 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,
+                       struct netr_Credential *clnt_chal,
+                       struct netr_Credential *srv_chal,
                        const unsigned char mach_pw[16],
-                       DOM_CHAL *init_chal_out)
+                       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) ));
@@ -211,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));
@@ -243,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;
        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;
+       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);
-}
-
-/****************************************************************************
- 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);
 }