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 
24 FILE_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 */
44 struct ntlm_key_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 */
66  struct ntlm_nonce nonce;
67  /** Challenge message */
69  /** Length of Challenge message */
70  size_t challenge_len;
71  /** Expected Authenticate message */
73  /** Expected length of Authenticate message */
74  size_t expected_len;
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 */
111 KEY_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 */
116 AUTHENTICATE_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  */
162 static 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  */
185 static 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;
228  struct ntlm_challenge_info info;
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  */
299 static 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 */
309 struct self_test ntlm_test __self_test = {
310  .name = "ntlm",
311  .exec = ntlm_test_exec,
312 };
A variable-length data descriptor.
Definition: ntlm.h:74
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
u32 info
Definition: ar9003_mac.h:67
struct ntlm_data lm
LAN Manager response.
Definition: ntlm.h:120
#define le32_to_cpu(value)
Definition: byteswap.h:113
A key generation test.
Definition: ntlm_test.c:44
const char * workstation
Workstation (or NULL)
Definition: ntlm_test.c:64
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:166
#define DBGC(...)
Definition: compiler.h:505
size_t expected_len
Expected length of Authenticate message.
Definition: ntlm_test.c:74
#define DATA(...)
Define inline message data.
Definition: ntlm_test.c:78
Self-test infrastructure.
const char * name
Test set name.
Definition: test.h:17
struct ntlm_nonce nonce
Nonce.
Definition: ntlm_test.c:66
A self-test set.
Definition: test.h:15
const char * domain
Domain name (or NULL)
Definition: ntlm_test.c:58
static void void * auth
Definition: crypto.h:264
struct ntlm_header header
Message header.
Definition: ntlm.h:118
uint16_t len
Length (in bytes)
Definition: ntlm.h:76
const char * username
User name (or NULL)
Definition: ntlm_test.c:48
size_t challenge_len
Length of Challenge message.
Definition: ntlm_test.c:70
#define okx(success, file, line)
Report test result.
Definition: test.h:44
const char * password
Password (or NULL)
Definition: ntlm_test.c:50
#define DBGC_HDA(...)
Definition: compiler.h:506
An Authenticate message.
Definition: ntlm.h:116
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
An NTLM verification key.
Definition: ntlm.h:175
struct ntlm_key expected
Expected key.
Definition: ntlm_test.c:52
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
struct ntlm_data workstation
Workstation name.
Definition: ntlm.h:128
const char * domain
Domain name (or NULL)
Definition: ntlm_test.c:46
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
A message header.
Definition: ntlm.h:17
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
struct ntlm_data domain
Domain name.
Definition: ntlm.h:124
struct ntlm_data lm
LAN Manager response.
Definition: ntlm.h:14
const char * username
User name (or NULL)
Definition: ntlm_test.c:60
A nonce.
Definition: ntlm.h:68
struct ntlm_data session
Session key.
Definition: ntlm.h:130
struct ntlm_challenge * challenge
Challenge message.
Definition: ntlm_test.c:68
#define le16_to_cpu(value)
Definition: byteswap.h:112
void * malloc(size_t size)
Allocate memory.
Definition: malloc.c:583
struct self_test ntlm_test __self_test
NTLM self-test.
Definition: ntlm_test.c:309
#define KEY_TEST(name, DOMAIN, USERNAME, PASSWORD, EXPECTED)
Define a key generation digest test.
Definition: ntlm_test.c:81
struct ntlm_data nt
NT response.
Definition: ntlm.h:122
struct ntlm_data user
User name.
Definition: ntlm.h:126
Negotiate key exchange.
Definition: ntlm.h:40
struct ntlm_authenticate * expected
Expected Authenticate message.
Definition: ntlm_test.c:72
uint32_t len
Length.
Definition: ena.h:14
A Challenge message.
Definition: ntlm.h:100
static void ntlm_test_exec(void)
Perform NTLM self-test.
Definition: ntlm_test.c:299
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:325
uint32_t offset
Offset from start of message header.
Definition: ntlm.h:84
uint8_t data[48]
Additional event data.
Definition: ena.h:22
__be32 raw[7]
Definition: CIB_PRM.h:28
void ntlm_key(const char *domain, const char *username, const char *password, struct ntlm_key *key)
Calculate NTLM verification key.
Definition: ntlm.c:114
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
NT LAN Manager (NTLM) authentication.
const char * password
Password (or NULL)
Definition: ntlm_test.c:62
An authentication test.
Definition: ntlm_test.c:56
NTLM challenge information.
Definition: ntlm.h:165
#define ntlm_key_ok(test)
Definition: ntlm_test.c:170
An NT response.
Definition: ntlm.h:144
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:114
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
A LAN Manager response.
Definition: ntlm.h:136
String functions.
#define AUTHENTICATE_TEST(name, DOMAIN, USERNAME, PASSWORD, WORKSTATION, NONCE, CHALLENGE, EXPECTED)
Define an authentication test.
Definition: ntlm_test.c:92
union @382 key
Sense key.
Definition: crypto.h:284
static int test
Definition: epic100.c:73
struct mschapv2_nt_response nt
NT response.
Definition: mschapv2.h:16
static void msg(unsigned int row, const char *fmt,...)
Print message centred on specified row.
Definition: settings_ui.c:288
#define ntlm_authenticate_ok(test)
Definition: ntlm_test.c:292