s4:ntlmssp Use common code for ntlmssp_sign.c
authorAndrew Bartlett <abartlet@samba.org>
Tue, 25 May 2010 11:18:15 +0000 (21:18 +1000)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 1 Jun 2010 07:11:24 +0000 (17:11 +1000)
The common code does not have a mem_ctx on ntlmssp_check_packet() and
ntlmssp_unseal_packet().

We do however need some internal working of the code exposed, so some
structures are moved to ntlmssp_sign.h

Andrew Bartlett

libcli/auth/ntlmssp_private.h
libcli/auth/ntlmssp_sign.c
source4/auth/ntlmssp/ntlmssp_sign.c
source4/auth/ntlmssp/wscript_build

index 0f0c7dbba941ca12be6f20b8370a9e98bded0fc1..e2044eea20761769a933b3693726851878012093 100644 (file)
 
 /* For structures internal to the NTLMSSP implementation that should not be exposed */
 
+#include "../lib/crypto/arcfour.h"
+
+struct ntlmssp_crypt_direction {
+       uint32_t seq_num;
+       uint8_t sign_key[16];
+       struct arcfour_state seal_state;
+};
+
+union ntlmssp_crypt_state {
+       /* NTLM */
+       struct ntlmssp_crypt_direction ntlm;
+
+       /* NTLM2 */
+       struct {
+               struct ntlmssp_crypt_direction sending;
+               struct ntlmssp_crypt_direction receiving;
+       } ntlm2;
+};
+
 /* The following definitions come from libcli/auth/ntlmssp.c  */
 
 void debug_ntlmssp_flags(uint32_t neg_flags);
index 61b52c6a6174391e724d475576c1af4c0be61c7a..3cf1ed75a73b741ca0f74b79a24bf35d17f7836e 100644 (file)
@@ -22,7 +22,6 @@
 #include "../libcli/auth/ntlmssp.h"
 #include "../libcli/auth/libcli_auth.h"
 #include "../lib/crypto/md5.h"
-#include "../lib/crypto/arcfour.h"
 #include "../lib/crypto/hmacmd5.h"
 #include "../lib/crypto/crc32.h"
 #include "../libcli/auth/ntlmssp_private.h"
@@ -64,23 +63,6 @@ enum ntlmssp_direction {
        NTLMSSP_RECEIVE
 };
 
-struct ntlmssp_crypt_direction {
-       uint32_t seq_num;
-       uint8_t sign_key[16];
-       struct arcfour_state seal_state;
-};
-
-union ntlmssp_crypt_state {
-       /* NTLM */
-       struct ntlmssp_crypt_direction ntlm;
-
-       /* NTLM2 */
-       struct {
-               struct ntlmssp_crypt_direction sending;
-               struct ntlmssp_crypt_direction receiving;
-       } ntlm2;
-};
-
 static NTSTATUS ntlmssp_make_packet_signature(struct ntlmssp_state *ntlmssp_state,
                                              TALLOC_CTX *sig_mem_ctx,
                                              const uint8_t *data, size_t length,
index 0a86235a103853e26d87045b29114d978a2d554e..8cde44150a43d57ded3472c7e7fbfdcd00ef6a17 100644 (file)
 
 #include "includes.h"
 #include "auth/ntlmssp/ntlmssp.h"
-#include "../libcli/auth/libcli_auth.h"
-#include "../lib/crypto/crypto.h"
 #include "auth/gensec/gensec.h"
-
-#define CLI_SIGN "session key to client-to-server signing key magic constant"
-#define CLI_SEAL "session key to client-to-server sealing key magic constant"
-#define SRV_SIGN "session key to server-to-client signing key magic constant"
-#define SRV_SEAL "session key to server-to-client sealing key magic constant"
-
-/**
- * Some notes on the NTLM2 code:
- *
- * NTLM2 is a AEAD system.  This means that the data encrypted is not
- * all the data that is signed.  In DCE-RPC case, the headers of the
- * DCE-RPC packets are also signed.  This prevents some of the
- * fun-and-games one might have by changing them.
- *
- */
-
-static void dump_arc4_state(const char *description,
-                           struct arcfour_state *state)
-{
-       dump_data_pw(description, state->sbox, sizeof(state->sbox));
-}
-
-static void calc_ntlmv2_key(uint8_t subkey[16],
-                           DATA_BLOB session_key,
-                           const char *constant)
-{
-       struct MD5Context ctx3;
-       MD5Init(&ctx3);
-       MD5Update(&ctx3, session_key.data, session_key.length);
-       MD5Update(&ctx3, (const uint8_t *)constant, strlen(constant)+1);
-       MD5Final(subkey, &ctx3);
-}
-
-enum ntlmssp_direction {
-       NTLMSSP_SEND,
-       NTLMSSP_RECEIVE
-};
-
-struct ntlmssp_crypt_direction {
-       uint32_t seq_num;
-       uint8_t sign_key[16];
-       struct arcfour_state seal_state;
-};
-
-union ntlmssp_crypt_state {
-       /* NTLM */
-       struct ntlmssp_crypt_direction ntlm;
-
-       /* NTLM2 */
-       struct {
-               struct ntlmssp_crypt_direction sending;
-               struct ntlmssp_crypt_direction receiving;
-       } ntlm2;
-};
-
-static NTSTATUS ntlmssp_make_packet_signature(struct ntlmssp_state *ntlmssp_state,
-                                             TALLOC_CTX *sig_mem_ctx,
-                                             const uint8_t *data, size_t length,
-                                             const uint8_t *whole_pdu, size_t pdu_length,
-                                             enum ntlmssp_direction direction,
-                                             DATA_BLOB *sig, bool encrypt_sig)
-{
-       if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
-               HMACMD5Context ctx;
-               uint8_t digest[16];
-               uint8_t seq_num[4];
-
-               *sig = data_blob_talloc(sig_mem_ctx, NULL, NTLMSSP_SIG_SIZE);
-               if (!sig->data) {
-                       return NT_STATUS_NO_MEMORY;
-               }
-
-               switch (direction) {
-               case NTLMSSP_SEND:
-                       SIVAL(seq_num, 0, ntlmssp_state->crypt->ntlm2.sending.seq_num);
-                       ntlmssp_state->crypt->ntlm2.sending.seq_num++;
-                       hmac_md5_init_limK_to_64(ntlmssp_state->crypt->ntlm2.sending.sign_key, 16, &ctx);
-                       break;
-               case NTLMSSP_RECEIVE:
-                       SIVAL(seq_num, 0, ntlmssp_state->crypt->ntlm2.receiving.seq_num);
-                       ntlmssp_state->crypt->ntlm2.receiving.seq_num++;
-                       hmac_md5_init_limK_to_64(ntlmssp_state->crypt->ntlm2.receiving.sign_key, 16, &ctx);
-                       break;
-               }
-               hmac_md5_update(seq_num, sizeof(seq_num), &ctx);
-               hmac_md5_update(whole_pdu, pdu_length, &ctx);
-               hmac_md5_final(digest, &ctx);
-
-               if (encrypt_sig && (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)) {
-                       switch (direction) {
-                       case NTLMSSP_SEND:
-                               arcfour_crypt_sbox(&ntlmssp_state->crypt->ntlm2.sending.seal_state,
-                                                  digest, 8);
-                               break;
-                       case NTLMSSP_RECEIVE:
-                               arcfour_crypt_sbox(&ntlmssp_state->crypt->ntlm2.receiving.seal_state,
-                                                  digest, 8);
-                               break;
-                       }
-               }
-
-               SIVAL(sig->data, 0, NTLMSSP_SIGN_VERSION);
-               memcpy(sig->data + 4, digest, 8);
-               memcpy(sig->data + 12, seq_num, 4);
-
-               DEBUG(10,("NTLM2: created signature over %llu bytes of input:\n",
-                         (unsigned long long)pdu_length));
-               dump_data(11, sig->data, sig->length);
-       } else {
-               bool ok;
-               uint32_t crc;
-
-               crc = crc32_calc_buffer(data, length);
-
-               ok = msrpc_gen(sig_mem_ctx,
-                              sig, "dddd",
-                              NTLMSSP_SIGN_VERSION, 0, crc,
-                              ntlmssp_state->crypt->ntlm.seq_num);
-               if (!ok) {
-                       return NT_STATUS_NO_MEMORY;
-               }
-               ntlmssp_state->crypt->ntlm.seq_num++;
-
-               arcfour_crypt_sbox(&ntlmssp_state->crypt->ntlm.seal_state,
-                                  sig->data+4, sig->length-4);
-
-               DEBUG(10,("NTLM1: created signature over %llu bytes of input:\n",
-                         (unsigned long long)length));
-               dump_data(11, sig->data, sig->length);
-       }
-       return NT_STATUS_OK;
-}
-
-NTSTATUS ntlmssp_sign_packet(struct ntlmssp_state *ntlmssp_state,
-                            TALLOC_CTX *sig_mem_ctx,
-                            const uint8_t *data, size_t length,
-                            const uint8_t *whole_pdu, size_t pdu_length,
-                            DATA_BLOB *sig)
-{
-       NTSTATUS nt_status;
-
-       nt_status = ntlmssp_make_packet_signature(ntlmssp_state,
-                                                 sig_mem_ctx,
-                                                 data, length,
-                                                 whole_pdu, pdu_length,
-                                                 NTLMSSP_SEND, sig, true);
-
-       return nt_status;
-}
-
-/**
- * Check the signature of an incoming packet 
- *
- */
-
-NTSTATUS ntlmssp_check_packet(struct ntlmssp_state *ntlmssp_state,
-                             TALLOC_CTX *sig_mem_ctx,
-                             const uint8_t *data, size_t length,
-                             const uint8_t *whole_pdu, size_t pdu_length,
-                             const DATA_BLOB *sig)
-{
-       DATA_BLOB local_sig;
-       NTSTATUS nt_status;
-
-       if (!ntlmssp_state->session_key.length) {
-               DEBUG(3, ("NO session key, cannot check packet signature\n"));
-               return NT_STATUS_NO_USER_SESSION_KEY;
-       }
-
-       nt_status = ntlmssp_make_packet_signature(ntlmssp_state,
-                                                 sig_mem_ctx,
-                                                 data, length,
-                                                 whole_pdu, pdu_length,
-                                                 NTLMSSP_RECEIVE,
-                                                 &local_sig, true);
-       
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               DEBUG(0,("NTLMSSP packet sig creation failed with %s\n",
-                        nt_errstr(nt_status)));
-               return nt_status;
-       }
-
-       if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
-               if (local_sig.length != sig->length ||
-                   memcmp(local_sig.data, sig->data, sig->length) != 0) {
-
-                       DEBUG(10,("BAD SIG NTLM2: wanted signature over %llu bytes of input:\n",
-                                 (unsigned long long)pdu_length));
-                       dump_data(10, local_sig.data, local_sig.length);
-
-                       DEBUG(10,("BAD SIG: got signature over %llu bytes of input:\n",
-                                 (unsigned long long)pdu_length));
-                       dump_data(10, sig->data, sig->length);
-
-                       data_blob_free(&local_sig);
-                       return NT_STATUS_ACCESS_DENIED;
-               }
-       } else {
-               if (local_sig.length != sig->length ||
-                   memcmp(local_sig.data + 8, sig->data + 8, sig->length - 8) != 0) {
-                       DEBUG(10,("BAD SIG NTLM1: wanted signature of %llu bytes of input:\n",
-                                 (unsigned long long)length));
-                       dump_data(5, local_sig.data, local_sig.length);
-
-                       DEBUG(10,("BAD SIG: got signature of %llu bytes of input:\n",
-                                 (unsigned long long)length));
-                       dump_data(10, sig->data, sig->length);
-
-                       data_blob_free(&local_sig);
-                       return NT_STATUS_ACCESS_DENIED;
-               }
-       }
-       dump_data_pw("checked ntlmssp signature\n", sig->data, sig->length);
-
-       data_blob_free(&local_sig);
-       return NT_STATUS_OK;
-}
-
-
-/**
- * Seal data with the NTLMSSP algorithm
- *
- */
-
-NTSTATUS ntlmssp_seal_packet(struct ntlmssp_state *ntlmssp_state,
-                            TALLOC_CTX *sig_mem_ctx,
-                            uint8_t *data, size_t length,
-                            const uint8_t *whole_pdu, size_t pdu_length,
-                            DATA_BLOB *sig)
-{
-       if (!ntlmssp_state->session_key.length) {
-               DEBUG(3, ("NO session key, cannot seal packet\n"));
-               return NT_STATUS_NO_USER_SESSION_KEY;
-       }
-
-       DEBUG(10,("ntlmssp_seal_data: seal\n"));
-       dump_data_pw("ntlmssp clear data\n", data, length);
-       if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
-               NTSTATUS nt_status;
-               /*
-                * The order of these two operations matters - we
-                * must first seal the packet, then seal the
-                * sequence number - this is because the
-                * send_seal_hash is not constant, but is is rather
-                * updated with each iteration
-                */
-               nt_status = ntlmssp_make_packet_signature(ntlmssp_state,
-                                                         sig_mem_ctx,
-                                                         data, length,
-                                                         whole_pdu, pdu_length,
-                                                         NTLMSSP_SEND,
-                                                         sig, false);
-               if (!NT_STATUS_IS_OK(nt_status)) {
-                       return nt_status;
-               }
-
-               arcfour_crypt_sbox(&ntlmssp_state->crypt->ntlm2.sending.seal_state,
-                                  data, length);
-               if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
-                       arcfour_crypt_sbox(&ntlmssp_state->crypt->ntlm2.sending.seal_state,
-                                          sig->data+4, 8);
-               }
-       } else {
-               bool ok;
-               uint32_t crc;
-
-               crc = crc32_calc_buffer(data, length);
-
-               ok = msrpc_gen(sig_mem_ctx,
-                              sig, "dddd",
-                              NTLMSSP_SIGN_VERSION, 0, crc,
-                              ntlmssp_state->crypt->ntlm.seq_num);
-               if (!ok) {
-                       return NT_STATUS_NO_MEMORY;
-               }
-
-               /*
-                * The order of these two operations matters - we
-                * must first seal the packet, then seal the
-                * sequence number - this is because the ntlmv1_arc4_state
-                * is not constant, but is is rather updated with
-                * each iteration
-                */
-
-               arcfour_crypt_sbox(&ntlmssp_state->crypt->ntlm.seal_state,
-                                  data, length);
-
-               arcfour_crypt_sbox(&ntlmssp_state->crypt->ntlm.seal_state,
-                                  sig->data+4, sig->length-4);
-
-               ntlmssp_state->crypt->ntlm.seq_num++;
-       }
-       dump_data_pw("ntlmssp signature\n", sig->data, sig->length);
-       dump_data_pw("ntlmssp sealed data\n", data, length);
-
-       return NT_STATUS_OK;
-}
-
-/**
- * Unseal data with the NTLMSSP algorithm
- *
- */
-
-NTSTATUS ntlmssp_unseal_packet(struct ntlmssp_state *ntlmssp_state,
-                              TALLOC_CTX *sig_mem_ctx,
-                              uint8_t *data, size_t length,
-                              const uint8_t *whole_pdu, size_t pdu_length,
-                              const DATA_BLOB *sig)
-{
-       NTSTATUS status;
-
-       if (!ntlmssp_state->session_key.length) {
-               DEBUG(3, ("NO session key, cannot unseal packet\n"));
-               return NT_STATUS_NO_USER_SESSION_KEY;
-       }
-
-       dump_data_pw("ntlmssp sealed data\n", data, length);
-       if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
-               arcfour_crypt_sbox(&ntlmssp_state->crypt->ntlm2.receiving.seal_state,
-                                  data, length);
-       } else {
-               arcfour_crypt_sbox(&ntlmssp_state->crypt->ntlm.seal_state,
-                                  data, length);
-       }
-       dump_data_pw("ntlmssp clear data\n", data, length);
-       status = ntlmssp_check_packet(ntlmssp_state,
-                                     sig_mem_ctx,
-                                     data, length,
-                                     whole_pdu, pdu_length,
-                                     sig);
-
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(1,("NTLMSSP packet check for unseal failed due to invalid signature on %llu bytes of input:\n",
-                        (unsigned long long)length));
-       }
-       return status;
-}
-
-/**
-   Initialise the state for NTLMSSP signing.
-*/
-NTSTATUS ntlmssp_sign_init(struct ntlmssp_state *ntlmssp_state)
-{
-       DEBUG(3, ("NTLMSSP Sign/Seal - Initialising with flags:\n"));
-       debug_ntlmssp_flags(ntlmssp_state->neg_flags);
-
-       if (ntlmssp_state->session_key.length < 8) {
-               DEBUG(3, ("NO session key, cannot intialise signing\n"));
-               return NT_STATUS_NO_USER_SESSION_KEY;
-       }
-
-       ntlmssp_state->crypt = talloc_zero(ntlmssp_state,
-                                          union ntlmssp_crypt_state);
-       if (ntlmssp_state->crypt == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
-               DATA_BLOB weak_session_key = ntlmssp_state->session_key;
-               const char *send_sign_const;
-               const char *send_seal_const;
-               const char *recv_sign_const;
-               const char *recv_seal_const;
-               uint8_t send_seal_key[16];
-               DATA_BLOB send_seal_blob = data_blob_const(send_seal_key,
-                                          sizeof(send_seal_key));
-               uint8_t recv_seal_key[16];
-               DATA_BLOB recv_seal_blob = data_blob_const(recv_seal_key,
-                                          sizeof(recv_seal_key));
-
-               switch (ntlmssp_state->role) {
-               case NTLMSSP_CLIENT:
-                       send_sign_const = CLI_SIGN;
-                       send_seal_const = CLI_SEAL;
-                       recv_sign_const = SRV_SIGN;
-                       recv_seal_const = SRV_SEAL;
-                       break;
-               case NTLMSSP_SERVER:
-                       send_sign_const = SRV_SIGN;
-                       send_seal_const = SRV_SEAL;
-                       recv_sign_const = CLI_SIGN;
-                       recv_seal_const = CLI_SEAL;
-                       break;
-               default:
-                       return NT_STATUS_INTERNAL_ERROR;
-               }
-
-               /*
-                * Weaken NTLMSSP keys to cope with down-level
-                * clients, servers and export restrictions.
-                *
-                * We probably should have some parameters to
-                * control this, once we get NTLM2 working.
-                *
-                * Key weakening was not performed on the master key
-                * for NTLM2, but must be done on the encryption subkeys only.
-                */
-
-               if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_128) {
-                       /* nothing to do */
-               } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_56) {
-                       weak_session_key.length = 7;
-               } else { /* forty bits */
-                       weak_session_key.length = 5;
-               }
-
-               dump_data_pw("NTLMSSP weakend master key:\n",
-                            weak_session_key.data,
-                            weak_session_key.length);
-
-               /* SEND: sign key */
-               calc_ntlmv2_key(ntlmssp_state->crypt->ntlm2.sending.sign_key,
-                               ntlmssp_state->session_key, send_sign_const);
-               dump_data_pw("NTLMSSP send sign key:\n",
-                            ntlmssp_state->crypt->ntlm2.sending.sign_key, 16);
-
-               /* SEND: seal ARCFOUR pad */
-               calc_ntlmv2_key(send_seal_key,
-                               weak_session_key, send_seal_const);
-               dump_data_pw("NTLMSSP send seal key:\n", send_seal_key, 16);
-
-               arcfour_init(&ntlmssp_state->crypt->ntlm2.sending.seal_state,
-                            &send_seal_blob);
-
-               dump_arc4_state("NTLMSSP send seal arc4 state:\n",
-                               &ntlmssp_state->crypt->ntlm2.sending.seal_state);
-
-               /* SEND: seq num */
-               ntlmssp_state->crypt->ntlm2.sending.seq_num = 0;
-
-               /* RECV: sign key */
-               calc_ntlmv2_key(ntlmssp_state->crypt->ntlm2.receiving.sign_key,
-                               ntlmssp_state->session_key, recv_sign_const);
-               dump_data_pw("NTLMSSP recv sign key:\n",
-                            ntlmssp_state->crypt->ntlm2.receiving.sign_key, 16);
-
-               /* RECV: seal ARCFOUR pad */
-               calc_ntlmv2_key(recv_seal_key,
-                               weak_session_key, recv_seal_const);
-               dump_data_pw("NTLMSSP recv seal key:\n", recv_seal_key, 16);
-
-               arcfour_init(&ntlmssp_state->crypt->ntlm2.receiving.seal_state,
-                            &recv_seal_blob);
-
-               dump_arc4_state("NTLMSSP recv seal arc4 state:\n",
-                               &ntlmssp_state->crypt->ntlm2.receiving.seal_state);
-
-               /* RECV: seq num */
-               ntlmssp_state->crypt->ntlm2.receiving.seq_num = 0;
-       } else {
-               uint8_t weak_session_key[8];
-               DATA_BLOB seal_session_key = ntlmssp_state->session_key;
-               bool do_weak = false;
-
-               DEBUG(5, ("NTLMSSP Sign/Seal - using NTLM1\n"));
-
-               /*
-                * Key weakening not performed on the master key for NTLM2
-                * and does not occour for NTLM1. Therefore we only need
-                * to do this for the LM_KEY.
-                */
-               if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) {
-                       do_weak = true;
-               }
-
-               /*
-                * Nothing to weaken.
-                * We certainly don't want to 'extend' the length...
-                */
-               if (seal_session_key.length < 16) {
-                       /* TODO: is this really correct? */
-                       do_weak = false;
-               }
-
-               if (do_weak) {
-                       memcpy(weak_session_key, seal_session_key.data, 8);
-                       seal_session_key = data_blob_const(weak_session_key, 8);
-
-                       /*
-                        * LM key doesn't support 128 bit crypto, so this is
-                        * the best we can do. If you negotiate 128 bit, but
-                        * not 56, you end up with 40 bit...
-                        */
-                       if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_56) {
-                               weak_session_key[7] = 0xa0;
-                       } else { /* forty bits */
-                               weak_session_key[5] = 0xe5;
-                               weak_session_key[6] = 0x38;
-                               weak_session_key[7] = 0xb0;
-                       }
-               }
-
-               arcfour_init(&ntlmssp_state->crypt->ntlm.seal_state,
-                            &seal_session_key);
-
-               dump_arc4_state("NTLMv1 arc4 state:\n",
-                               &ntlmssp_state->crypt->ntlm.seal_state);
-
-               ntlmssp_state->crypt->ntlm.seq_num = 0;
-       }
-
-       return NT_STATUS_OK;
-}
+#include "../libcli/auth/ntlmssp_private.h"
 
 NTSTATUS gensec_ntlmssp_sign_packet(struct gensec_security *gensec_security,
                                    TALLOC_CTX *sig_mem_ctx,
@@ -560,7 +56,6 @@ NTSTATUS gensec_ntlmssp_check_packet(struct gensec_security *gensec_security,
        NTSTATUS nt_status;
 
        nt_status = ntlmssp_check_packet(gensec_ntlmssp->ntlmssp_state,
-                                        sig_mem_ctx,
                                         data, length,
                                         whole_pdu, pdu_length,
                                         sig);
@@ -603,7 +98,6 @@ NTSTATUS gensec_ntlmssp_unseal_packet(struct gensec_security *gensec_security,
        NTSTATUS nt_status;
 
        nt_status = ntlmssp_unseal_packet(gensec_ntlmssp->ntlmssp_state,
-                                         sig_mem_ctx,
                                          data, length,
                                          whole_pdu, pdu_length,
                                          sig);
index a47bb6cd73824a2e23e0aadfffc7a447db3a941a..05d206936af9fc7892ceece52140482110784bb2 100644 (file)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 bld.SAMBA_MODULE('gensec_ntlmssp',
-       source='ntlmssp.c ntlmssp_sign.c ntlmssp_client.c ntlmssp_server.c',
+       source='ntlmssp.c ntlmssp_sign.c ../../../libcli/auth/ntlmssp_sign.c ntlmssp_client.c ntlmssp_server.c',
        autoproto='proto.h',
        subsystem='gensec',
        init_function='gensec_ntlmssp_init',