iPXE
ntlm_test.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2017 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26/** @file
27 *
28 * NTLM authentication self-tests
29 *
30 * The test vectors are taken from the MS-NLMP specification document.
31 *
32 */
33
34/* Forcibly enable assertions */
35#undef NDEBUG
36
37#include <stdlib.h>
38#include <string.h>
39#include <byteswap.h>
40#include <ipxe/ntlm.h>
41#include <ipxe/test.h>
42
43/** A key generation test */
45 /** Domain name (or NULL) */
46 const char *domain;
47 /** User name (or NULL) */
48 const char *username;
49 /** Password (or NULL) */
50 const char *password;
51 /** Expected key */
53};
54
55/** An authentication test */
57 /** Domain name (or NULL) */
58 const char *domain;
59 /** User name (or NULL) */
60 const char *username;
61 /** Password (or NULL) */
62 const char *password;
63 /** Workstation (or NULL) */
64 const char *workstation;
65 /** Nonce */
67 /** Challenge message */
69 /** Length of Challenge message */
71 /** Expected Authenticate message */
73 /** Expected length of Authenticate message */
75};
76
77/** Define inline message data */
78#define DATA(...) { __VA_ARGS__ }
79
80/** Define a key generation digest test */
81#define KEY_TEST( name, DOMAIN, USERNAME, PASSWORD, EXPECTED ) \
82 static struct ntlm_key_test name = { \
83 .domain = DOMAIN, \
84 .username = USERNAME, \
85 .password = PASSWORD, \
86 .expected = { \
87 .raw = EXPECTED, \
88 }, \
89 };
90
91/** Define an authentication test */
92#define AUTHENTICATE_TEST( name, DOMAIN, USERNAME, PASSWORD, \
93 WORKSTATION, NONCE, CHALLENGE, EXPECTED ) \
94 static const uint8_t name ## _challenge[] = CHALLENGE; \
95 static const uint8_t name ## _expected[] = EXPECTED; \
96 static struct ntlm_authenticate_test name = { \
97 .domain = DOMAIN, \
98 .username = USERNAME, \
99 .password = PASSWORD, \
100 .workstation = WORKSTATION, \
101 .nonce = { \
102 .raw = NONCE, \
103 }, \
104 .challenge = ( ( void * ) name ## _challenge ), \
105 .challenge_len = sizeof ( name ## _challenge ), \
106 .expected = ( ( void * ) name ## _expected ), \
107 .expected_len = sizeof ( name ## _expected ), \
108 };
109
110/** NTOWFv2() test from MS-NLMP specification */
111KEY_TEST ( msnlmp_ntowfv2, "Domain", "User", "Password",
112 DATA ( 0x0c, 0x86, 0x8a, 0x40, 0x3b, 0xfd, 0x7a, 0x93, 0xa3, 0x00,
113 0x1e, 0xf2, 0x2e, 0xf0, 0x2e, 0x3f ) );
114
115/** Authentication test from MS-NLMP specification */
116AUTHENTICATE_TEST ( msnlmp_authenticate,
117 "Domain", "User", "Password", "COMPUTER",
118 DATA ( 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa ),
119 DATA ( 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00,
120 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x38, 0x00, 0x00, 0x00,
121 0x33, 0x82, 0x8a, 0xe2, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab,
122 0xcd, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
123 0x24, 0x00, 0x24, 0x00, 0x44, 0x00, 0x00, 0x00, 0x06, 0x00,
124 0x70, 0x17, 0x00, 0x00, 0x00, 0x0f, 0x53, 0x00, 0x65, 0x00,
125 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x02, 0x00,
126 0x0c, 0x00, 0x44, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00,
127 0x69, 0x00, 0x6e, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x53, 0x00,
128 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00,
129 0x00, 0x00, 0x00, 0x00 ),
130 DATA ( 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x03, 0x00,
131 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x6c, 0x00, 0x00, 0x00,
132 0x54, 0x00, 0x54, 0x00, 0x84, 0x00, 0x00, 0x00, 0x0c, 0x00,
133 0x0c, 0x00, 0x48, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00,
134 0x54, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x5c, 0x00,
135 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0xd8, 0x00, 0x00, 0x00,
136 0x35, 0x82, 0x88, 0xe2, 0x05, 0x01, 0x28, 0x0a, 0x00, 0x00,
137 0x00, 0x0f, 0x44, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00,
138 0x69, 0x00, 0x6e, 0x00, 0x55, 0x00, 0x73, 0x00, 0x65, 0x00,
139 0x72, 0x00, 0x43, 0x00, 0x4f, 0x00, 0x4d, 0x00, 0x50, 0x00,
140 0x55, 0x00, 0x54, 0x00, 0x45, 0x00, 0x52, 0x00, 0x86, 0xc3,
141 0x50, 0x97, 0xac, 0x9c, 0xec, 0x10, 0x25, 0x54, 0x76, 0x4a,
142 0x57, 0xcc, 0xcc, 0x19, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
143 0xaa, 0xaa, 0x68, 0xcd, 0x0a, 0xb8, 0x51, 0xe5, 0x1c, 0x96,
144 0xaa, 0xbc, 0x92, 0x7b, 0xeb, 0xef, 0x6a, 0x1c, 0x01, 0x01,
145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
147 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0c, 0x00,
148 0x44, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00,
149 0x6e, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x53, 0x00, 0x65, 0x00,
150 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00,
151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0xda, 0xd2, 0x54,
152 0x4f, 0xc9, 0x79, 0x90, 0x94, 0xce, 0x1c, 0xe9, 0x0b, 0xc9,
153 0xd0, 0x3e ) );
154
155/**
156 * Report key generation test result
157 *
158 * @v test Key generation test
159 * @v file Test code file
160 * @v line Test code line
161 */
162static void ntlm_key_okx ( struct ntlm_key_test *test,
163 const char *file, unsigned int line ) {
164 struct ntlm_key key;
165
166 ntlm_key ( test->domain, test->username, test->password, &key );
167 okx ( memcmp ( &key, &test->expected, sizeof ( key ) ) == 0,
168 file, line );
169}
170#define ntlm_key_ok( test ) \
171 ntlm_key_okx ( test, __FILE__, __LINE__ )
172
173/**
174 * Report NTLM variable-length data test result
175 *
176 * @v msg Message header
177 * @v msg_len Length of message
178 * @v data Variable-length data descriptor
179 * @v expected Expected message header
180 * @v expected_data Expected variable-length data descriptor
181 * @v field Field name
182 * @v file Test code file
183 * @v line Test code line
184 */
185static void ntlm_data_okx ( struct ntlm_header *msg, size_t msg_len,
186 struct ntlm_data *data,
187 struct ntlm_header *expected,
188 struct ntlm_data *expected_data,
189 const char *field, const char *file,
190 unsigned int line ) {
191 size_t offset;
192 size_t len;
193 void *raw;
194 void *expected_raw;
195
196 /* Verify data lies within message */
197 okx ( data->len == data->max_len, file, line );
198 offset = le32_to_cpu ( data->offset );
199 len = le16_to_cpu ( data->len );
200 okx ( offset <= msg_len, file, line );
201 okx ( len <= ( msg_len - offset ), file, line );
202
203 /* Verify content matches expected content */
204 raw = ( ( ( void * ) msg ) + offset );
205 expected_raw = ( ( ( void * ) expected ) +
206 le32_to_cpu ( expected_data->offset ) );
207 DBGC ( msg, "NTLM %s expected:\n", field );
208 DBGC_HDA ( msg, 0, expected_raw, le16_to_cpu ( expected_data->len ) );
209 DBGC ( msg, "NTLM %s actual:\n", field );
210 DBGC_HDA ( msg, 0, raw, len );
211 okx ( data->len == expected_data->len, file, line );
212 okx ( memcmp ( raw, expected_raw, len ) == 0, file, line );
213}
214#define ntlm_data_ok( msg, msg_len, data, expected, expected_data ) \
215 ntlm_data_okx ( msg, msg_len, data, expected, expected_data, \
216 __FILE__, __LINE__ )
217
218/**
219 * Report NTLM authentication test result
220 *
221 * @v test Authentication test
222 * @v file Test code file
223 * @v line Test code line
224 */
226 const char *file, unsigned int line ) {
227 struct ntlm_authenticate *expected = test->expected;
229 struct ntlm_authenticate *auth;
230 struct ntlm_key key;
231 struct ntlm_lm_response lm;
232 struct ntlm_nt_response nt;
233 size_t len;
234
235 /* Parse Challenge message */
236 okx ( ntlm_challenge ( test->challenge, test->challenge_len,
237 &info ) == 0, file, line );
238
239 /* Generate key */
240 ntlm_key ( test->domain, test->username, test->password, &key );
241
242 /* Generate responses */
243 ntlm_response ( &info, &key, &test->nonce, &lm, &nt );
244
245 /* Allocate buffer for Authenticate message */
246 len = ntlm_authenticate_len ( &info, test->domain, test->username,
247 test->workstation );
248 okx ( len >= sizeof ( *auth ), file, line );
249 auth = malloc ( len );
250 okx ( auth != NULL, file, line );
251
252 /* Construct Authenticate message */
253 okx ( ntlm_authenticate ( &info, test->domain, test->username,
254 test->workstation, &lm, &nt, auth ) == len,
255 file, line );
256
257 /* Verify header */
258 okx ( memcmp ( &auth->header, &expected->header,
259 sizeof ( auth->header ) ) == 0, file, line );
260
261 /* Verify LAN Manager response */
262 ntlm_data_okx ( &auth->header, len, &auth->lm, &expected->header,
263 &expected->lm, "LM", file, line );
264
265 /* Verify NT response */
266 ntlm_data_okx ( &auth->header, len, &auth->nt, &expected->header,
267 &expected->nt, "NT", file, line );
268
269 /* Verify domain name */
270 ntlm_data_okx ( &auth->header, len, &auth->domain, &expected->header,
271 &expected->domain, "domain", file, line );
272
273 /* Verify user name */
274 ntlm_data_okx ( &auth->header, len, &auth->user, &expected->header,
275 &expected->user, "user", file, line );
276
277 /* Verify workstation name */
278 ntlm_data_okx ( &auth->header, len, &auth->workstation,
279 &expected->header, &expected->workstation,
280 "workstation",file, line );
281
282 /* Verify session key */
283 if ( auth->flags & NTLM_NEGOTIATE_KEY_EXCH ) {
284 ntlm_data_okx ( &auth->header, len, &auth->session,
285 &expected->header, &expected->session,
286 "session", file, line );
287 }
288
289 /* Free Authenticate message */
290 free ( auth );
291}
292#define ntlm_authenticate_ok( test ) \
293 ntlm_authenticate_okx ( test, __FILE__, __LINE__ )
294
295/**
296 * Perform NTLM self-test
297 *
298 */
299static void ntlm_test_exec ( void ) {
300
301 /* Verify key generation */
302 ntlm_key_ok ( &msnlmp_ntowfv2 );
303
304 /* Verify authentication response */
305 ntlm_authenticate_ok ( &msnlmp_authenticate );
306}
307
308/** NTLM self-test */
309struct self_test ntlm_test __self_test = {
310 .name = "ntlm",
311 .exec = ntlm_test_exec,
312};
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
union @162305117151260234136356364136041353210355154177 key
Sense key.
Definition scsi.h:3
__be32 raw[7]
Definition CIB_PRM.h:0
#define DATA(...)
Define inline data.
Definition acpi_test.c:74
u32 info
Definition ar9003_mac.h:0
uint16_t offset
Offset to command line.
Definition bzimage.h:3
ring len
Length.
Definition dwmac.h:226
uint8_t data[48]
Additional event data.
Definition ena.h:11
static int test
Definition epic100.c:73
#define DBGC(...)
Definition compiler.h:505
#define DBGC_HDA(...)
Definition compiler.h:506
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define le16_to_cpu(value)
Definition byteswap.h:113
#define le32_to_cpu(value)
Definition byteswap.h:114
String functions.
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:621
void msg(unsigned int row, const char *fmt,...)
Print message centred on specified row.
Definition message.c:62
struct mschapv2_nt_response nt
NT response.
Definition mschapv2.h:5
void ntlm_response(struct ntlm_challenge_info *info, struct ntlm_key *key, struct ntlm_nonce *nonce, struct ntlm_lm_response *lm, struct ntlm_nt_response *nt)
Construct NTLM responses.
Definition ntlm.c:167
size_t ntlm_authenticate_len(struct ntlm_challenge_info *info, const char *domain, const char *username, const char *workstation)
Calculate NTLM Authenticate message length.
Definition ntlm.c:326
void ntlm_key(const char *domain, const char *username, const char *password, struct ntlm_key *key)
Calculate NTLM verification key.
Definition ntlm.c:115
NT LAN Manager (NTLM) authentication.
@ NTLM_NEGOTIATE_KEY_EXCH
Negotiate key exchange.
Definition ntlm.h:41
#define AUTHENTICATE_TEST(name, DOMAIN, USERNAME, PASSWORD, WORKSTATION, NONCE, CHALLENGE, EXPECTED)
Define an authentication test.
Definition ntlm_test.c:92
static void ntlm_data_okx(struct ntlm_header *msg, size_t msg_len, struct ntlm_data *data, struct ntlm_header *expected, struct ntlm_data *expected_data, const char *field, const char *file, unsigned int line)
Report NTLM variable-length data test result.
Definition ntlm_test.c:185
static void ntlm_test_exec(void)
Perform NTLM self-test.
Definition ntlm_test.c:299
#define KEY_TEST(name, DOMAIN, USERNAME, PASSWORD, EXPECTED)
Define a key generation digest test.
Definition ntlm_test.c:81
static void ntlm_key_okx(struct ntlm_key_test *test, const char *file, unsigned int line)
Report key generation test result.
Definition ntlm_test.c:162
static void ntlm_authenticate_okx(struct ntlm_authenticate_test *test, const char *file, unsigned int line)
Report NTLM authentication test result.
Definition ntlm_test.c:225
#define ntlm_authenticate_ok(test)
Definition ntlm_test.c:292
#define ntlm_key_ok(test)
Definition ntlm_test.c:170
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
An authentication test.
Definition ntlm_test.c:56
struct ntlm_authenticate * expected
Expected Authenticate message.
Definition ntlm_test.c:72
const char * password
Password (or NULL)
Definition ntlm_test.c:62
const char * workstation
Workstation (or NULL)
Definition ntlm_test.c:64
struct ntlm_nonce nonce
Nonce.
Definition ntlm_test.c:66
size_t challenge_len
Length of Challenge message.
Definition ntlm_test.c:70
size_t expected_len
Expected length of Authenticate message.
Definition ntlm_test.c:74
struct ntlm_challenge * challenge
Challenge message.
Definition ntlm_test.c:68
const char * username
User name (or NULL)
Definition ntlm_test.c:60
const char * domain
Domain name (or NULL)
Definition ntlm_test.c:58
An Authenticate message.
Definition ntlm.h:117
struct ntlm_data lm
LAN Manager response.
Definition ntlm.h:121
struct ntlm_data user
User name.
Definition ntlm.h:127
struct ntlm_data domain
Domain name.
Definition ntlm.h:125
struct ntlm_data nt
NT response.
Definition ntlm.h:123
struct ntlm_data session
Session key.
Definition ntlm.h:131
struct ntlm_header header
Message header.
Definition ntlm.h:119
struct ntlm_data workstation
Workstation name.
Definition ntlm.h:129
uint32_t flags
Negotiation flags.
Definition ntlm.h:133
NTLM challenge information.
Definition ntlm.h:166
A Challenge message.
Definition ntlm.h:101
A variable-length data descriptor.
Definition ntlm.h:75
uint16_t len
Length (in bytes)
Definition ntlm.h:77
uint32_t offset
Offset from start of message header.
Definition ntlm.h:85
A message header.
Definition ntlm.h:18
A key generation test.
Definition ntlm_test.c:44
const char * password
Password (or NULL)
Definition ntlm_test.c:50
const char * username
User name (or NULL)
Definition ntlm_test.c:48
struct ntlm_key expected
Expected key.
Definition ntlm_test.c:52
const char * domain
Domain name (or NULL)
Definition ntlm_test.c:46
An NTLM verification key.
Definition ntlm.h:176
A LAN Manager response.
Definition ntlm.h:137
A nonce.
Definition ntlm.h:69
An NT response.
Definition ntlm.h:145
A self-test set.
Definition test.h:15
Self-test infrastructure.
#define okx(success, file, line)
Report test result.
Definition test.h:44
#define __self_test
Declare a self-test.
Definition test.h:32