iPXE
Functions | Variables
ntlm.c File Reference

NT LAN Manager (NTLM) authentication. More...

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/md4.h>
#include <ipxe/md5.h>
#include <ipxe/hmac.h>
#include <ipxe/ntlm.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 
int ntlm_challenge (struct ntlm_challenge *challenge, size_t len, struct ntlm_challenge_info *info)
 Parse NTLM Challenge. More...
 
void ntlm_key (const char *domain, const char *username, const char *password, struct ntlm_key *key)
 Calculate NTLM verification key. More...
 
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. More...
 
static void * ntlm_append (struct ntlm_header *header, struct ntlm_data *data, void *payload, size_t len)
 Append data to NTLM message. More...
 
static void * ntlm_append_string (struct ntlm_header *header, struct ntlm_data *data, void *payload, const char *string)
 Append Unicode string data to NTLM message. More...
 
size_t ntlm_authenticate (struct ntlm_challenge_info *info, const char *domain, const char *username, const char *workstation, struct ntlm_lm_response *lm, struct ntlm_nt_response *nt, struct ntlm_authenticate *auth)
 Construct NTLM Authenticate message. More...
 
size_t ntlm_authenticate_len (struct ntlm_challenge_info *info, const char *domain, const char *username, const char *workstation)
 Calculate NTLM Authenticate message length. More...
 

Variables

const struct ntlm_negotiate ntlm_negotiate
 Negotiate message. More...
 

Detailed Description

NT LAN Manager (NTLM) authentication.

Definition in file ntlm.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ ntlm_challenge()

int ntlm_challenge ( struct ntlm_challenge challenge,
size_t  len,
struct ntlm_challenge_info info 
)

Parse NTLM Challenge.

Parameters
challengeChallenge message
lenLength of Challenge message
infoChallenge information to fill in
Return values
rcReturn status code

Definition at line 68 of file ntlm.c.

69  {
70  size_t offset;
71 
72  DBGC ( challenge, "NTLM challenge message:\n" );
73  DBGC_HDA ( challenge, 0, challenge, len );
74 
75  /* Sanity checks */
76  if ( len < sizeof ( *challenge ) ) {
77  DBGC ( challenge, "NTLM underlength challenge (%zd bytes)\n",
78  len );
79  return -EINVAL;
80  }
81 
82  /* Extract nonce */
83  info->nonce = &challenge->nonce;
84  DBGC ( challenge, "NTLM challenge nonce:\n" );
85  DBGC_HDA ( challenge, 0, info->nonce, sizeof ( *info->nonce ) );
86 
87  /* Extract target information */
88  info->len = le16_to_cpu ( challenge->info.len );
89  offset = le32_to_cpu ( challenge->info.offset );
90  if ( ( offset > len ) ||
91  ( info->len > ( len - offset ) ) ) {
92  DBGC ( challenge, "NTLM target information outside "
93  "challenge\n" );
94  DBGC_HDA ( challenge, 0, challenge, len );
95  return -EINVAL;
96  }
97  info->target = ( ( ( void * ) challenge ) + offset );
98  DBGC ( challenge, "NTLM challenge target information:\n" );
99  DBGC_HDA ( challenge, 0, info->target, info->len );
100 
101  return 0;
102 }
#define EINVAL
Invalid argument.
Definition: errno.h:428
u32 info
Definition: ar9003_mac.h:67
#define le32_to_cpu(value)
Definition: byteswap.h:113
#define DBGC(...)
Definition: compiler.h:505
uint16_t len
Length (in bytes)
Definition: ntlm.h:76
#define DBGC_HDA(...)
Definition: compiler.h:506
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
#define le16_to_cpu(value)
Definition: byteswap.h:112
struct ntlm_data info
Target information.
Definition: ntlm.h:112
uint32_t len
Length.
Definition: ena.h:14
uint32_t offset
Offset from start of message header.
Definition: ntlm.h:84
struct ntlm_nonce nonce
Server nonce.
Definition: ntlm.h:108

References DBGC, DBGC_HDA, EINVAL, info, ntlm_challenge::info, le16_to_cpu, le32_to_cpu, len, ntlm_data::len, ntlm_challenge::nonce, ntlm_data::offset, and offset.

◆ ntlm_key()

void ntlm_key ( const char *  domain,
const char *  username,
const char *  password,
struct ntlm_key key 
)

Calculate NTLM verification key.

Parameters
domainDomain name (or NULL)
usernameUser name (or NULL)
passwordPassword (or NULL)
keyKey to fill in

This is the NTOWFv2() function as defined in MS-NLMP.

Definition at line 114 of file ntlm.c.

115  {
116  struct digest_algorithm *md4 = &md4_algorithm;
117  struct digest_algorithm *md5 = &md5_algorithm;
118  union {
119  uint8_t md4[MD4_CTX_SIZE];
121  } ctx;
123  uint8_t c;
124  uint16_t wc;
125 
126  /* Use empty usernames/passwords if not specified */
127  if ( ! domain )
128  domain = "";
129  if ( ! username )
130  username = "";
131  if ( ! password )
132  password = "";
133 
134  /* Construct MD4 digest of (Unicode) password */
135  digest_init ( md4, ctx.md4 );
136  while ( ( c = *(password++) ) ) {
137  wc = cpu_to_le16 ( c );
138  digest_update ( md4, ctx.md4, &wc, sizeof ( wc ) );
139  }
140  digest_final ( md4, ctx.md4, digest );
141 
142  /* Construct HMAC-MD5 of (Unicode) upper-case username */
143  hmac_init ( md5, ctx.md5, digest, sizeof ( digest ) );
144  while ( ( c = *(username++) ) ) {
145  wc = cpu_to_le16 ( toupper ( c ) );
146  hmac_update ( md5, ctx.md5, &wc, sizeof ( wc ) );
147  }
148  while ( ( c = *(domain++) ) ) {
149  wc = cpu_to_le16 ( c );
150  hmac_update ( md5, ctx.md5, &wc, sizeof ( wc ) );
151  }
152  hmac_final ( md5, ctx.md5, key->raw );
153  DBGC ( key, "NTLM key:\n" );
154  DBGC_HDA ( key, 0, key, sizeof ( *key ) );
155 }
#define MD4_DIGEST_SIZE
MD4 digest size.
Definition: md4.h:72
void hmac_init(struct digest_algorithm *digest, void *ctx, const void *key, size_t key_len)
Initialise HMAC.
Definition: hmac.c:57
uint32_t c
Definition: md4.c:30
static wchar_t wc
Definition: wchar.h:22
unsigned short uint16_t
Definition: stdint.h:11
#define DBGC(...)
Definition: compiler.h:505
static int toupper(int character)
Convert character to upper case.
Definition: ctype.h:120
static void struct digest_algorithm * digest
HMAC-MD5 digest.
Definition: crypto.h:308
#define DBGC_HDA(...)
Definition: compiler.h:506
static void hmac_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Update HMAC.
Definition: hmac.h:42
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
#define MD5_CTX_SIZE
MD5 context size.
Definition: md5.h:66
unsigned char uint8_t
Definition: stdint.h:10
#define MD5_BLOCK_SIZE
MD5 block size.
Definition: md5.h:69
#define MD4_CTX_SIZE
MD4 context size.
Definition: md4.h:66
#define cpu_to_le16(value)
Definition: byteswap.h:106
A message digest algorithm.
Definition: crypto.h:17
void hmac_final(struct digest_algorithm *digest, void *ctx, void *hmac)
Finalise HMAC.
Definition: hmac.c:87
struct digest_algorithm md4_algorithm
MD4 algorithm.
Definition: md4.c:261
union @382 key
Sense key.
Definition: crypto.h:284
struct ntlm_data domain
Domain name.
Definition: ntlm.h:16
struct digest_algorithm md5_algorithm
MD5 algorithm.
Definition: md5.c:286

References c, cpu_to_le16, ctx, DBGC, DBGC_HDA, digest, domain, hmac_final(), hmac_init(), hmac_update(), key, md4_algorithm, MD4_CTX_SIZE, MD4_DIGEST_SIZE, md5_algorithm, MD5_BLOCK_SIZE, MD5_CTX_SIZE, toupper(), and wc.

Referenced by http_ntlm_authenticate(), ntlm_authenticate_okx(), and ntlm_key_okx().

◆ ntlm_response()

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.

Parameters
infoChallenge information
keyVerification key
nonceNonce, or NULL to use a random nonce
lmLAN Manager response to fill in
ntNT response to fill in

Definition at line 166 of file ntlm.c.

168  {
169  struct digest_algorithm *md5 = &md5_algorithm;
170  struct ntlm_nonce tmp_nonce;
172  unsigned int i;
173 
174  /* Generate random nonce, if needed */
175  if ( ! nonce ) {
176  for ( i = 0 ; i < sizeof ( tmp_nonce ) ; i++ )
177  tmp_nonce.raw[i] = random();
178  nonce = &tmp_nonce;
179  }
180 
181  /* Construct LAN Manager response */
182  memcpy ( &lm->nonce, nonce, sizeof ( lm->nonce ) );
183  hmac_init ( md5, ctx, key->raw, sizeof ( *key ) );
184  hmac_update ( md5, ctx, info->nonce, sizeof ( *info->nonce ) );
185  hmac_update ( md5, ctx, &lm->nonce, sizeof ( lm->nonce ) );
186  hmac_final ( md5, ctx, lm->digest );
187  DBGC ( key, "NTLM LAN Manager response:\n" );
188  DBGC_HDA ( key, 0, lm, sizeof ( *lm ) );
189 
190  /* Construct NT response */
191  memset ( nt, 0, sizeof ( *nt ) );
192  nt->version = NTLM_VERSION_NTLMV2;
193  nt->high = NTLM_VERSION_NTLMV2;
194  memcpy ( &nt->nonce, nonce, sizeof ( nt->nonce ) );
195  hmac_init ( md5, ctx, key->raw, sizeof ( *key ) );
196  hmac_update ( md5, ctx, info->nonce, sizeof ( *info->nonce ) );
197  hmac_update ( md5, ctx, &nt->version,
198  ( sizeof ( *nt ) -
199  offsetof ( typeof ( *nt ), version ) ) );
200  hmac_update ( md5, ctx, info->target, info->len );
201  hmac_update ( md5, ctx, &nt->zero, sizeof ( nt->zero ) );
202  hmac_final ( md5, ctx, nt->digest );
203  DBGC ( key, "NTLM NT response prefix:\n" );
204  DBGC_HDA ( key, 0, nt, sizeof ( *nt ) );
205 }
void hmac_init(struct digest_algorithm *digest, void *ctx, const void *key, size_t key_len)
Initialise HMAC.
Definition: hmac.c:57
u32 info
Definition: ar9003_mac.h:67
#define DBGC(...)
Definition: compiler.h:505
#define offsetof(type, field)
Get offset of a field within a structure.
Definition: stddef.h:24
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define DBGC_HDA(...)
Definition: compiler.h:506
static void hmac_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Update HMAC.
Definition: hmac.h:42
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
#define MD5_CTX_SIZE
MD5 context size.
Definition: md5.h:66
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition: random.c:31
struct ntlm_data lm
LAN Manager response.
Definition: ntlm.h:14
unsigned char uint8_t
Definition: stdint.h:10
A nonce.
Definition: ntlm.h:68
#define MD5_BLOCK_SIZE
MD5 block size.
Definition: md5.h:69
u32 version
Driver version.
Definition: ath9k_hw.c:1983
#define NTLM_VERSION_NTLMV2
NTLM version.
Definition: ntlm.h:162
A message digest algorithm.
Definition: crypto.h:17
void hmac_final(struct digest_algorithm *digest, void *ctx, void *hmac)
Finalise HMAC.
Definition: hmac.c:87
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition: acpi.c:45
struct ntlm_nonce nonce
Server nonce.
Definition: ntlm.h:18
union @382 key
Sense key.
Definition: crypto.h:284
struct mschapv2_nt_response nt
NT response.
Definition: mschapv2.h:16
struct digest_algorithm md5_algorithm
MD5 algorithm.
Definition: md5.c:286
void * memset(void *dest, int character, size_t len) __nonnull

References ctx, DBGC, DBGC_HDA, hmac_final(), hmac_init(), hmac_update(), info, key, lm, md5_algorithm, MD5_BLOCK_SIZE, MD5_CTX_SIZE, memcpy(), memset(), nonce, nt, NTLM_VERSION_NTLMV2, offsetof, random(), ntlm_nonce::raw, typeof(), and version.

Referenced by http_ntlm_authenticate(), and ntlm_authenticate_okx().

◆ ntlm_append()

static void* ntlm_append ( struct ntlm_header header,
struct ntlm_data data,
void *  payload,
size_t  len 
)
static

Append data to NTLM message.

Parameters
headerMessage header, or NULL to only calculate next payload
dataData descriptor
payloadData payload
lenLength of data
Return values
payloadNext data payload

Definition at line 216 of file ntlm.c.

217  {
218 
219  /* Populate data descriptor */
220  if ( header ) {
221  data->offset = cpu_to_le32 ( payload - ( ( void * ) header ) );
222  data->len = data->max_len = cpu_to_le16 ( len );
223  }
224 
225  return ( payload + len );
226 }
#define cpu_to_le32(value)
Definition: byteswap.h:107
uint32_t len
Length.
Definition: ena.h:14
struct ena_aq_header header
Header.
Definition: ena.h:12
#define cpu_to_le16(value)
Definition: byteswap.h:106
uint8_t data[48]
Additional event data.
Definition: ena.h:22

References cpu_to_le16, cpu_to_le32, data, header, and len.

Referenced by ntlm_append_string(), and ntlm_authenticate().

◆ ntlm_append_string()

static void* ntlm_append_string ( struct ntlm_header header,
struct ntlm_data data,
void *  payload,
const char *  string 
)
static

Append Unicode string data to NTLM message.

Parameters
headerMessage header, or NULL to only calculate next payload
dataData descriptor
payloadData payload
stringString to append, or NULL
Return values
payloadNext data payload

Definition at line 237 of file ntlm.c.

239  {
240  uint16_t *tmp = payload;
241  uint8_t c;
242 
243  /* Convert string to Unicode */
244  for ( tmp = payload ; ( string && ( c = *(string++) ) ) ; tmp++ ) {
245  if ( header )
246  *tmp = cpu_to_le16 ( c );
247  }
248 
249  /* Append string data */
250  return ntlm_append ( header, data, payload,
251  ( ( ( void * ) tmp ) - payload ) );
252 }
uint32_t c
Definition: md4.c:30
unsigned short uint16_t
Definition: stdint.h:11
unsigned long tmp
Definition: linux_pci.h:53
static void * ntlm_append(struct ntlm_header *header, struct ntlm_data *data, void *payload, size_t len)
Append data to NTLM message.
Definition: ntlm.c:216
unsigned char uint8_t
Definition: stdint.h:10
struct ena_aq_header header
Header.
Definition: ena.h:12
#define cpu_to_le16(value)
Definition: byteswap.h:106
uint8_t data[48]
Additional event data.
Definition: ena.h:22

References c, cpu_to_le16, data, header, ntlm_append(), and tmp.

Referenced by ntlm_authenticate().

◆ ntlm_authenticate()

size_t ntlm_authenticate ( struct ntlm_challenge_info info,
const char *  domain,
const char *  username,
const char *  workstation,
struct ntlm_lm_response lm,
struct ntlm_nt_response nt,
struct ntlm_authenticate auth 
)

Construct NTLM Authenticate message.

Parameters
infoChallenge information
domainDomain name, or NULL
usernameUser name, or NULL
workstationWorkstation name, or NULL
lmLAN Manager response
ntNT response
authMessage to fill in, or NULL to only calculate length
Return values
lenLength of message

Definition at line 266 of file ntlm.c.

270  {
271  void *tmp;
272  size_t nt_len;
273  size_t len;
274 
275  /* Construct response header */
276  if ( auth ) {
277  memset ( auth, 0, sizeof ( *auth ) );
278  memcpy ( auth->header.magic, ntlm_negotiate.header.magic,
279  sizeof ( auth->header.magic ) );
280  auth->header.type = cpu_to_le32 ( NTLM_AUTHENTICATE );
281  auth->flags = ntlm_negotiate.flags;
282  }
283  tmp = ( ( ( void * ) auth ) + sizeof ( *auth ) );
284 
285  /* Construct LAN Manager response */
286  if ( auth )
287  memcpy ( tmp, lm, sizeof ( *lm ) );
288  tmp = ntlm_append ( &auth->header, &auth->lm, tmp, sizeof ( *lm ) );
289 
290  /* Construct NT response */
291  nt_len = ( sizeof ( *nt ) + info->len + sizeof ( nt->zero ) );
292  if ( auth ) {
293  memcpy ( tmp, nt, sizeof ( *nt ) );
294  memcpy ( ( tmp + sizeof ( *nt ) ), info->target, info->len );
295  memset ( ( tmp + sizeof ( *nt ) + info->len ), 0,
296  sizeof ( nt->zero ) );
297  }
298  tmp = ntlm_append ( &auth->header, &auth->nt, tmp, nt_len );
299 
300  /* Populate domain, user, and workstation names */
301  tmp = ntlm_append_string ( &auth->header, &auth->domain, tmp, domain );
302  tmp = ntlm_append_string ( &auth->header, &auth->user, tmp, username );
303  tmp = ntlm_append_string ( &auth->header, &auth->workstation, tmp,
304  workstation );
305 
306  /* Calculate length */
307  len = ( tmp - ( ( void * ) auth ) );
308  if ( auth ) {
309  DBGC ( auth, "NTLM authenticate message:\n" );
310  DBGC_HDA ( auth, 0, auth, len );
311  }
312 
313  return len;
314 }
uint8_t magic[8]
Magic signature.
Definition: ntlm.h:19
u32 info
Definition: ar9003_mac.h:67
#define DBGC(...)
Definition: compiler.h:505
static void void * auth
Definition: crypto.h:264
Authenticate message.
Definition: ntlm.h:34
unsigned long tmp
Definition: linux_pci.h:53
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define DBGC_HDA(...)
Definition: compiler.h:506
#define cpu_to_le32(value)
Definition: byteswap.h:107
uint32_t flags
Negotiation flags.
Definition: ntlm.h:92
static void * ntlm_append_string(struct ntlm_header *header, struct ntlm_data *data, void *payload, const char *string)
Append Unicode string data to NTLM message.
Definition: ntlm.c:237
struct ntlm_data lm
LAN Manager response.
Definition: ntlm.h:14
static void * ntlm_append(struct ntlm_header *header, struct ntlm_data *data, void *payload, size_t len)
Append data to NTLM message.
Definition: ntlm.c:216
struct ntlm_header header
Message header.
Definition: ntlm.h:90
uint32_t len
Length.
Definition: ena.h:14
struct ntlm_data workstation
Workstation name.
Definition: ntlm.h:18
struct mschapv2_nt_response nt
NT response.
Definition: mschapv2.h:16
struct ntlm_data domain
Domain name.
Definition: ntlm.h:16
void * memset(void *dest, int character, size_t len) __nonnull
A Negotiate message.
Definition: ntlm.h:88

References auth, cpu_to_le32, DBGC, DBGC_HDA, domain, ntlm_negotiate::flags, ntlm_negotiate::header, info, len, lm, ntlm_header::magic, memcpy(), memset(), nt, ntlm_append(), ntlm_append_string(), NTLM_AUTHENTICATE, tmp, and workstation.

Referenced by http_format_ntlm_auth(), and ntlm_authenticate_len().

◆ ntlm_authenticate_len()

size_t ntlm_authenticate_len ( struct ntlm_challenge_info info,
const char *  domain,
const char *  username,
const char *  workstation 
)

Calculate NTLM Authenticate message length.

Parameters
infoChallenge information
domainDomain name, or NULL
usernameUser name, or NULL
workstationWorkstation name, or NULL
Return values
lenLength of Authenticate message

Definition at line 325 of file ntlm.c.

327  {
328 
329  return ntlm_authenticate ( info, domain, username, workstation,
330  NULL, NULL, NULL );
331 }
u32 info
Definition: ar9003_mac.h:67
size_t ntlm_authenticate(struct ntlm_challenge_info *info, const char *domain, const char *username, const char *workstation, struct ntlm_lm_response *lm, struct ntlm_nt_response *nt, struct ntlm_authenticate *auth)
Construct NTLM Authenticate message.
Definition: ntlm.c:266
struct ntlm_data workstation
Workstation name.
Definition: ntlm.h:18
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
struct ntlm_data domain
Domain name.
Definition: ntlm.h:16

References domain, info, ntlm_authenticate(), NULL, and workstation.

Referenced by http_ntlm_authenticate(), and ntlm_authenticate_okx().

Variable Documentation

◆ ntlm_negotiate

Initial value:
= {
.header = {
.magic = NTLM_MAGIC,
},
}
Negotiate NTLM key.
Definition: ntlm.h:46
Negotiate always sign.
Definition: ntlm.h:44
#define NTLM_MAGIC
Magic signature.
Definition: ntlm.h:25
#define cpu_to_le32(value)
Definition: byteswap.h:107
Negotiate extended security.
Definition: ntlm.h:42
Negotiate message type.
Definition: ntlm.h:30
Request target name and information.
Definition: ntlm.h:48
Negotiate Unicode character encoding.
Definition: ntlm.h:50

Negotiate message.

This message content is fixed since there is no need to specify the calling workstation name or domain name, and the set of flags is mandated by the MS-NLMP specification.

Definition at line 48 of file ntlm.c.