Procházet zdrojové kódy

Use smb_buffer in smb_ntlm.c whenever possible

Julien 'Lta' BALLET před 11 roky
rodič
revize
e783acd8ce

+ 3 - 0
Makefile.am

@@ -81,6 +81,9 @@ bin_PROGRAMS =
 
 if PROGRAMS
 bin_PROGRAMS += dsm dsm_discover dsm_inverse dsm_lookup dsm_ntlm_test
+if DEBUG
+bin_PROGRAMS += dsm_ntlm_test
+endif
 endif
 
 dsm_SOURCES = bin/dsm.c

+ 8 - 6
bin/ntlm_test.c

@@ -39,7 +39,7 @@ int hexprint(const char *name, const char *data, size_t data_sz)
     {
       printf("\n0x");
     }
-    printf("%0.2hhx", *(data + i));
+    printf("%.2hhx", *(data + i));
   }
   printf("\n");
 }
@@ -60,19 +60,21 @@ int main(int argc, char const *argv[])
   uint64_t    usr_challenge   = htobe64(0x9a12f85759053d89);
   uint64_t    srv_ts          = htobe64(0x80b0dda51669cf01);
   uint64_t    srv_ts2         = htobe64(0x34fd56df1669cf01);
-  char        *lm2, *ntlm2;
+  void        *lm2, *ntlm2;
 
   smb_ntlm_blob *blob;
   size_t        blob_sz;
 
   smb_ntlmh   hashv1, hashv2, xkey, xkey_crypt;
+  smb_buffer  buf;
 
-  smb_ntlm_hash(password, hashv1);
-  smb_ntlm2_hash(user, password, domain, hashv2);
-  lm2 = smb_lm2_response(hashv2, srv_challenge, usr_challenge);
+  smb_ntlm_hash(password, &hashv1);
+  smb_ntlm2_hash(user, password, domain, &hashv2);
+  lm2 = smb_lm2_response(&hashv2, srv_challenge, usr_challenge);
 
   blob_sz = 16;//smb_ntlm_make_blob(&blob, srv_ts, usr_challenge, domain, domain, srv_ts2);
-  ntlm2 = smb_ntlm2_response(&hashv2, srv_challenge, lm2, blob_sz);
+  smb_buffer_init(&buf, lm2, blob_sz);
+  ntlm2 = smb_ntlm2_response(&hashv2, srv_challenge, &buf);
   //smb_ntlm2_session_key(&hashv2, ntlm2, &session_key);
 
   smb_ntlm_generate_xkey(xkey);

+ 5 - 1
include/bdsm/smb_buffer.h

@@ -52,7 +52,11 @@ void    smb_buffer_alloc(smb_buffer *buf, size_t size);
  * @brief Allocate a size long memory area from the stack and place it in
  *  the buffer structure
  */
-void    smb_buffer_alloca(smb_buffer *buf, size_t size);
+#define smb_buffer_alloca(buf, sz)    \
+  (buf)->data = alloca(sz);           \
+  (buf)->size = sz;                   \
+  assert((buf)->data != NULL);
+
 
 /**
  * @brief Free the data of this buffer if necessary

+ 5 - 6
include/bdsm/smb_ntlm.h

@@ -19,6 +19,7 @@
 #ifndef __BDSM_SMB_NTLM_H_
 #define __BDSM_SMB_NTLM_H_
 
+#include "bdsm/smb_buffer.h"
 #include "bdsm/smb_defs.h"
 
 #define SMB_LM2_BLOB_SIZE         8
@@ -92,11 +93,10 @@ void        smb_ntlm2_hash(const char *username, const char *password,
 // Precompute the blob that will be HMAC'ed to produce NTLM2 Response
 // You have to free() the blob after usage
 size_t      smb_ntlm_make_blob(smb_ntlm_blob **blob, uint64_t ts,
-                               uint64_t user_challenge, void *tgt,
-                               size_t tgt_sz);
+                               uint64_t user_challenge, smb_buffer *target);
 // Returned response is blob_size + 16 long. You'll have to free it
 uint8_t     *smb_ntlm2_response(smb_ntlmh *hash_v2, uint64_t srv_challenge,
-                                uint8_t *blob, size_t blob_size);
+                                smb_buffer *blob);
 // Returned response is 24 bytes long. You'll have to free it.
 uint8_t     *smb_lm2_response(smb_ntlmh *hash_v2, uint64_t srv_challenge,
                               uint64_t user_challenge);
@@ -105,11 +105,10 @@ void        smb_ntlm2_session_key(smb_ntlmh *hash_v2, void *ntlm2,
                                   smb_ntlmh *xkey, smb_ntlmh *enc_xkey);
 
 void        smb_ntlmssp_negotiate(const char *host, const char *domain,
-                                  void **token, size_t *token_sz);
+                                  smb_buffer *token);
 void        smb_ntlmssp_response(uint64_t srv_challenge, uint64_t srv_ts,
                                  const char *host, const char *domain,
                                  const char *user, const char *password,
-                                 void *tgt, size_t tgt_sz,
-                                 void **token, size_t *token_sz);
+                                 smb_buffer *target, smb_buffer *token);
 
 #endif

+ 1 - 0
include/bdsm/smb_session.h

@@ -20,6 +20,7 @@
 #define __BDSM_SMB_SESSION_H_
 
 
+#include "bdsm/smb_buffer.h"
 #include "bdsm/netbios_session.h"
 #include "bdsm/smb_defs.h"
 #include "bdsm/smb_types.h"

+ 2 - 5
include/bdsm/smb_types.h

@@ -28,6 +28,7 @@
 #include <stddef.h>
 #include <libtasn1.h>
 
+#include "bdsm/smb_buffer.h"
 #include "bdsm/smb_packets.h"
 
 /**
@@ -128,11 +129,7 @@ typedef struct
     ASN1_TYPE           asn1_def;
   }                   spnego;           // eXtended SECurity negociation data
 
-  struct {
-    uint32_t            flags;
-    void                *tgt_info;      // Target info buffer, given by server.
-    size_t              tgt_info_sz;    // The size of the buffer
-  }                   xsec;
+  smb_buffer          xsec_target;
 
   smb_creds           creds;
   smb_transport       transport;

+ 0 - 10
src/smb_buffer.c

@@ -40,16 +40,6 @@ void    smb_buffer_alloc(smb_buffer *buf, size_t size)
   assert(buf->data != NULL);
 }
 
-void    smb_buffer_alloca(smb_buffer *buf, size_t size)
-{
-  assert(buf != NULL);
-
-  buf->data = alloca(size);
-  buf->size = size;
-
-  assert(buf->data != NULL);
-}
-
 void    smb_buffer_free(smb_buffer *buf)
 {
   if (buf == NULL || buf->data == NULL)

+ 48 - 47
src/smb_ntlm.c

@@ -112,24 +112,22 @@ void        smb_ntlm2_hash(const char *user, const char *password,
 }
 
 uint8_t     *smb_ntlm2_response(smb_ntlmh *hash_v2, uint64_t srv_challenge,
-                                uint8_t *blob, size_t blob_size)
+                                smb_buffer *blob)
 {
-  uint8_t         *data, *response, hmac[16];
-  size_t          data_len;
+  smb_buffer      data;
+  uint8_t         *response, hmac[16];
 
 
-  data_len  = sizeof(uint64_t) + blob_size;
-  data      = alloca(data_len);
-  assert(data != NULL);
-  memcpy(data, (void *)&srv_challenge, sizeof(uint64_t));
-  memcpy(data + sizeof(uint64_t), blob, blob_size);
+  smb_buffer_alloca(&data, sizeof(uint64_t) + blob->size);
+  memcpy(data.data, (void *)&srv_challenge, sizeof(uint64_t));
+  memcpy(data.data + sizeof(uint64_t), blob->data, blob->size);
 
-  HMAC_MD5(hash_v2, SMB_NTLM_HASH_SIZE, data, data_len, &hmac);
+  HMAC_MD5(hash_v2, SMB_NTLM_HASH_SIZE, data.data, data.size, &hmac);
 
-  response = malloc(blob_size + 16);
+  response = malloc(blob->size + 16);
   assert(response != NULL);
   memcpy(response, (void *)hmac, 16);
-  memcpy(response + 16, blob, blob_size);
+  memcpy(response + 16, blob->data, blob->size);
 
   return (response);
 }
@@ -137,7 +135,10 @@ uint8_t     *smb_ntlm2_response(smb_ntlmh *hash_v2, uint64_t srv_challenge,
 uint8_t     *smb_lm2_response(smb_ntlmh *hash_v2, uint64_t srv_challenge,
                               uint64_t user_challenge)
 {
-  return (smb_ntlm2_response(hash_v2, srv_challenge, (void *)&user_challenge, 8));
+  smb_buffer buf;
+
+  smb_buffer_init(&buf, (void *)&user_challenge, 8);
+  return (smb_ntlm2_response(hash_v2, srv_challenge, &buf));
 }
 
 // static void   _wcamelcase(char *str)
@@ -215,24 +216,23 @@ uint8_t     *smb_lm2_response(smb_ntlmh *hash_v2, uint64_t srv_challenge,
 // }
 
 size_t      smb_ntlm_make_blob(smb_ntlm_blob **out_blob, uint64_t ts,
-                               uint64_t user_challenge, void *tgt_info,
-                               size_t tgt_sz)
+                               uint64_t user_challenge, smb_buffer *target)
 {
   smb_ntlm_blob *blob;
 
-  assert(out_blob != NULL && tgt_info != NULL);
+  assert(out_blob != NULL && target != NULL);
 
-  blob = malloc(tgt_sz + sizeof(smb_ntlm_blob));
+  blob = malloc(target->size + sizeof(smb_ntlm_blob));
 
   memset((void *)blob, 0, sizeof(smb_ntlm_blob));
   blob->header    = 0x101;
   blob->timestamp = ts;
   blob->challenge = user_challenge;
 
-  memcpy(blob->target, tgt_info, tgt_sz);
+  memcpy(blob->target, target->data, target->size);
 
   *out_blob = blob;
-  return (sizeof(smb_ntlm_blob) + tgt_sz);
+  return (sizeof(smb_ntlm_blob) + target->size);
 }
 
 void        smb_ntlm2_session_key(smb_ntlmh *hash_v2, void *ntlm2,
@@ -249,20 +249,20 @@ void        smb_ntlm2_session_key(smb_ntlmh *hash_v2, void *ntlm2,
 
 
 void        smb_ntlmssp_negotiate(const char *host, const char *domain,
-                                  void **token, size_t *token_sz)
+                                  smb_buffer *token)
 {
   smb_ntlmssp_nego  *nego;
 
-  assert(host != NULL && domain != NULL && token != NULL && token_sz != NULL);
+  assert(host != NULL && domain != NULL && token != NULL);
 
-  *token_sz = sizeof(smb_ntlmssp_nego) + strlen(host) + strlen(domain);
-  if (*token_sz % 2) // Align on Word
-    *token_sz += 1;
+  token->size = sizeof(smb_ntlmssp_nego) + strlen(host) + strlen(domain);
+  if (token->size % 2) // Align on Word
+    token->size += 1;
+  smb_buffer_alloc(token, token->size);
+  // fprintf(stderr, "Token size if %ld\n", token->size);
 
-  // fprintf(stderr, "Token size if %ld\n", *token_sz);
 
-  nego      = (smb_ntlmssp_nego *)malloc(*token_sz);
-  assert(nego != NULL);
+  nego      = (smb_ntlmssp_nego *)token->data;
 
   nego->type  = SMB_NTLMSSP_CMD_NEGO;
   nego->flags = 0x60088215;//0x20080205;
@@ -274,8 +274,6 @@ void        smb_ntlmssp_negotiate(const char *host, const char *domain,
   memcpy(nego->id, "NTLMSSP", 8);
   memcpy(nego->names, domain, strlen(domain));
   memcpy(nego->names + strlen(domain), domain, strlen(domain));
-
-  *token = (void *)nego;
 }
 
 #define __AUTH_APPEND(FIELD, value, size, cursor)           \
@@ -287,43 +285,48 @@ void        smb_ntlmssp_negotiate(const char *host, const char *domain,
 void        smb_ntlmssp_response(uint64_t srv_challenge, uint64_t srv_ts,
                                  const char *host, const char *domain,
                                  const char *user, const char *password,
-                                 void *tgt, size_t tgt_sz,
-                                 void **token, size_t *token_sz)
+                                 smb_buffer *target, smb_buffer *token)
 {
   smb_ntlmssp_auth      *auth;
   smb_ntlm_blob         *blob;
   smb_ntlmh             hash_v2, xkey, xkey_crypt;
+  smb_buffer            buf;
   void                  *lm2, *ntlm2;
   size_t                blob_size, utf_sz, cursor = 0;
   uint64_t              user_challenge;
   char                  *utf;
 
   assert(host != NULL && domain != NULL && user != NULL && password != NULL);
-  assert(token != NULL && token_sz != NULL);
+  assert(token != NULL && target != NULL);
 
   //// We compute most of the data first to know the final token size
   smb_ntlm2_hash(user, password, domain, &hash_v2);
   user_challenge = smb_ntlm_generate_challenge();
   smb_ntlm_generate_xkey(&xkey);
-  blob_size = smb_ntlm_make_blob(&blob, srv_ts, user_challenge, tgt, tgt_sz);
+  blob_size = smb_ntlm_make_blob(&blob, srv_ts, user_challenge, target);
 
   lm2   = smb_lm2_response(&hash_v2, srv_challenge, smb_ntlm_generate_challenge());
-  ntlm2 = smb_ntlm2_response(&hash_v2, srv_challenge, (void *)blob, blob_size);
+  smb_buffer_init(&buf, blob, blob_size);
+  ntlm2 = smb_ntlm2_response(&hash_v2, srv_challenge, &buf);
   smb_ntlm2_session_key(&hash_v2, ntlm2, &xkey, &xkey_crypt);
 
-  *token_sz = sizeof(smb_ntlmssp_auth)
-              + strlen(host) * 2
-              + strlen(domain) * 2
-              + strlen(user) * 2
-              + blob_size + 16 // Blob + HMAC
-              + 8 + 16  // LM2 Response (miniblob=user_challenge + HMAC)
-              + 16;     // Session Key
-  if (*token_sz % 2) // Align on Word
-    *token_sz += 1;
+  smb_buffer_init(&buf, NULL, 0);
+  free(blob);
 
-  auth = (smb_ntlmssp_auth *)malloc(*token_sz);
-  assert(auth != NULL);
-  memset(auth, 0, *token_sz);
+  // Compute size of and allocate token
+  token->size = sizeof(smb_ntlmssp_auth)
+                + strlen(host) * 2
+                + strlen(domain) * 2
+                + strlen(user) * 2
+                + blob_size + 16 // Blob + HMAC
+                + 8 + 16  // LM2 Response (miniblob=user_challenge + HMAC)
+                + 16;     // Session Key
+  if (token->size % 2) // Align on Word
+    token->size += 1;
+  smb_buffer_alloc(token, token->size);
+
+  auth = (smb_ntlmssp_auth *)token->data;
+  memset(auth, 0, token->size);
 
   memcpy(auth->id, "NTLMSSP", 8);
   auth->type  = SMB_NTLMSSP_CMD_AUTH;
@@ -347,6 +350,4 @@ void        smb_ntlmssp_response(uint64_t srv_challenge, uint64_t srv_ts,
 
   free(lm2);
   free(ntlm2);
-
-  *token = auth;
 }

+ 7 - 3
src/smb_session.c

@@ -41,7 +41,6 @@ smb_session   *smb_session_new()
   // Explicitly sets pointer to NULL, insted of 0
   s->spnego.init        = NULL;
   s->spnego.asn1_def    = NULL;
-  s->xsec.tgt_info      = NULL;
   s->transport.session  = NULL;
   s->shares             = NULL;
 
@@ -49,6 +48,11 @@ smb_session   *smb_session_new()
   s->creds.login        = NULL;
   s->creds.password     = NULL;
 
+  smb_buffer_init(&s->xsec_target, NULL, 0);
+
+  // Until we know more, assume server supports everything.
+  // s->c
+
   return (s);
 }
 
@@ -67,8 +71,8 @@ void            smb_session_destroy(smb_session *s)
       free(s->spnego.init);
     if (s->spnego.asn1_def != NULL)
       asn1_delete_structure(&s->spnego.asn1_def);
-    if (s->xsec.tgt_info != NULL)
-      free(s->xsec.tgt_info);
+
+    smb_buffer_free(&s->xsec_target);
 
     // Free stored credentials.
     if (s->creds.domain != NULL)

+ 13 - 16
src/smb_spnego.c

@@ -69,9 +69,8 @@ static int      negotiate(smb_session *s, const char *domain)
 {
   smb_message           *msg = NULL;
   smb_session_xsec_req  *req = NULL;
+  smb_buffer            ntlm;
   ASN1_TYPE             token;
-  void                  *ntlm;
-  size_t                ntlm_size;
   int                   res, der_size = 128;
   char                  der[128], err_desc[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
 
@@ -105,9 +104,10 @@ static int      negotiate(smb_session *s, const char *domain)
   res = asn1_write_value(token, "spnego.negTokenInit.mechListMIC", NULL, 0);
   if (res != ASN1_SUCCESS) goto error;
 
-  smb_ntlmssp_negotiate(domain, domain, &ntlm, &ntlm_size);
-  res = asn1_write_value(token, "spnego.negTokenInit.mechToken", ntlm, ntlm_size);
-  free(ntlm);
+  smb_ntlmssp_negotiate(domain, domain, &ntlm);
+  res = asn1_write_value(token, "spnego.negTokenInit.mechToken", ntlm.data,
+                         ntlm.size);
+  smb_buffer_free(&ntlm);
   if (res != ASN1_SUCCESS) goto error;
 
   res = asn1_der_coding(token, "", der, &der_size, err_desc);
@@ -198,13 +198,10 @@ static int      challenge(smb_session *s)
 
   // We got the server challenge, yeaaah.
   challenge = (smb_ntlmssp_challenge *)resp_token;
-  s->xsec.tgt_info_sz = challenge->tgt_len;
-  s->xsec.tgt_info = malloc(s->xsec.tgt_info_sz);
-  assert(s->xsec.tgt_info != NULL);
-  memcpy(s->xsec.tgt_info,
+  smb_buffer_alloc(&s->xsec_target, challenge->tgt_len);
+  memcpy(s->xsec_target.data,
          challenge->data + challenge->tgt_offset - sizeof(smb_ntlmssp_challenge),
-         s->xsec.tgt_info_sz);
-  //s->srv.challenge = *((uint64_t *)(resp_token + 24));
+         s->xsec_target.size);
   s->srv.challenge = challenge->challenge;
   s->srv.uid       = msg.packet->header.uid;
 
@@ -218,9 +215,8 @@ static int      auth(smb_session *s, const char *domain, const char *user,
 {
   smb_message           *msg = NULL, resp;
   smb_session_xsec_req  *req = NULL;
+  smb_buffer            ntlm;
   ASN1_TYPE             token;
-  void                  *ntlm;
-  size_t                ntlm_size;
   int                   res, der_size = 512;
   char                  der[512], err_desc[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
 
@@ -254,9 +250,10 @@ static int      auth(smb_session *s, const char *domain, const char *user,
 
 
   smb_ntlmssp_response(s->srv.challenge, s->srv.ts - 4200, domain, domain, user,
-                       password, s->xsec.tgt_info, s->xsec.tgt_info_sz,
-                       &ntlm, &ntlm_size);
-  res = asn1_write_value(token, "negTokenResp.responseToken", ntlm, ntlm_size);
+                       password, &s->xsec_target, &ntlm);
+  res = asn1_write_value(token, "negTokenResp.responseToken", ntlm.data,
+                         ntlm.size);
+  smb_buffer_free(&ntlm);
   if (res != ASN1_SUCCESS) goto error;
 
   res = asn1_der_coding(token, "", der, &der_size, err_desc);