...

Source file src/github.com/Azure/go-ntlmssp/nlmp_test.go

Documentation: github.com/Azure/go-ntlmssp

     1  package ntlmssp
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	"strings"
     7  	"testing"
     8  )
     9  
    10  // test cases from http://davenport.sourceforge.net/ntlm.html
    11  
    12  var username = "user"
    13  var password = "SecREt01"
    14  var ntlmHashHex = "CD06CA7C7E10C99B1D33B7485A2ED808" // NT Hash in hex of "SecREt01"
    15  var target = "DOMAIN"
    16  var domain = "MYDOMAIN"
    17  var workstation = "MYPC"
    18  var challenge = []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}
    19  
    20  func TestUsernameDomainWorkstation(t *testing.T) {
    21  	// taking a username and workstation as input, check that the username, domain, workstation
    22  	// and negotiate message bytes all match their expected values
    23  	tables := []struct {
    24  		u  string
    25  		w  string
    26  		xu string
    27  		xd string
    28  		xb []byte
    29  	}{
    30  		{username, "", username, "", []byte{
    31  			0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
    32  			0x88, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    33  			0x28, 0x00, 0x00, 0x00, 0x06, 0x01, 0xb1, 0x1d, 0x00, 0x00, 0x00, 0x0f}},
    34  		{domain + "\\" + username, "", username, domain, []byte{
    35  			0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10,
    36  			0x88, 0xa0, 0x08, 0x00, 0x08, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    37  			0x30, 0x00, 0x00, 0x00, 0x06, 0x01, 0xb1, 0x1d, 0x00, 0x00, 0x00, 0x0f, 0x4d, 0x59,
    38  			0x44, 0x4f, 0x4d, 0x41, 0x49, 0x4e}},
    39  		{domain + "\\" + username, workstation, username, domain, []byte{
    40  			0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x30,
    41  			0x88, 0xa0, 0x08, 0x00, 0x08, 0x00, 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
    42  			0x30, 0x00, 0x00, 0x00, 0x06, 0x01, 0xb1, 0x1d, 0x00, 0x00, 0x00, 0x0f, 0x4d, 0x59,
    43  			0x44, 0x4f, 0x4d, 0x41, 0x49, 0x4e, 0x4d, 0x59, 0x50, 0x43}},
    44  		{username, workstation, username, "", []byte{
    45  			0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
    46  			0x88, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
    47  			0x28, 0x00, 0x00, 0x00, 0x06, 0x01, 0xb1, 0x1d, 0x00, 0x00, 0x00, 0x0f, 0x4d, 0x59,
    48  			0x50, 0x43}},
    49  	}
    50  
    51  	for _, table := range tables {
    52  		tuser, tdomain := GetDomain(table.u)
    53  		if tuser != table.xu {
    54  			t.Fatalf("username not correct, expected %v got %v", tuser, table.xu)
    55  		}
    56  		if tdomain != table.xd {
    57  			t.Fatalf("domain not correct, expected %v got %v", tdomain, table.xd)
    58  		}
    59  
    60  		tb, err := NewNegotiateMessage(tdomain, table.w)
    61  		if err != nil {
    62  			t.Fatalf("error creating new negotiate message with domain '%v' and workstation '%v'", tdomain, table.w)
    63  		}
    64  
    65  		if !bytes.Equal(tb, table.xb) {
    66  			t.Fatalf("negotiate message bytes not correct, expected %v got %v", tb, table.xb)
    67  		}
    68  	}
    69  
    70  }
    71  
    72  func TestCalculateNTLMv2Response(t *testing.T) {
    73  	NTLMv2Hash := getNtlmV2Hash(password, username, target)
    74  	ClientChallenge := []byte{0xff, 0xff, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44}
    75  	Time := []byte{0x00, 0x90, 0xd3, 0x36, 0xb7, 0x34, 0xc3, 0x01}
    76  	targetInfo := []byte{0x02, 0x00, 0x0c, 0x00, 0x44, 0x00, 0x4f, 0x00, 0x4d, 0x00, 0x41, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x53, 0x00, 0x45, 0x00, 0x52, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00, 0x04, 0x00, 0x14, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x03, 0x00, 0x22, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x2e, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00}
    77  
    78  	v := computeNtlmV2Response(NTLMv2Hash, challenge, ClientChallenge, Time, targetInfo)
    79  
    80  	if expected := []byte{
    81  		0xcb, 0xab, 0xbc, 0xa7, 0x13, 0xeb, 0x79, 0x5d, 0x04, 0xc9, 0x7a, 0xbc, 0x01, 0xee, 0x49, 0x83,
    82  		0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0xd3, 0x36, 0xb7, 0x34, 0xc3, 0x01,
    83  		0xff, 0xff, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0c, 0x00,
    84  		0x44, 0x00, 0x4f, 0x00, 0x4d, 0x00, 0x41, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x01, 0x00, 0x0c, 0x00,
    85  		0x53, 0x00, 0x45, 0x00, 0x52, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00, 0x04, 0x00, 0x14, 0x00,
    86  		0x64, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2e, 0x00, 0x63, 0x00,
    87  		0x6f, 0x00, 0x6d, 0x00, 0x03, 0x00, 0x22, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00,
    88  		0x65, 0x00, 0x72, 0x00, 0x2e, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00,
    89  		0x6e, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    90  		0x00, 0x00,
    91  	}; !bytes.Equal(v, expected) {
    92  		t.Fatalf("expected %x, got %x", expected, v)
    93  	}
    94  }
    95  
    96  func TestCalculateNTLMv2ResponseWithHash(t *testing.T) {
    97  	hashBytes, err := hex.DecodeString(ntlmHashHex)
    98  	if err != nil {
    99  		t.Fatalf("error decoding hex hash: %s", ntlmHashHex)
   100  	}
   101  
   102  	ClientChallenge := []byte{0xff, 0xff, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44}
   103  	Time := []byte{0x00, 0x90, 0xd3, 0x36, 0xb7, 0x34, 0xc3, 0x01}
   104  	targetInfo := []byte{0x02, 0x00, 0x0c, 0x00, 0x44, 0x00, 0x4f, 0x00, 0x4d, 0x00, 0x41, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x53, 0x00, 0x45, 0x00, 0x52, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00, 0x04, 0x00, 0x14, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x03, 0x00, 0x22, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x2e, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00}
   105  
   106  	NTLMv2Hash := hmacMd5(hashBytes, toUnicode(strings.ToUpper(username)+target))
   107  
   108  	v := computeNtlmV2Response(NTLMv2Hash, challenge, ClientChallenge, Time, targetInfo)
   109  
   110  	if expected := []byte{
   111  		0xcb, 0xab, 0xbc, 0xa7, 0x13, 0xeb, 0x79, 0x5d, 0x04, 0xc9, 0x7a, 0xbc, 0x01, 0xee, 0x49, 0x83,
   112  		0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0xd3, 0x36, 0xb7, 0x34, 0xc3, 0x01,
   113  		0xff, 0xff, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0c, 0x00,
   114  		0x44, 0x00, 0x4f, 0x00, 0x4d, 0x00, 0x41, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x01, 0x00, 0x0c, 0x00,
   115  		0x53, 0x00, 0x45, 0x00, 0x52, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00, 0x04, 0x00, 0x14, 0x00,
   116  		0x64, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2e, 0x00, 0x63, 0x00,
   117  		0x6f, 0x00, 0x6d, 0x00, 0x03, 0x00, 0x22, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00,
   118  		0x65, 0x00, 0x72, 0x00, 0x2e, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00,
   119  		0x6e, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   120  		0x00, 0x00,
   121  	}; !bytes.Equal(v, expected) {
   122  		t.Fatalf("expected %x, got %x", expected, v)
   123  	}
   124  }
   125  
   126  func TestCalculateLMv2Response(t *testing.T) {
   127  	NTLMv2Hash := getNtlmV2Hash(password, username, target)
   128  	ClientChallenge := []byte{0xff, 0xff, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44}
   129  
   130  	v := computeLmV2Response(NTLMv2Hash, challenge, ClientChallenge)
   131  
   132  	if expected := []byte{
   133  		0xd6, 0xe6, 0x15, 0x2e, 0xa2, 0x5d, 0x03, 0xb7, 0xc6, 0xba, 0x66, 0x29, 0xc2, 0xd6, 0xaa, 0xf0, 0xff, 0xff, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44,
   134  	}; !bytes.Equal(v, expected) {
   135  		t.Fatalf("expected %x, got %x", expected, v)
   136  	}
   137  }
   138  
   139  func TestToUnicode(t *testing.T) {
   140  	v := toUnicode(password)
   141  	if expected := []byte{0x53, 0x00, 0x65, 0x00, 0x63, 0x00, 0x52, 0x00, 0x45, 0x00, 0x74, 0x00, 0x30, 0x00, 0x31, 0x00}; !bytes.Equal(v, expected) {
   142  		t.Fatalf("expected %v, got %v", expected, v)
   143  	}
   144  }
   145  
   146  func TestNTLMhash(t *testing.T) {
   147  	v := getNtlmHash(password)
   148  	if expected := []byte{0xcd, 0x06, 0xca, 0x7c, 0x7e, 0x10, 0xc9, 0x9b, 0x1d, 0x33, 0xb7, 0x48, 0x5a, 0x2e, 0xd8, 0x08}; !bytes.Equal(v, expected) {
   149  		t.Fatalf("expected %v, got %v", expected, v)
   150  	}
   151  }
   152  
   153  func TestNTLMv2Hash(t *testing.T) {
   154  	v := getNtlmV2Hash(password, username, target)
   155  	if expected := []byte{0x04, 0xb8, 0xe0, 0xba, 0x74, 0x28, 0x9c, 0xc5, 0x40, 0x82, 0x6b, 0xab, 0x1d, 0xee, 0x63, 0xae}; !bytes.Equal(v, expected) {
   156  		t.Fatalf("expected %v, got %v", expected, v)
   157  	}
   158  }
   159  

View as plain text