/* GSS-NTLM Copyright (C) 2013 Simo Sorce This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, see . */ #include #include #include #include #include #include #include "config.h" #include "../src/gssapi_ntlmssp.h" #include "../src/gss_ntlmssp.h" const char *hex_to_dump(const uint8_t *d, size_t s) { static char hex_to_dump_str[1536]; char format[] = " %02x"; size_t t, i, j, k, p; bool print_trail = false; bool next_line = false; if (s > 256) t = 256; else t = s; for (i = 0, p = 0; i < t; i++) { snprintf(&hex_to_dump_str[p], 4, format, d[i]); p += 3; k = (i + 1) % 16; if (i + 1 == t) { print_trail = true; next_line = false; } else if (k == 0) { print_trail = true; next_line = true; } if (print_trail) { for (j = 16 - k + 1; j > 0; j--) { hex_to_dump_str[p++] = ' '; hex_to_dump_str[p++] = ' '; hex_to_dump_str[p++] = ' '; } hex_to_dump_str[p++] = '|'; if (k == 0) k = 16; for (j = 0; j < 16; j++) { if (k > 0) { if (isalnum(d[j])) hex_to_dump_str[p++] = d[j]; else hex_to_dump_str[p++] = '.'; k--; } else hex_to_dump_str[p++] = ' '; } hex_to_dump_str[p++] = '|'; print_trail = false; } if (next_line) { hex_to_dump_str[p++] = '\n'; hex_to_dump_str[p] = '\0'; next_line = false; } } if (t < s) { snprintf(&hex_to_dump_str[p], 7, " [..]\n"); } else if (hex_to_dump_str[p] != '\n') { hex_to_dump_str[p] = '\n'; hex_to_dump_str[p + 1] = '\0'; } return hex_to_dump_str; } static int test_difference(const char *text, const void *expected, size_t expected_len, const void *obtained, size_t obtained_len) { if (expected_len == 0) expected_len = strlen((const char *)expected); if (obtained_len == 0) obtained_len = strlen((const char *)obtained); if ((expected_len != obtained_len) || (memcmp(expected, obtained, expected_len) != 0)) { fprintf(stderr, "%s differ!\n", text); fprintf(stderr, "expected\n%s", hex_to_dump(expected, expected_len)); fprintf(stderr, "obtained\n%s", hex_to_dump(obtained, obtained_len)); return EINVAL; } return 0; } static int test_buffers(const char *text, struct ntlm_buffer *expected, struct ntlm_buffer *obtained) { return test_difference(text, expected->data, expected->length, obtained->data, obtained->length); } static int test_keys(const char *text, struct ntlm_key *expected, struct ntlm_key *obtained) { return test_difference(text, expected->data, expected->length, obtained->data, obtained->length); } /* Test Data as per para 4.2 of MS-NLMP */ const char *T_User = "User"; const char *T_UserDom = "Domain"; const char *T_Passwd = "Password"; const char *T_Server_Name = "Server"; const char *T_Workstation = "COMPUTER"; uint8_t T_RandomSessionKey[] = { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }; uint64_t T_time = 0; uint8_t T_ClientChallenge[] = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }; uint8_t T_ServerChallenge[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; /* NTLMv1 Auth Test Data */ struct { struct ntlm_key ResponseKeyLM; struct ntlm_key ResponseKeyNT; struct ntlm_key SessionBaseKey; uint8_t LMv1Response[24]; uint8_t NTLMv1Response[24]; struct ntlm_key KeyExchangeKey; struct ntlm_key EncryptedSessionKey1; struct ntlm_key EncryptedSessionKey2; struct ntlm_key EncryptedSessionKey3; uint32_t ChallengeFlags; uint8_t ChallengeMessage[0x44]; uint8_t AuthenticateMessage[0xAC]; } T_NTLMv1 = { { .data = { 0xe5, 0x2c, 0xac, 0x67, 0x41, 0x9a, 0x9a, 0x22, 0x4a, 0x3b, 0x10, 0x8f, 0x3f, 0xa6, 0xcb, 0x6d }, .length = 16 }, { .data = { 0xa4, 0xf4, 0x9c, 0x40, 0x65, 0x10, 0xbd, 0xca, 0xb6, 0x82, 0x4e, 0xe7, 0xc3, 0x0f, 0xd8, 0x52 }, .length = 16 }, { .data = { 0xd8, 0x72, 0x62, 0xb0, 0xcd, 0xe4, 0xb1, 0xcb, 0x74, 0x99, 0xbe, 0xcc, 0xcd, 0xf1, 0x07, 0x84 }, .length = 16 }, { 0x98, 0xde, 0xf7, 0xb8, 0x7f, 0x88, 0xaa, 0x5d, 0xaf, 0xe2, 0xdf, 0x77, 0x96, 0x88, 0xa1, 0x72, 0xde, 0xf1, 0x1c, 0x7d, 0x5c, 0xcd, 0xef, 0x13 }, { 0x67, 0xc4, 0x30, 0x11, 0xf3, 0x02, 0x98, 0xa2, 0xad, 0x35, 0xec, 0xe6, 0x4f, 0x16, 0x33, 0x1c, 0x44, 0xbd, 0xbe, 0xd9, 0x27, 0x84, 0x1f, 0x94 }, { .data = { 0xb0, 0x9e, 0x37, 0x9f, 0x7f, 0xbe, 0xcb, 0x1e, 0xaf, 0x0a, 0xfd, 0xcb, 0x03, 0x83, 0xc8, 0xa0 }, .length = 16 }, { .data = { 0x51, 0x88, 0x22, 0xb1, 0xb3, 0xf3, 0x50, 0xc8, 0x95, 0x86, 0x82, 0xec, 0xbb, 0x3e, 0x3c, 0xb7 }, .length = 16 }, { .data = { 0x74, 0x52, 0xca, 0x55, 0xc2, 0x25, 0xa1, 0xca, 0x04, 0xb4, 0x8f, 0xae, 0x32, 0xcf, 0x56, 0xfc }, .length = 16 }, { .data = { 0x4c, 0xd7, 0xbb, 0x57, 0xd6, 0x97, 0xef, 0x9b, 0x54, 0x9f, 0x02, 0xb8, 0xf9, 0xb3, 0x78, 0x64 }, .length = 16 }, ( NTLMSSP_NEGOTIATE_56 | NTLMSSP_NEGOTIATE_KEY_EXCH | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_VERSION | NTLMSSP_TARGET_TYPE_SERVER | NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_OEM | NTLMSSP_NEGOTIATE_UNICODE ), { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x38, 0x00, 0x00, 0x00, 0x33, 0x82, 0x02, 0xe2, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x70, 0x17, 0x00, 0x00, 0x00, 0x0f, 0x53, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00 }, { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x84, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x48, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x54, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x35, 0x82, 0x80, 0xe2, 0x05, 0x01, 0x28, 0x0a, 0x00, 0x00, 0x00, 0x0f, 0x44, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x55, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x43, 0x00, 0x4f, 0x00, 0x4d, 0x00, 0x50, 0x00, 0x55, 0x00, 0x54, 0x00, 0x45, 0x00, 0x52, 0x00, 0x98, 0xde, 0xf7, 0xb8, 0x7f, 0x88, 0xaa, 0x5d, 0xaf, 0xe2, 0xdf, 0x77, 0x96, 0x88, 0xa1, 0x72, 0xde, 0xf1, 0x1c, 0x7d, 0x5c, 0xcd, 0xef, 0x13, 0x67, 0xc4, 0x30, 0x11, 0xf3, 0x02, 0x98, 0xa2, 0xad, 0x35, 0xec, 0xe6, 0x4f, 0x16, 0x33, 0x1c, 0x44, 0xbd, 0xbe, 0xd9, 0x27, 0x84, 0x1f, 0x94, 0x51, 0x88, 0x22, 0xb1, 0xb3, 0xf3, 0x50, 0xc8, 0x95, 0x86, 0x82, 0xec, 0xbb, 0x3e, 0x3c, 0xb7 } }; /* NTLMv2 Auth Test Data */ struct { uint32_t ChallengeFlags; uint8_t TargetInfo[36]; struct ntlm_key ResponseKeyNT; struct ntlm_key SessionBaseKey; uint8_t LMv2Response[16]; uint8_t NTLMv2Response[16]; struct ntlm_key EncryptedSessionKey; uint8_t ChallengeMessage[0x68]; uint8_t AuthenticateMessage[0xE8]; } T_NTLMv2 = { ( NTLMSSP_NEGOTIATE_56 | NTLMSSP_NEGOTIATE_KEY_EXCH | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_VERSION | NTLMSSP_NEGOTIATE_TARGET_INFO | NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY | NTLMSSP_TARGET_TYPE_SERVER | NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_OEM | NTLMSSP_NEGOTIATE_UNICODE ), { /* MSV_AV_NB_DOMAIN_NAME, 12 "D.o.m.a.i.n." */ 0x02, 0x00, 0x0c, 0x00, 0x44, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, /* MSV_AV_NB_COMPUTER_NAME, 12 "S.e.r.v.e.r." */ 0x01, 0x00, 0x0c, 0x00, 0x53, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, /* MSV_AV_EOL, 0 */ 0x00, 0x00, 0x00, 0x00 }, { .data = { 0x0c, 0x86, 0x8a, 0x40, 0x3b, 0xfd, 0x7a, 0x93, 0xa3, 0x00, 0x1e, 0xf2, 0x2e, 0xf0, 0x2e, 0x3f }, .length = 16 }, { .data = { 0x8d, 0xe4, 0x0c, 0xca, 0xdb, 0xc1, 0x4a, 0x82, 0xf1, 0x5c, 0xb0, 0xad, 0x0d, 0xe9, 0x5c, 0xa3 }, .length = 16 }, { 0x86, 0xc3, 0x50, 0x97, 0xac, 0x9c, 0xec, 0x10, 0x25, 0x54, 0x76, 0x4a, 0x57, 0xcc, 0xcc, 0x19 }, { 0x68, 0xcd, 0x0a, 0xb8, 0x51, 0xe5, 0x1c, 0x96, 0xaa, 0xbc, 0x92, 0x7b, 0xeb, 0xef, 0x6a, 0x1c }, { .data = { 0xc5, 0xda, 0xd2, 0x54, 0x4f, 0xc9, 0x79, 0x90, 0x94, 0xce, 0x1c, 0xe9, 0x0b, 0xc9, 0xd0, 0x3e }, .length = 16 }, { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x38, 0x00, 0x00, 0x00, 0x33, 0x82, 0x8a, 0xe2, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x24, 0x00, 0x44, 0x00, 0x00, 0x00, 0x06, 0x00, 0x70, 0x17, 0x00, 0x00, 0x00, 0x0f, 0x53, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x44, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x53, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x54, 0x00, 0x54, 0x00, 0x84, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x48, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x54, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x35, 0x82, 0x88, 0xe2, 0x05, 0x01, 0x28, 0x0a, 0x00, 0x00, 0x00, 0x0f, 0x44, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x55, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x43, 0x00, 0x4f, 0x00, 0x4d, 0x00, 0x50, 0x00, 0x55, 0x00, 0x54, 0x00, 0x45, 0x00, 0x52, 0x00, 0x86, 0xc3, 0x50, 0x97, 0xac, 0x9c, 0xec, 0x10, 0x25, 0x54, 0x76, 0x4a, 0x57, 0xcc, 0xcc, 0x19, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x68, 0xcd, 0x0a, 0xb8, 0x51, 0xe5, 0x1c, 0x96, 0xaa, 0xbc, 0x92, 0x7b, 0xeb, 0xef, 0x6a, 0x1c, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x44, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x53, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0xda, 0xd2, 0x54, 0x4f, 0xc9, 0x79, 0x90, 0x94, 0xce, 0x1c, 0xe9, 0x0b, 0xc9, 0xd0, 0x3e } }; /* NTLMv2 Auth with Channel Bindings Test Data */ struct { uint32_t ChallengeFlags; const char *User; const char *Password; const char *Domain; const char *Workstation; const char *Server; const char *DnsDomain; const char *DnsServer; const char *Forest; uint64_t ServerTime; uint8_t ServerChallenge[8]; struct ntlm_key NTLMHash; uint8_t TargetInfo[0xb6]; uint8_t ChallengeMessage[0xfe]; uint8_t AuthenticateMessage[0x228]; uint8_t MIC[16]; uint8_t CBSum[16]; } T_NTLMv2_CBT = { ( NTLMSSP_NEGOTIATE_56 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_VERSION | NTLMSSP_NEGOTIATE_TARGET_INFO | NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY | NTLMSSP_TARGET_TYPE_DOMAIN | NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_UNICODE ), "Administrator", "P@ssw0rd", "WS2008R2", "WIN7-2-PC", "DC-WS2008R2", "ws2008r2.local", "DC-ws2008r2.ws2008r2.local", "ws2008r2.local", 0x01cdde0bc33fe77b, { 0xa2, 0xc5, 0xe8, 0xca, 0x30, 0x84, 0xaa, 0x72 }, { .data = { 0xe1, 0x9c, 0xcf, 0x75, 0xee, 0x54, 0xe0, 0x6b, 0x06, 0xa5, 0x90, 0x7a, 0xf1, 0x3c, 0xef, 0x42 }, .length = 16 }, { 0x02, 0x00, 0x10, 0x00, 0x57, 0x00, 0x53, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x52, 0x00, 0x32, 0x00, 0x01, 0x00, 0x16, 0x00, 0x44, 0x00, 0x43, 0x00, 0x2d, 0x00, 0x57, 0x00, 0x53, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x52, 0x00, 0x32, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x77, 0x00, 0x73, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x72, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x03, 0x00, 0x34, 0x00, 0x44, 0x00, 0x43, 0x00, 0x2d, 0x00, 0x77, 0x00, 0x73, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x72, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x77, 0x00, 0x73, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x72, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x05, 0x00, 0x1c, 0x00, 0x77, 0x00, 0x73, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x72, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x7b, 0xe7, 0x3f, 0xc3, 0x0b, 0xde, 0xcd, 0x01, 0x00, 0x00, 0x00, 0x00 }, { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x38, 0x00, 0x00, 0x00, 0x05, 0x82, 0x89, 0xa2, 0xa2, 0xc5, 0xe8, 0xca, 0x30, 0x84, 0xaa, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb6, 0x00, 0xb6, 0x00, 0x48, 0x00, 0x00, 0x00, 0x06, 0x01, 0xb0, 0x1d, 0x00, 0x00, 0x00, 0x0f, 0x57, 0x00, 0x53, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x52, 0x00, 0x32, 0x00, 0x02, 0x00, 0x10, 0x00, 0x57, 0x00, 0x53, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x52, 0x00, 0x32, 0x00, 0x01, 0x00, 0x16, 0x00, 0x44, 0x00, 0x43, 0x00, 0x2d, 0x00, 0x57, 0x00, 0x53, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x52, 0x00, 0x32, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x77, 0x00, 0x73, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x72, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x03, 0x00, 0x34, 0x00, 0x44, 0x00, 0x43, 0x00, 0x2d, 0x00, 0x77, 0x00, 0x73, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x72, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x77, 0x00, 0x73, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x72, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x05, 0x00, 0x1c, 0x00, 0x77, 0x00, 0x73, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x72, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x7b, 0xe7, 0x3f, 0xc3, 0x0b, 0xde, 0xcd, 0x01, 0x00, 0x00, 0x00, 0x00 }, { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x94, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x7c, 0x01, 0xac, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x58, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x1a, 0x00, 0x68, 0x00, 0x00, 0x00, 0x12, 0x00, 0x12, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x02, 0x00, 0x00, 0x05, 0x82, 0x88, 0xa2, 0x06, 0x01, 0xb0, 0x1d, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x54, 0xa5, 0x42, 0xb0, 0x90, 0xb6, 0x6c, 0x1f, 0xea, 0x1a, 0x2c, 0xc8, 0x2e, 0x93, 0x0b, 0x57, 0x00, 0x53, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x52, 0x00, 0x32, 0x00, 0x41, 0x00, 0x64, 0x00, 0x6d, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x57, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x50, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x6a, 0x21, 0xae, 0x1a, 0x44, 0xc0, 0x44, 0x69, 0x3e, 0xee, 0x59, 0xfc, 0x5d, 0x81, 0xe0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xe7, 0x3f, 0xc3, 0x0b, 0xde, 0xcd, 0x01, 0x27, 0xfc, 0x11, 0x80, 0x82, 0xc2, 0xfb, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x57, 0x00, 0x53, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x52, 0x00, 0x32, 0x00, 0x01, 0x00, 0x16, 0x00, 0x44, 0x00, 0x43, 0x00, 0x2d, 0x00, 0x57, 0x00, 0x53, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x52, 0x00, 0x32, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x77, 0x00, 0x73, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x72, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x03, 0x00, 0x34, 0x00, 0x44, 0x00, 0x43, 0x00, 0x2d, 0x00, 0x77, 0x00, 0x73, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x72, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x77, 0x00, 0x73, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x72, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x05, 0x00, 0x1c, 0x00, 0x77, 0x00, 0x73, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x72, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x7b, 0xe7, 0x3f, 0xc3, 0x0b, 0xde, 0xcd, 0x01, 0x06, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x4d, 0x6b, 0x0d, 0x27, 0x54, 0x10, 0x22, 0xf5, 0xff, 0xa6, 0x73, 0xda, 0x2b, 0xfc, 0xfd, 0xf1, 0x94, 0x2f, 0x25, 0x7b, 0xe1, 0x1a, 0x49, 0xc9, 0x54, 0x19, 0x7a, 0xca, 0x8a, 0xaf, 0x2e, 0xaf, 0x0a, 0x00, 0x10, 0x00, 0x65, 0x86, 0xe9, 0x9d, 0x81, 0xc2, 0xfc, 0x98, 0x4e, 0x47, 0x17, 0x2f, 0xd4, 0xdd, 0x03, 0x10, 0x09, 0x00, 0x3e, 0x00, 0x48, 0x00, 0x54, 0x00, 0x54, 0x00, 0x50, 0x00, 0x2f, 0x00, 0x64, 0x00, 0x63, 0x00, 0x2d, 0x00, 0x77, 0x00, 0x73, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x72, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x77, 0x00, 0x73, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x72, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xf0, 0x54, 0xa5, 0x42, 0xb0, 0x90, 0xb6, 0x6c, 0x1f, 0xea, 0x1a, 0x2c, 0xc8, 0x2e, 0x93, 0x0b }, { 0x65, 0x86, 0xE9, 0x9D, 0x81, 0xC2, 0xFC, 0x98, 0x4E, 0x47, 0x17, 0x2F, 0xD4, 0xDD, 0x03, 0x10 }, }; struct t_gsswrapex_data { uint32_t flags; struct ntlm_buffer Plaintext; struct ntlm_key KeyExchangeKey; struct ntlm_key ClientSealKey; struct ntlm_key ClientSignKey; struct ntlm_buffer Ciphertext; struct ntlm_buffer Signature; }; /* Basic GSS_WrapEx V1 Test Data */ uint8_t T_GSSWRAPv1noESS_Plaintext_data[18] = { 0x50, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x78, 0x00, 0x74, 0x00 }; uint8_t T_GSSWRAPv1noESS_Ciphertext_data[18] = { 0x56, 0xfe, 0x04, 0xd8, 0x61, 0xf9, 0x31, 0x9a, 0xf0, 0xd7, 0x23, 0x8a, 0x2e, 0x3b, 0x4d, 0x45, 0x7f, 0xb8 }; uint8_t T_GSSWRAPv1noESS_Signature_data[16] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xdc, 0xd1, 0xdf, 0x2e, 0x45, 0x9d, 0x36 }; struct t_gsswrapex_data T_GSSWRAPv1noESS = { ( NTLMSSP_NEGOTIATE_56 | NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL ), { .data = T_GSSWRAPv1noESS_Plaintext_data, .length = sizeof(T_GSSWRAPv1noESS_Plaintext_data) }, { .data = { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }, .length = 16 }, { .data = { 0 }, .length = 0 }, { .data = { 0 }, .length = 0 }, { .data = T_GSSWRAPv1noESS_Ciphertext_data, .length = sizeof(T_GSSWRAPv1noESS_Ciphertext_data) }, { .data = T_GSSWRAPv1noESS_Signature_data, .length = sizeof(T_GSSWRAPv1noESS_Signature_data) }, }; /* GSS_WrapEx V1 Extended Session Security Test Data */ uint8_t T_GSSWRAPEXv1_Plaintext_data[18] = { 0x50, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x78, 0x00, 0x74, 0x00 }; uint8_t T_GSSWRAPEXv1_Ciphertext_data[18] = { 0xa0, 0x23, 0x72, 0xf6, 0x53, 0x02, 0x73, 0xf3, 0xaa, 0x1e, 0xb9, 0x01, 0x90, 0xce, 0x52, 0x00, 0xc9, 0x9d }; uint8_t T_GSSWRAPEXv1_Signature_data[16] = { 0x01, 0x00, 0x00, 0x00, 0xff, 0x2a, 0xeb, 0x52, 0xf6, 0x81, 0x79, 0x3a, 0x00, 0x00, 0x00, 0x00 }; struct t_gsswrapex_data T_GSSWRAPEXv1 = { ( NTLMSSP_NEGOTIATE_56 | NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY ), { .data = T_GSSWRAPEXv1_Plaintext_data, .length = sizeof(T_GSSWRAPEXv1_Plaintext_data) }, { .data = { 0xeb, 0x93, 0x42, 0x9a, 0x8b, 0xd9, 0x52, 0xf8, 0xb8, 0x9c, 0x55, 0xb8, 0x7f, 0x47, 0x5e, 0xdc }, .length = 16 }, { .data = { 0x04, 0xdd, 0x7f, 0x01, 0x4d, 0x85, 0x04, 0xd2, 0x65, 0xa2, 0x5c, 0xc8, 0x6a, 0x3a, 0x7c, 0x06 }, .length = 16 }, { .data = { 0x60, 0xe7, 0x99, 0xbe, 0x5c, 0x72, 0xfc, 0x92, 0x92, 0x2a, 0xe8, 0xeb, 0xe9, 0x61, 0xfb, 0x8d }, .length = 16 }, { .data = T_GSSWRAPEXv1_Ciphertext_data, .length = sizeof(T_GSSWRAPEXv1_Ciphertext_data) }, { .data = T_GSSWRAPEXv1_Signature_data, .length = sizeof(T_GSSWRAPEXv1_Signature_data) }, }; /* GSS_WrapEx V2 Test Data */ uint8_t T_GSSWRAPEXv2_Plaintext_data[18] = { 0x50, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x78, 0x00, 0x74, 0x00 }; uint8_t T_GSSWRAPEXv2_Ciphertext_data[18] = { 0x54, 0xe5, 0x01, 0x65, 0xbf, 0x19, 0x36, 0xdc, 0x99, 0x60, 0x20, 0xc1, 0x81, 0x1b, 0x0f, 0x06, 0xfb, 0x5f }; uint8_t T_GSSWRAPEXv2_Signature_data[16] = { 0x01, 0x00, 0x00, 0x00, 0x7f, 0xb3, 0x8e, 0xc5, 0xc5, 0x5d, 0x49, 0x76, 0x00, 0x00, 0x00, 0x00 }; struct t_gsswrapex_data T_GSSWRAPEXv2 = { ( NTLMSSP_NEGOTIATE_56 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_KEY_EXCH | NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY ), { .data = T_GSSWRAPEXv2_Plaintext_data, .length = sizeof(T_GSSWRAPEXv2_Plaintext_data) }, { .data = { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }, .length = 16 }, { .data = { 0x59, 0xf6, 0x00, 0x97, 0x3c, 0xc4, 0x96, 0x0a, 0x25, 0x48, 0x0a, 0x7c, 0x19, 0x6e, 0x4c, 0x58 }, .length = 16 }, { .data = { 0x47, 0x88, 0xdc, 0x86, 0x1b, 0x47, 0x82, 0xf3, 0x5d, 0x43, 0xfd, 0x98, 0xfe, 0x1a, 0x2d, 0x39 }, .length = 16 }, { .data = T_GSSWRAPEXv2_Ciphertext_data, .length = sizeof(T_GSSWRAPEXv2_Ciphertext_data) }, { .data = T_GSSWRAPEXv2_Signature_data, .length = sizeof(T_GSSWRAPEXv2_Signature_data) }, }; int test_LMOWFv1(struct ntlm_ctx *ctx) { struct ntlm_key result = { .length = 16 }; int ret; ret = LMOWFv1(T_Passwd, &result); if (ret) return ret; return test_keys("results", &T_NTLMv1.ResponseKeyLM, &result); } int test_NTOWFv1(struct ntlm_ctx *ctx) { struct ntlm_key result = { .length = 16 }; int ret; ret = NTOWFv1(T_Passwd, &result); if (ret) return ret; return test_keys("results", &T_NTLMv1.ResponseKeyNT, &result); } int test_SessionBaseKeyV1(struct ntlm_ctx *ctx) { struct ntlm_key session_base_key = { .length = 16 }; int ret; ret = ntlm_session_base_key(&T_NTLMv1.ResponseKeyNT, &session_base_key); if (ret) return ret; return test_keys("results", &T_NTLMv1.SessionBaseKey, &session_base_key); } int test_LMResponseV1(struct ntlm_ctx *ctx) { uint8_t buf[24]; struct ntlm_buffer result = { buf, 24 }; int ret; ret = ntlm_compute_lm_response(&T_NTLMv1.ResponseKeyLM, false, T_ServerChallenge, T_ClientChallenge, &result); if (ret) return ret; return test_difference("results", T_NTLMv1.LMv1Response, sizeof(T_NTLMv1.LMv1Response), result.data, result.length); } int test_NTResponseV1(struct ntlm_ctx *ctx) { uint8_t buf[24]; struct ntlm_buffer result = { buf, 24 }; int ret; ret = ntlm_compute_nt_response(&T_NTLMv1.ResponseKeyNT, false, T_ServerChallenge, T_ClientChallenge, &result); if (ret) return ret; return test_difference("results", T_NTLMv1.NTLMv1Response, sizeof(T_NTLMv1.NTLMv1Response), result.data, result.length); } int test_NTOWFv2(struct ntlm_ctx *ctx) { struct ntlm_key nt_hash = { .length = 16 }; struct ntlm_key result = { .length = 16 }; int ret; ret = NTOWFv1(T_Passwd, &nt_hash); if (ret) return ret; ret = NTOWFv2(ctx, &nt_hash, T_User, T_UserDom, &result); if (ret) return ret; return test_keys("results", &T_NTLMv2.ResponseKeyNT, &result); } int test_LMResponseV2(struct ntlm_ctx *ctx) { struct ntlm_buffer result; int ret; ret = ntlmv2_compute_lm_response(&T_NTLMv2.ResponseKeyNT, T_ServerChallenge, T_ClientChallenge, &result); if (ret) return ret; ret = test_difference("results", T_NTLMv2.LMv2Response, sizeof(T_NTLMv2.LMv2Response), result.data, sizeof(T_NTLMv2.LMv2Response)); free(result.data); return ret; } int test_NTResponseV2(struct ntlm_ctx *ctx) { struct ntlm_buffer target_info = { T_NTLMv2.TargetInfo, 36 }; struct ntlm_buffer result; int ret; ret = ntlmv2_compute_nt_response(&T_NTLMv2.ResponseKeyNT, T_ServerChallenge, T_ClientChallenge, T_time, &target_info, &result); if (ret) return ret; ret = test_difference("results", T_NTLMv2.NTLMv2Response, sizeof(T_NTLMv2.NTLMv2Response), result.data, sizeof(T_NTLMv2.NTLMv2Response)); free(result.data); return ret; } int test_SessionBaseKeyV2(struct ntlm_ctx *ctx) { struct ntlm_buffer nt_response = { T_NTLMv2.NTLMv2Response, 16 }; struct ntlm_key session_base_key = { .length = 16 }; int ret; ret = ntlmv2_session_base_key(&T_NTLMv2.ResponseKeyNT, &nt_response, &session_base_key); if (ret) return ret; return test_keys("results", &T_NTLMv2.SessionBaseKey, &session_base_key); } int test_EncryptedSessionKey(struct ntlm_ctx *ctx, struct ntlm_key *key_exchange_key, struct ntlm_key *encrypted_session_key) { struct ntlm_key exported_session_key = { .length = 16 }; struct ntlm_key encrypted_random_session_key = { .length = 16 }; int ret; memcpy(exported_session_key.data, T_RandomSessionKey, 16); ret = ntlm_encrypted_session_key(key_exchange_key, &exported_session_key, &encrypted_random_session_key); if (ret) return ret; return test_keys("results", encrypted_session_key, &encrypted_random_session_key); } int test_EncryptedSessionKey1(struct ntlm_ctx *ctx) { struct ntlm_buffer lm_response = { T_NTLMv1.LMv1Response, 24 }; struct ntlm_key key_exchnage_key = { .length = 16 }; int ret; ret = KXKEY(ctx, false, false, false, T_ServerChallenge, &T_NTLMv1.ResponseKeyLM, &T_NTLMv1.SessionBaseKey, &lm_response, &key_exchnage_key); if (ret) return ret; return test_EncryptedSessionKey(ctx, &key_exchnage_key, &T_NTLMv1.EncryptedSessionKey1); } int test_EncryptedSessionKey2(struct ntlm_ctx *ctx) { struct ntlm_buffer lm_response = { T_NTLMv1.LMv1Response, 24 }; struct ntlm_key key_exchnage_key = { .length = 16 }; int ret; ret = KXKEY(ctx, false, false, true, T_ServerChallenge, &T_NTLMv1.ResponseKeyLM, &T_NTLMv1.SessionBaseKey, &lm_response, &key_exchnage_key); if (ret) return ret; return test_EncryptedSessionKey(ctx, &key_exchnage_key, &T_NTLMv1.EncryptedSessionKey2); } int test_EncryptedSessionKey3(struct ntlm_ctx *ctx) { struct ntlm_buffer lm_response = { T_NTLMv1.LMv1Response, 24 }; struct ntlm_key key_exchnage_key = { .length = 16 }; int ret; ret = KXKEY(ctx, false, true, false, T_ServerChallenge, &T_NTLMv1.ResponseKeyLM, &T_NTLMv1.SessionBaseKey, &lm_response, &key_exchnage_key); if (ret) return ret; return test_EncryptedSessionKey(ctx, &key_exchnage_key, &T_NTLMv1.EncryptedSessionKey3); } int test_DecodeChallengeMessageV1(struct ntlm_ctx *ctx) { struct ntlm_buffer chal_msg = { T_NTLMv1.ChallengeMessage, 0x68 }; uint32_t type; uint32_t flags; char *target_name = NULL; uint8_t chal[8]; struct ntlm_buffer challenge = { chal, 8 }; int err; int ret; ret = ntlm_decode_msg_type(ctx, &chal_msg, &type); if (ret) return ret; if (type != 2) return EINVAL; ret = ntlm_decode_chal_msg(ctx, &chal_msg, &flags, &target_name, &challenge, NULL); if (ret) return ret; err = test_difference("flags", &T_NTLMv1.ChallengeFlags, 4, &flags, 4); if (err) ret = err; err = test_difference("Target Names", T_Server_Name, 0, target_name, 0); if (err) ret = err; err = test_difference("Challenges", T_ServerChallenge, 8, chal, 8); if (err) ret = err; free(target_name); return ret; } int test_EncodeChallengeMessageV1(struct ntlm_ctx *ctx) { struct ntlm_buffer challenge = { T_ServerChallenge, 8 }; struct ntlm_buffer message = { 0 }; int ret; ret = ntlm_encode_chal_msg(ctx, T_NTLMv1.ChallengeFlags, T_Server_Name, &challenge, NULL, &message); if (ret) return ret; ret = test_difference("Challenge Messages", T_NTLMv1.ChallengeMessage, sizeof(T_NTLMv1.ChallengeMessage), message.data, message.length); free(message.data); return ret; } int test_DecodeChallengeMessageV2(struct ntlm_ctx *ctx) { struct ntlm_buffer chal_msg = { T_NTLMv2.ChallengeMessage, sizeof(T_NTLMv2.ChallengeMessage) }; uint32_t type; uint32_t flags; char *target_name = NULL; uint8_t chal[8]; struct ntlm_buffer challenge = { chal, 8 }; struct ntlm_buffer target_info = { 0 }; int err; int ret; ret = ntlm_decode_msg_type(ctx, &chal_msg, &type); if (ret) return ret; if (type != 2) return EINVAL; ret = ntlm_decode_chal_msg(ctx, &chal_msg, &flags, &target_name, &challenge, &target_info); if (ret) return ret; err = test_difference("flags", &T_NTLMv2.ChallengeFlags, 4, &flags, 4); if (err) ret = err; err = test_difference("Target Names", T_Server_Name, 0, target_name, 0); if (err) ret = err; err = test_difference("Challenges", T_ServerChallenge, 8, chal, 8); if (err) ret = err; err = test_difference("Target Infos", T_NTLMv2.TargetInfo, 36, target_info.data, target_info.length); if (err) ret = err; free(target_name); free(target_info.data); return ret; } int test_EncodeChallengeMessageV2(struct ntlm_ctx *ctx) { struct ntlm_buffer challenge = { T_ServerChallenge, 8 }; struct ntlm_buffer target_info = { T_NTLMv2.TargetInfo, 36 }; struct ntlm_buffer message = { 0 }; int ret; ret = ntlm_encode_chal_msg(ctx, T_NTLMv2.ChallengeFlags, T_Server_Name, &challenge, &target_info, &message); if (ret) return ret; ret = test_difference("Challenge Messages", T_NTLMv2.ChallengeMessage, sizeof(T_NTLMv2.ChallengeMessage), message.data, message.length); free(message.data); return ret; } int test_DecodeAuthenticateMessageV2(struct ntlm_ctx *ctx) { struct ntlm_buffer auth_msg = { T_NTLMv2.AuthenticateMessage, 0xE8 }; uint32_t type; struct ntlm_buffer lm_chalresp = { 0 }; struct ntlm_buffer nt_chalresp = { 0 }; char *dom = NULL; char *usr = NULL; char *wks = NULL; struct ntlm_buffer enc_sess_key = { 0 }; int err; int ret; ret = ntlm_decode_msg_type(ctx, &auth_msg, &type); if (ret) return ret; if (type != 3) return EINVAL; ret = ntlm_decode_auth_msg(ctx, &auth_msg, T_NTLMv2.ChallengeFlags, &lm_chalresp, &nt_chalresp, &dom, &usr, &wks, &enc_sess_key, NULL, NULL); if (ret) return ret; if (lm_chalresp.length != 24) { fprintf(stderr, "Expected a 24 bytes long LM Challenge\n"); fprintf(stderr, "Obtained %s", hex_to_dump(lm_chalresp.data, lm_chalresp.length)); ret = EINVAL; } else { err = test_difference("LM Challenges", T_NTLMv2.LMv2Response, sizeof(T_NTLMv2.LMv2Response), lm_chalresp.data, sizeof(T_NTLMv2.LMv2Response)); if (err) ret = err; } if (nt_chalresp.length != 84) { fprintf(stderr, "Expected a 84 bytes long NT Challenge\n"); fprintf(stderr, "Obtained %s", hex_to_dump(nt_chalresp.data, nt_chalresp.length)); ret = EINVAL; } else { err = test_difference("NT Challenges", T_NTLMv2.NTLMv2Response, sizeof(T_NTLMv2.LMv2Response), nt_chalresp.data, sizeof(T_NTLMv2.LMv2Response)); if (err) ret = err; } err = test_difference("Domain Names", T_UserDom, 0, dom, 0); if (err) ret = err; err = test_difference("User Names", T_User, 0, usr, 0); if (err) ret = err; err = test_difference("Workstation Names", T_Workstation, 0, wks, 0); if (err) ret = err; err = test_difference("EncryptedSessionKey", T_NTLMv2.EncryptedSessionKey.data, T_NTLMv2.EncryptedSessionKey.length, enc_sess_key.data, enc_sess_key.length); if (err) ret = err; free(lm_chalresp.data); free(nt_chalresp.data); free(dom); free(usr); free(wks); free(enc_sess_key.data); return ret; } int test_EncodeAuthenticateMessageV2(struct ntlm_ctx *ctx) { int ret = 0; return ret; } int test_DecodeChallengeMessageV2CBT(struct ntlm_ctx *ctx) { struct ntlm_buffer chal_msg = { T_NTLMv2_CBT.ChallengeMessage, sizeof(T_NTLMv2_CBT.ChallengeMessage) }; uint32_t type; uint32_t flags; char *target_name = NULL; uint8_t chal[8]; struct ntlm_buffer challenge = { chal, 8 }; struct ntlm_buffer target_info = { 0 }; int err; int ret; ret = ntlm_decode_msg_type(ctx, &chal_msg, &type); if (ret) return ret; if (type != 2) return EINVAL; ret = ntlm_decode_chal_msg(ctx, &chal_msg, &flags, &target_name, &challenge, &target_info); if (ret) return ret; err = test_difference("flags", &T_NTLMv2_CBT.ChallengeFlags, 4, &flags, 4); if (err) ret = err; err = test_difference("Target Names", T_NTLMv2_CBT.Domain, 0, target_name, 0); if (err) ret = err; err = test_difference("Challenges", T_NTLMv2_CBT.ServerChallenge, sizeof(T_NTLMv2_CBT.ServerChallenge), chal, 8); if (err) ret = err; err = test_difference("Target Infos", T_NTLMv2_CBT.TargetInfo, sizeof(T_NTLMv2_CBT.TargetInfo), target_info.data, target_info.length); if (err) ret = err; free(target_name); free(target_info.data); return ret; } int test_EncodeChallengeMessageV2CBT(struct ntlm_ctx *ctx) { struct ntlm_buffer challenge = { T_NTLMv2_CBT.ServerChallenge, 8 }; struct ntlm_buffer target_info = { T_NTLMv2_CBT.TargetInfo, sizeof(T_NTLMv2_CBT.TargetInfo) }; struct ntlm_buffer message = { 0 }; int ret; ret = ntlm_encode_chal_msg(ctx, T_NTLMv2_CBT.ChallengeFlags, T_NTLMv2_CBT.Domain, &challenge, &target_info, &message); if (ret) return ret; ret = test_difference("Challenge Messages", T_NTLMv2_CBT.ChallengeMessage, sizeof(T_NTLMv2_CBT.ChallengeMessage), message.data, message.length); free(message.data); return ret; } int test_DecodeAuthenticateMessageV2CBT(struct ntlm_ctx *ctx) { struct ntlm_buffer auth_msg = { T_NTLMv2_CBT.AuthenticateMessage, sizeof(T_NTLMv2_CBT.AuthenticateMessage) }; uint32_t type; struct ntlm_buffer lm_chalresp = { 0 }; struct ntlm_buffer nt_chalresp = { 0 }; char *dom = NULL; char *usr = NULL; char *wks = NULL; struct ntlm_buffer enc_sess_key = { 0 }; uint8_t micdata[16]; struct ntlm_buffer mic = { micdata, 16 }; struct ntlm_key ntlmv2_key = { .length = 16 }; struct ntlm_buffer target_info = { 0 }; struct ntlm_buffer cb = { 0 }; int ret, c; int err; ret = ntlm_decode_msg_type(ctx, &auth_msg, &type); if (ret) return ret; if (type != 3) return EINVAL; ret = ntlm_decode_auth_msg(ctx, &auth_msg, T_NTLMv2_CBT.ChallengeFlags, &lm_chalresp, &nt_chalresp, &dom, &usr, &wks, &enc_sess_key, &target_info, &mic); if (ret) return ret; for (c = 1; lm_chalresp.length > c; c++) { lm_chalresp.data[0] |= lm_chalresp.data[c]; } if ((lm_chalresp.length != 24) || (lm_chalresp.data[0] != 0)) { fprintf(stderr, "LM Challenge too short[%zd] or not all zeros!\n", lm_chalresp.length); ret = EINVAL; } err = test_difference("Domain Names", T_NTLMv2_CBT.Domain, 0, dom, 0); if (err) ret = err; err = test_difference("User Names", T_NTLMv2_CBT.User, 0, usr, 0); if (err) ret = err; err = test_difference("Workstation Names", T_NTLMv2_CBT.Workstation, 0, wks, 0); if (err) ret = err; if (enc_sess_key.length != 0) { fprintf(stderr, "Encrypted Random Session Key not null (%zd)!\n", enc_sess_key.length); ret = EINVAL; } err = test_difference("MIC", T_NTLMv2_CBT.MIC, sizeof(T_NTLMv2_CBT.MIC), mic.data, mic.length); if (err) ret = err; ret = NTOWFv2(ctx, &T_NTLMv2_CBT.NTLMHash, T_NTLMv2_CBT.User, T_NTLMv2_CBT.Domain, &ntlmv2_key); if (ret) { fprintf(stderr, "NTLMv2 key generation failed!\n"); goto done; } ret = ntlmv2_verify_nt_response(&nt_chalresp, &ntlmv2_key, T_NTLMv2_CBT.ServerChallenge); if (ret) { fprintf(stderr, "NTLMv2 Verification failed!\n"); goto done; } ret = ntlm_decode_target_info(ctx, &target_info, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &cb); if (ret) { fprintf(stderr, "NTLMv2 failed to decode target info!\n"); goto done; } err = test_difference("CBTs", T_NTLMv2_CBT.CBSum, sizeof(T_NTLMv2_CBT.CBSum), cb.data, cb.length); if (err) ret = err; done: free(lm_chalresp.data); free(nt_chalresp.data); free(dom); free(usr); free(wks); free(enc_sess_key.data); free(target_info.data); return ret; } int test_GSS_Wrap_EX(struct ntlm_ctx *ctx, struct t_gsswrapex_data *data) { struct ntlm_signseal_state state; uint8_t outbuf[data->Ciphertext.length]; uint8_t signbuf[16]; struct ntlm_buffer output = { outbuf, data->Ciphertext.length }; struct ntlm_buffer signature = { signbuf, 16 }; int ret; int err; ret = ntlm_signseal_keys(data->flags, true, &data->KeyExchangeKey, &state); if (ret) return ret; if (data->ClientSealKey.length) { err = test_keys("Client Sealing Keys", &data->ClientSealKey, &state.send.seal_key); if (err) ret = err; } if (data->ClientSignKey.length) { err = test_keys("Client Signing Keys", &data->ClientSignKey, &state.send.sign_key); if (err) ret = err; } if (ret) return ret; ret = ntlm_seal(data->flags, &state, &data->Plaintext, &output, &signature); if (ret) { fprintf(stderr, "Sealing failed\n"); return ret; } err = test_buffers("Ciphertext", &data->Ciphertext, &output); if (err) ret = err; err = test_buffers("Signature", &data->Signature, &signature); if (err) ret = err; return ret; } #define TEST_USER_FILE "examples/test_user_file.txt" long seed = 0; static size_t repeatable_rand(uint8_t *buf, size_t max) { char *env_seed; size_t len; int i; if (seed == 0) { env_seed = getenv("NTLMSSPTEST_SEED"); if (env_seed) { seed = strtol(env_seed, NULL, 0); } else { seed = time(NULL); fprintf(stdout, "repeatable_rand seed = %ld\n", seed); } srandom(seed); } len = random() % max; if (len < 5) len = 5; for (i = 0; i < len; i++) { buf[i] = random(); } return len; } #define CASE(X) case X: return #X const char *gss_maj_to_str(uint32_t err) { switch (err) { CASE(GSS_S_COMPLETE); /* caling errors */ CASE(GSS_S_CALL_INACCESSIBLE_READ); CASE(GSS_S_CALL_INACCESSIBLE_WRITE); CASE(GSS_S_CALL_BAD_STRUCTURE); /* routine errors */ CASE(GSS_S_BAD_MECH); CASE(GSS_S_BAD_NAME); CASE(GSS_S_BAD_NAMETYPE); CASE(GSS_S_BAD_BINDINGS); CASE(GSS_S_BAD_STATUS); CASE(GSS_S_BAD_SIG); CASE(GSS_S_NO_CRED); CASE(GSS_S_NO_CONTEXT); CASE(GSS_S_DEFECTIVE_TOKEN); CASE(GSS_S_CREDENTIALS_EXPIRED); CASE(GSS_S_CONTEXT_EXPIRED); CASE(GSS_S_BAD_QOP); CASE(GSS_S_UNAUTHORIZED); CASE(GSS_S_UNAVAILABLE); CASE(GSS_S_DUPLICATE_ELEMENT); CASE(GSS_S_NAME_NOT_MN); CASE(GSS_S_BAD_MECH_ATTR); /* supplementary info */ CASE(GSS_S_CONTINUE_NEEDED); CASE(GSS_S_DUPLICATE_TOKEN); CASE(GSS_S_OLD_TOKEN); CASE(GSS_S_UNSEQ_TOKEN); CASE(GSS_S_GAP_TOKEN); default: return "Unknown Error"; } } static void print_min_status(uint32_t err) { gss_buffer_desc buf; uint32_t msgctx = 0; uint32_t retmaj; uint32_t retmin; do { retmaj = gssntlm_display_status(&retmin, err, GSS_C_MECH_CODE, NULL, &msgctx, &buf); if (retmaj) { fprintf(stderr, "!!gssntlm_display_status failed for err=%d", err); msgctx = 0; } else { fprintf(stderr, "%.*s%.*s", (int)buf.length, (char *)buf.value, msgctx, " "); (void)gss_release_buffer(&retmin, &buf); } } while (msgctx); } int test_Errors(void) { int i; for (i = ERR_BASE; i < ERR_LAST; i++) { fprintf(stderr, "%x: ", i); print_min_status(i); fprintf(stderr, "\n"); } return 0; } static void print_gss_error(const char *text, uint32_t maj, uint32_t min) { fprintf(stderr, "%s Major Error: [%s] Minor Error: [", text, gss_maj_to_str(maj)); print_min_status(min); fprintf(stderr, "]\n"); fflush(stderr); } int test_gssapi_1(bool user_env_file, bool use_cb, bool no_seal) { gss_ctx_id_t cli_ctx = GSS_C_NO_CONTEXT; gss_ctx_id_t srv_ctx = GSS_C_NO_CONTEXT; gss_buffer_desc cli_token = { 0 }; gss_buffer_desc srv_token = { 0 }; gss_cred_id_t cli_cred = GSS_C_NO_CREDENTIAL; gss_cred_id_t srv_cred = GSS_C_NO_CREDENTIAL; const char *username; const char *password = "testpassword"; const char *srvname = "test@testserver"; gss_name_t gss_username = NULL; gss_name_t gss_srvname = NULL; gss_buffer_desc pwbuf; gss_buffer_desc nbuf; uint32_t retmin, retmaj; const char *msg = "Sample, signature checking, message."; gss_buffer_desc message = { strlen(msg), discard_const(msg) }; gss_buffer_desc ctx_token; gss_OID actual_mech = GSS_C_NO_OID; uint8_t rand_cb[128]; struct gss_channel_bindings_struct cbts = { 0 }; gss_channel_bindings_t cbt = GSS_C_NO_CHANNEL_BINDINGS; uint32_t req_flags; int ret; setenv("NTLM_USER_FILE", TEST_USER_FILE, 0); if (user_env_file) { username = "testuser"; } else { username = "TESTDOM\\testuser"; } nbuf.value = discard_const(username); nbuf.length = strlen(username); retmaj = gssntlm_import_name(&retmin, &nbuf, GSS_C_NT_USER_NAME, &gss_username); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_import_name(username) failed!", retmaj, retmin); return EINVAL; } if (user_env_file) { retmaj = gssntlm_acquire_cred(&retmin, (gss_name_t)gss_username, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_INITIATE, &cli_cred, NULL, NULL); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_acquire_cred(username) failed!", retmaj, retmin); ret = EINVAL; goto done; } } else { pwbuf.value = discard_const(password); pwbuf.length = strlen(password); retmaj = gssntlm_acquire_cred_with_password(&retmin, (gss_name_t)gss_username, (gss_buffer_t)&pwbuf, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_INITIATE, &cli_cred, NULL, NULL); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_acquire_cred_with_password failed!", retmaj, retmin); ret = EINVAL; goto done; } } retmaj = gssntlm_inquire_cred_by_mech(&retmin, cli_cred, GSS_C_NO_OID, NULL, NULL, NULL, NULL); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_import_cred_by_mech failed!", retmaj, retmin); return EINVAL; } nbuf.value = discard_const(srvname); nbuf.length = strlen(srvname); retmaj = gssntlm_import_name(&retmin, &nbuf, GSS_C_NT_HOSTBASED_SERVICE, &gss_srvname); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_import_name(srvname) failed!", retmaj, retmin); return EINVAL; } retmaj = gssntlm_acquire_cred(&retmin, (gss_name_t)gss_srvname, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_ACCEPT, &srv_cred, NULL, NULL); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_acquire_cred(srvname) failed!", retmaj, retmin); ret = EINVAL; goto done; } if (use_cb) { /* generate random cb */ cbts.application_data.length = repeatable_rand(rand_cb, 128); cbts.application_data.value = rand_cb; cbt = &cbts; } if (no_seal) { req_flags = GSS_C_INTEG_FLAG; } else { req_flags = GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG; } retmaj = gssntlm_init_sec_context(&retmin, cli_cred, &cli_ctx, gss_srvname, GSS_C_NO_OID, req_flags, 0, cbt, GSS_C_NO_BUFFER, NULL, &cli_token, NULL, NULL); if (retmaj != GSS_S_CONTINUE_NEEDED) { print_gss_error("gssntlm_init_sec_context 1 failed!", retmaj, retmin); ret = EINVAL; goto done; } retmaj = gssntlm_accept_sec_context(&retmin, &srv_ctx, srv_cred, &cli_token, cbt, NULL, NULL, &srv_token, NULL, NULL, NULL); if (retmaj != GSS_S_CONTINUE_NEEDED) { print_gss_error("gssntlm_accept_sec_context 1 failed!", retmaj, retmin); ret = EINVAL; goto done; } gss_release_buffer(&retmin, &cli_token); /* test importing and exporting context before it is fully estabished */ retmaj = gssntlm_export_sec_context(&retmin, &srv_ctx, &ctx_token); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_export_sec_context 1 failed!", retmaj, retmin); ret = EINVAL; goto done; } retmaj = gssntlm_import_sec_context(&retmin, &ctx_token, &srv_ctx); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_import_sec_context 1 failed!", retmaj, retmin); ret = EINVAL; goto done; } gss_release_buffer(&retmin, &ctx_token); retmaj = gssntlm_init_sec_context(&retmin, cli_cred, &cli_ctx, gss_srvname, GSS_C_NO_OID, req_flags, 0, cbt, &srv_token, &actual_mech, &cli_token, NULL, NULL); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_init_sec_context 2 failed!", retmaj, retmin); ret = EINVAL; goto done; } if (!actual_mech) { fprintf(stderr, "Expected actual mech to be returned!\n"); ret = EINVAL; goto done; } actual_mech = GSS_C_NO_OID; gss_release_buffer(&retmin, &srv_token); retmaj = gssntlm_accept_sec_context(&retmin, &srv_ctx, srv_cred, &cli_token, cbt, NULL, &actual_mech, &srv_token, NULL, NULL, NULL); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_accept_sec_context 2 failed!", retmaj, retmin); ret = EINVAL; goto done; } if (!actual_mech) { fprintf(stderr, "Expected actual mech to be returned!\n"); ret = EINVAL; goto done; } actual_mech = GSS_C_NO_OID; gss_release_buffer(&retmin, &cli_token); gss_release_buffer(&retmin, &srv_token); /* test importing and exporting context after it is fully estabished */ retmaj = gssntlm_export_sec_context(&retmin, &cli_ctx, &ctx_token); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_export_sec_context 2 failed!", retmaj, retmin); ret = EINVAL; goto done; } retmaj = gssntlm_import_sec_context(&retmin, &ctx_token, &cli_ctx); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_import_sec_context 2 failed!", retmaj, retmin); ret = EINVAL; goto done; } gss_release_buffer(&retmin, &ctx_token); retmaj = gssntlm_get_mic(&retmin, cli_ctx, 0, &message, &cli_token); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_get_mic(cli) failed!", retmaj, retmin); ret = EINVAL; goto done; } retmaj = gssntlm_verify_mic(&retmin, srv_ctx, &message, &cli_token, NULL); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_verify_mic(srv) failed!", retmaj, retmin); ret = EINVAL; goto done; } gss_release_buffer(&retmin, &cli_token); retmaj = gssntlm_get_mic(&retmin, srv_ctx, 0, &message, &srv_token); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_get_mic(srv) failed!", retmaj, retmin); ret = EINVAL; goto done; } retmaj = gssntlm_verify_mic(&retmin, cli_ctx, &message, &srv_token, NULL); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_verify_mic(cli) failed!", retmaj, retmin); ret = EINVAL; goto done; } gss_release_buffer(&retmin, &srv_token); retmaj = gssntlm_wrap(&retmin, cli_ctx, 1, 0, &message, NULL, &cli_token); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_wrap(cli) failed!", retmaj, retmin); ret = EINVAL; goto done; } retmaj = gssntlm_unwrap(&retmin, srv_ctx, &cli_token, &srv_token, NULL, NULL); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_unwrap(srv) failed!", retmaj, retmin); ret = EINVAL; goto done; } if (memcmp(message.value, srv_token.value, srv_token.length) != 0) { print_gss_error("sealing and unsealing failed to return the " "same result", retmaj, retmin); ret = EINVAL; goto done; } gss_release_buffer(&retmin, &cli_token); gss_release_buffer(&retmin, &srv_token); gssntlm_release_name(&retmin, &gss_username); gssntlm_release_name(&retmin, &gss_srvname); retmaj = gssntlm_inquire_context(&retmin, srv_ctx, &gss_username, &gss_srvname, NULL, NULL, NULL, NULL, NULL); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_inquire_context failed!", retmaj, retmin); ret = EINVAL; goto done; } retmaj = gssntlm_display_name(&retmin, gss_username, &nbuf, NULL); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_display_name failed!", retmaj, retmin); ret = EINVAL; goto done; } if (strcmp(nbuf.value, "TESTDOM\\testuser") != 0) { fprintf(stderr, "Expected username of [%s] but got [%s] instead!\n", "TESTDOM\\testuser", (char *)nbuf.value); ret = EINVAL; goto done; } gss_release_buffer(&retmin, &nbuf); ret = 0; done: gssntlm_delete_sec_context(&retmin, &cli_ctx, GSS_C_NO_BUFFER); gssntlm_delete_sec_context(&retmin, &srv_ctx, GSS_C_NO_BUFFER); gssntlm_release_name(&retmin, &gss_username); gssntlm_release_name(&retmin, &gss_srvname); gssntlm_release_cred(&retmin, &cli_cred); gssntlm_release_cred(&retmin, &srv_cred); gss_release_buffer(&retmin, &cli_token); gss_release_buffer(&retmin, &srv_token); return ret; } int test_gssapi_cl(void) { gss_ctx_id_t cli_ctx = GSS_C_NO_CONTEXT; gss_ctx_id_t srv_ctx = GSS_C_NO_CONTEXT; gss_buffer_desc cli_token = { 0 }; gss_buffer_desc srv_token = { 0 }; gss_cred_id_t cli_cred = GSS_C_NO_CREDENTIAL; gss_cred_id_t srv_cred = GSS_C_NO_CREDENTIAL; const char *username = "TESTDOM\\testuser"; const char *password = "testpassword"; const char *srvname = "test@testserver"; gss_name_t gss_username = NULL; gss_name_t gss_srvname = NULL; gss_buffer_desc pwbuf; gss_buffer_desc nbuf; gss_OID_desc set_seqnum_oid = { GSS_NTLMSSP_SET_SEQ_NUM_OID_LENGTH, discard_const(GSS_NTLMSSP_SET_SEQ_NUM_OID_STRING) }; gss_buffer_desc set_seqnum_buf; uint32_t app_seq_num; uint32_t retmin, retmaj; const char *msg = "Sample, signature checking, message."; gss_buffer_desc message = { strlen(msg), discard_const(msg) }; int ret; setenv("NTLM_USER_FILE", TEST_USER_FILE, 0); nbuf.value = discard_const(username); nbuf.length = strlen(username); retmaj = gssntlm_import_name(&retmin, &nbuf, GSS_C_NT_USER_NAME, &gss_username); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_import_name(username) failed!", retmaj, retmin); return EINVAL; } pwbuf.value = discard_const(password); pwbuf.length = strlen(password); retmaj = gssntlm_acquire_cred_with_password(&retmin, (gss_name_t)gss_username, (gss_buffer_t)&pwbuf, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_INITIATE, &cli_cred, NULL, NULL); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_acquire_cred_with_password failed!", retmaj, retmin); return EINVAL; } nbuf.value = discard_const(srvname); nbuf.length = strlen(srvname); retmaj = gssntlm_import_name(&retmin, &nbuf, GSS_C_NT_HOSTBASED_SERVICE, &gss_srvname); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_import_name(srvname) failed!", retmaj, retmin); return EINVAL; } retmaj = gssntlm_acquire_cred(&retmin, (gss_name_t)gss_srvname, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_ACCEPT, &srv_cred, NULL, NULL); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_acquire_cred(srvname) failed!", retmaj, retmin); ret = EINVAL; goto done; } retmaj = gssntlm_accept_sec_context(&retmin, &srv_ctx, srv_cred, &cli_token, GSS_C_NO_CHANNEL_BINDINGS, NULL, NULL, &srv_token, NULL, NULL, NULL); if (retmaj != GSS_S_CONTINUE_NEEDED) { print_gss_error("gssntlm_accept_sec_context 1 failed!", retmaj, retmin); ret = EINVAL; goto done; } gss_release_buffer(&retmin, &cli_token); retmaj = gssntlm_init_sec_context(&retmin, cli_cred, &cli_ctx, gss_srvname, GSS_C_NO_OID, GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG | GSS_C_DATAGRAM_FLAG, 0, GSS_C_NO_CHANNEL_BINDINGS, &srv_token, NULL, &cli_token, NULL, NULL); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_init_sec_context 1 failed!", retmaj, retmin); ret = EINVAL; goto done; } gss_release_buffer(&retmin, &srv_token); retmaj = gssntlm_accept_sec_context(&retmin, &srv_ctx, srv_cred, &cli_token, GSS_C_NO_CHANNEL_BINDINGS, NULL, NULL, &srv_token, NULL, NULL, NULL); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_accept_sec_context 2 failed!", retmaj, retmin); ret = EINVAL; goto done; } /* TODO: again with channel bindings */ gss_release_buffer(&retmin, &cli_token); gss_release_buffer(&retmin, &srv_token); /* arbitrary seq number forced on the context */ app_seq_num = 10; set_seqnum_buf.value = &app_seq_num; set_seqnum_buf.length = 4; retmaj = gssntlm_set_sec_context_option(&retmin, (gss_ctx_id_t *)&cli_ctx, &set_seqnum_oid, &set_seqnum_buf); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_set_sec_context_option(cli) failed!", retmaj, retmin); ret = EINVAL; goto done; } retmaj = gssntlm_set_sec_context_option(&retmin, (gss_ctx_id_t *)&srv_ctx, &set_seqnum_oid, &set_seqnum_buf); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_set_sec_context_option(srv) failed!", retmaj, retmin); ret = EINVAL; goto done; } retmaj = gssntlm_get_mic(&retmin, cli_ctx, 0, &message, &cli_token); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_get_mic(cli) failed!", retmaj, retmin); ret = EINVAL; goto done; } retmaj = gssntlm_verify_mic(&retmin, srv_ctx, &message, &cli_token, NULL); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_verify_mic(srv) failed!", retmaj, retmin); ret = EINVAL; goto done; } gss_release_buffer(&retmin, &cli_token); retmaj = gssntlm_get_mic(&retmin, srv_ctx, 0, &message, &srv_token); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_get_mic(srv) failed!", retmaj, retmin); ret = EINVAL; goto done; } retmaj = gssntlm_verify_mic(&retmin, cli_ctx, &message, &srv_token, NULL); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_verify_mic(cli) failed!", retmaj, retmin); ret = EINVAL; goto done; } gss_release_buffer(&retmin, &srv_token); retmaj = gssntlm_wrap(&retmin, cli_ctx, 1, 0, &message, NULL, &cli_token); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_wrap(cli) failed!", retmaj, retmin); ret = EINVAL; goto done; } retmaj = gssntlm_unwrap(&retmin, srv_ctx, &cli_token, &srv_token, NULL, NULL); if (retmaj != GSS_S_COMPLETE) { print_gss_error("gssntlm_unwrap(srv) failed!", retmaj, retmin); ret = EINVAL; goto done; } if (memcmp(message.value, srv_token.value, srv_token.length) != 0) { print_gss_error("sealing and unsealing failed to return the " "same result", retmaj, retmin); ret = EINVAL; goto done; } gss_release_buffer(&retmin, &cli_token); gss_release_buffer(&retmin, &srv_token); gssntlm_release_name(&retmin, &gss_username); gssntlm_release_name(&retmin, &gss_srvname); ret = 0; done: gssntlm_delete_sec_context(&retmin, &cli_ctx, GSS_C_NO_BUFFER); gssntlm_delete_sec_context(&retmin, &srv_ctx, GSS_C_NO_BUFFER); gssntlm_release_name(&retmin, &gss_username); gssntlm_release_name(&retmin, &gss_srvname); gssntlm_release_cred(&retmin, &cli_cred); gssntlm_release_cred(&retmin, &srv_cred); gss_release_buffer(&retmin, &cli_token); gss_release_buffer(&retmin, &srv_token); return ret; } int main(int argc, const char *argv[]) { struct ntlm_ctx *ctx; int ret; /* enable trace debugging by dfault in tests */ setenv("GSSNTLMSSP_DEBUG", "tests-trace.log", 0); fprintf(stdout, "Test errors\n"); ret = test_Errors(); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); ret = ntlm_init_ctx(&ctx); if (ret) goto done; fprintf(stdout, "Test LMOWFv1\n"); ret = test_LMOWFv1(ctx); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test NTOWFv1\n"); ret = test_NTOWFv1(ctx); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test LMResponse v1\n"); ret = test_LMResponseV1(ctx); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test NTResponse v1\n"); ret = test_NTResponseV1(ctx); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test SessionBaseKey v1\n"); ret = test_SessionBaseKeyV1(ctx); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test EncryptedSessionKey v1 (1)\n"); ret = test_EncryptedSessionKey1(ctx); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test EncryptedSessionKey v1 (2)\n"); ret = test_EncryptedSessionKey2(ctx); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test EncryptedSessionKey v1 (3)\n"); ret = test_EncryptedSessionKey3(ctx); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); /* override internal version for V1 test vector */ ntlm_internal_set_version(6, 0, 6000, 15); fprintf(stdout, "Test decoding ChallengeMessage v1\n"); ret = test_DecodeChallengeMessageV1(ctx); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test encoding ChallengeMessage v1\n"); ret = test_EncodeChallengeMessageV1(ctx); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test LMResponse v2\n"); ret = test_LMResponseV2(ctx); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test NTResponse v2\n"); ret = test_NTResponseV2(ctx); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test SessionBaseKey v2\n"); ret = test_SessionBaseKeyV2(ctx); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test EncryptedSessionKey v2\n"); ret = test_EncryptedSessionKey(ctx, &T_NTLMv2.SessionBaseKey, &T_NTLMv2.EncryptedSessionKey); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); /* override internal version for V2 test vector */ ntlm_internal_set_version(6, 0, 6000, 15); fprintf(stdout, "Test decoding ChallengeMessage v2\n"); ret = test_DecodeChallengeMessageV2(ctx); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test encoding ChallengeMessage v2\n"); ret = test_EncodeChallengeMessageV2(ctx); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test decoding AuthenticateMessage v2\n"); ret = test_DecodeAuthenticateMessageV2(ctx); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test encoding AuthenticateMessage v2\n"); ret = test_EncodeAuthenticateMessageV2(ctx); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); /* override internal version for CBT test vector */ ntlm_internal_set_version(6, 1, 7600, 15); fprintf(stdout, "Test decoding ChallengeMessage v2 with CBT\n"); ret = test_DecodeChallengeMessageV2CBT(ctx); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test encoding ChallengeMessage v2 with CBT\n"); ret = test_EncodeChallengeMessageV2CBT(ctx); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test decoding AuthenticateMessage v2 with CBT\n"); ret = test_DecodeAuthenticateMessageV2CBT(ctx); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test sealing a Message with No Extended Security\n"); ret = test_GSS_Wrap_EX(ctx, &T_GSSWRAPv1noESS); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test sealing a Message with NTLMv1 Extended Security\n"); ret = test_GSS_Wrap_EX(ctx, &T_GSSWRAPEXv1); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test sealing a Message with NTLMv2 Extended Security\n"); ret = test_GSS_Wrap_EX(ctx, &T_GSSWRAPEXv2); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, " *** Test with NTLMv1 auth"); setenv("LM_COMPAT_LEVEL", "0", 1); fprintf(stdout, "Test GSSAPI conversation (user env file)\n"); ret = test_gssapi_1(true, false, false); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test GSSAPI conversation (no SEAL)\n"); ret = test_gssapi_1(true, false, true); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test GSSAPI conversation (with password)\n"); ret = test_gssapi_1(false, false, false); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test Connectionless exchange\n"); ret = test_gssapi_cl(); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, " *** Again forcing NTLMv2 auth"); setenv("LM_COMPAT_LEVEL", "5", 1); fprintf(stdout, "Test GSSAPI conversation (user env file)\n"); ret = test_gssapi_1(true, false, false); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test GSSAPI conversation (no SEAL)\n"); ret = test_gssapi_1(true, false, true); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test GSSAPI conversation (with password)\n"); ret = test_gssapi_1(false, false, false); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test GSSAPI conversation (with CB)\n"); ret = test_gssapi_1(false, true, false); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); fprintf(stdout, "Test Connectionless exchange\n"); ret = test_gssapi_cl(); fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS")); done: ntlm_free_ctx(&ctx); return ret; }