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];
120  uint8_t md5[MD5_CTX_SIZE];
121  } ctx;
123  size_t digest_len;
124  uint8_t c;
125  uint16_t wc;
126 
127  /* Use empty usernames/passwords if not specified */
128  if ( ! domain )
129  domain = "";
130  if ( ! username )
131  username = "";
132  if ( ! password )
133  password = "";
134 
135  /* Construct MD4 digest of (Unicode) password */
136  digest_init ( md4, ctx.md4 );
137  while ( ( c = *(password++) ) ) {
138  wc = cpu_to_le16 ( c );
139  digest_update ( md4, ctx.md4, &wc, sizeof ( wc ) );
140  }
141  digest_final ( md4, ctx.md4, digest );
142 
143  /* Construct HMAC-MD5 of (Unicode) upper-case username */
144  digest_len = sizeof ( digest );
145  hmac_init ( md5, ctx.md5, digest, &digest_len );
146  while ( ( c = *(username++) ) ) {
147  wc = cpu_to_le16 ( toupper ( c ) );
148  hmac_update ( md5, ctx.md5, &wc, sizeof ( wc ) );
149  }
150  while ( ( c = *(domain++) ) ) {
151  wc = cpu_to_le16 ( c );
152  hmac_update ( md5, ctx.md5, &wc, sizeof ( wc ) );
153  }
154  hmac_final ( md5, ctx.md5, digest, &digest_len, key->raw );
155  DBGC ( key, "NTLM key:\n" );
156  DBGC_HDA ( key, 0, key, sizeof ( *key ) );
157 }
#define MD4_DIGEST_SIZE
MD4 digest size.
Definition: md4.h:69
uint32_t c
Definition: md4.c:30
static wchar_t wc
Definition: wchar.h:22
static void digest_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Definition: crypto.h:177
unsigned short uint16_t
Definition: stdint.h:11
void hmac_final(struct digest_algorithm *digest, void *digest_ctx, void *key, size_t *key_len, void *hmac)
Finalise HMAC.
Definition: hmac.c:115
static void digest_final(struct digest_algorithm *digest, void *ctx, void *out)
Definition: crypto.h:182
#define DBGC(...)
Definition: compiler.h:505
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
struct md4_digest digest
Digest of data already processed.
Definition: md4.h:12
static int toupper(int character)
Convert character to upper case.
Definition: ctype.h:109
#define DBGC_HDA(...)
Definition: compiler.h:506
static void digest_init(struct digest_algorithm *digest, void *ctx)
Definition: crypto.h:172
#define MD5_CTX_SIZE
MD5 context size.
Definition: md5.h:66
unsigned char uint8_t
Definition: stdint.h:10
#define MD4_CTX_SIZE
MD4 context size.
Definition: md4.h:66
void hmac_init(struct digest_algorithm *digest, void *digest_ctx, void *key, size_t *key_len)
Initialise HMAC.
Definition: hmac.c:80
#define cpu_to_le16(value)
Definition: byteswap.h:106
A message digest algorithm.
Definition: crypto.h:16
struct digest_algorithm md4_algorithm
MD4 algorithm.
Definition: md4.c:261
static void hmac_update(struct digest_algorithm *digest, void *digest_ctx, const void *data, size_t len)
Update HMAC.
Definition: hmac.h:21
union @376 key
Sense key.
Definition: scsi.h:18
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, digest_final(), digest_init(), digest_update(), domain, hmac_final(), hmac_init(), hmac_update(), key, md4_algorithm, MD4_CTX_SIZE, MD4_DIGEST_SIZE, md5_algorithm, 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 168 of file ntlm.c.

170  {
171  struct digest_algorithm *md5 = &md5_algorithm;
172  struct ntlm_nonce tmp_nonce;
174  size_t key_len = sizeof ( *key );
175  unsigned int i;
176 
177  /* Generate random nonce, if needed */
178  if ( ! nonce ) {
179  for ( i = 0 ; i < sizeof ( tmp_nonce ) ; i++ )
180  tmp_nonce.raw[i] = random();
181  nonce = &tmp_nonce;
182  }
183 
184  /* Construct LAN Manager response */
185  memcpy ( &lm->nonce, nonce, sizeof ( lm->nonce ) );
186  hmac_init ( md5, ctx, key->raw, &key_len );
187  hmac_update ( md5, ctx, info->nonce, sizeof ( *info->nonce ) );
188  hmac_update ( md5, ctx, &lm->nonce, sizeof ( lm->nonce ) );
189  hmac_final ( md5, ctx, key->raw, &key_len, lm->digest );
190  DBGC ( key, "NTLM LAN Manager response:\n" );
191  DBGC_HDA ( key, 0, lm, sizeof ( *lm ) );
192 
193  /* Construct NT response */
194  memset ( nt, 0, sizeof ( *nt ) );
195  nt->version = NTLM_VERSION_NTLMV2;
196  nt->high = NTLM_VERSION_NTLMV2;
197  memcpy ( &nt->nonce, nonce, sizeof ( nt->nonce ) );
198  hmac_init ( md5, ctx, key->raw, &key_len );
199  hmac_update ( md5, ctx, info->nonce, sizeof ( *info->nonce ) );
200  hmac_update ( md5, ctx, &nt->version,
201  ( sizeof ( *nt ) -
202  offsetof ( typeof ( *nt ), version ) ) );
203  hmac_update ( md5, ctx, info->target, info->len );
204  hmac_update ( md5, ctx, &nt->zero, sizeof ( nt->zero ) );
205  hmac_final ( md5, ctx, key->raw, &key_len, nt->digest );
206  DBGC ( key, "NTLM NT response prefix:\n" );
207  DBGC_HDA ( key, 0, nt, sizeof ( *nt ) );
208 }
u32 info
Definition: ar9003_mac.h:67
void hmac_final(struct digest_algorithm *digest, void *digest_ctx, void *key, size_t *key_len, void *hmac)
Finalise HMAC.
Definition: hmac.c:115
#define DBGC(...)
Definition: compiler.h:505
#define offsetof(type, field)
Get offset of a field within a structure.
Definition: stddef.h:24
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
void * memcpy(void *dest, const void *src, size_t len) __nonnull
struct ntlm_data nt
NT response.
Definition: ntlm.h:16
u32 version
Version number.
Definition: ath9k_hw.c:1983
#define DBGC_HDA(...)
Definition: compiler.h:506
#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:30
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
void hmac_init(struct digest_algorithm *digest, void *digest_ctx, void *key, size_t *key_len)
Initialise HMAC.
Definition: hmac.c:80
#define NTLM_VERSION_NTLMV2
NTLM version.
Definition: ntlm.h:162
A message digest algorithm.
Definition: crypto.h:16
static void hmac_update(struct digest_algorithm *digest, void *digest_ctx, const void *data, size_t len)
Update HMAC.
Definition: hmac.h:21
struct ntlm_nonce nonce
Server nonce.
Definition: ntlm.h:18
union @376 key
Sense key.
Definition: scsi.h:18
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_CTX_SIZE, memcpy(), memset(), nonce, nt, NTLM_VERSION_NTLMV2, offsetof, random(), ntlm_nonce::raw, 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 219 of file ntlm.c.

220  {
221 
222  /* Populate data descriptor */
223  if ( header ) {
224  data->offset = cpu_to_le32 ( payload - ( ( void * ) header ) );
225  data->len = data->max_len = cpu_to_le16 ( len );
226  }
227 
228  return ( payload + len );
229 }
#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
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12

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 240 of file ntlm.c.

242  {
243  uint16_t *tmp = payload;
244  uint8_t c;
245 
246  /* Convert string to Unicode */
247  for ( tmp = payload ; ( string && ( c = *(string++) ) ) ; tmp++ ) {
248  if ( header )
249  *tmp = cpu_to_le16 ( c );
250  }
251 
252  /* Append string data */
253  return ntlm_append ( header, data, payload,
254  ( ( ( void * ) tmp ) - payload ) );
255 }
uint32_t c
Definition: md4.c:30
unsigned short uint16_t
Definition: stdint.h:11
uint8_t * tmp
Definition: entropy.h:156
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:219
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
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12

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 269 of file ntlm.c.

273  {
274  void *tmp;
275  size_t nt_len;
276  size_t len;
277 
278  /* Construct response header */
279  if ( auth ) {
280  memset ( auth, 0, sizeof ( *auth ) );
282  sizeof ( auth->header.magic ) );
284  auth->flags = ntlm_negotiate.flags;
285  }
286  tmp = ( ( ( void * ) auth ) + sizeof ( *auth ) );
287 
288  /* Construct LAN Manager response */
289  if ( auth )
290  memcpy ( tmp, lm, sizeof ( *lm ) );
291  tmp = ntlm_append ( &auth->header, &auth->lm, tmp, sizeof ( *lm ) );
292 
293  /* Construct NT response */
294  nt_len = ( sizeof ( *nt ) + info->len + sizeof ( nt->zero ) );
295  if ( auth ) {
296  memcpy ( tmp, nt, sizeof ( *nt ) );
297  memcpy ( ( tmp + sizeof ( *nt ) ), info->target, info->len );
298  memset ( ( tmp + sizeof ( *nt ) + info->len ), 0,
299  sizeof ( nt->zero ) );
300  }
301  tmp = ntlm_append ( &auth->header, &auth->nt, tmp, nt_len );
302 
303  /* Populate domain, user, and workstation names */
304  tmp = ntlm_append_string ( &auth->header, &auth->domain, tmp, domain );
305  tmp = ntlm_append_string ( &auth->header, &auth->user, tmp, username );
306  tmp = ntlm_append_string ( &auth->header, &auth->workstation, tmp,
307  workstation );
308 
309  /* Calculate length */
310  len = ( tmp - ( ( void * ) auth ) );
311  if ( auth ) {
312  DBGC ( auth, "NTLM authenticate message:\n" );
313  DBGC_HDA ( auth, 0, auth, len );
314  }
315 
316  return len;
317 }
uint8_t magic[8]
Magic signature.
Definition: ntlm.h:19
u32 info
Definition: ar9003_mac.h:67
struct ntlm_data lm
LAN Manager response.
Definition: ntlm.h:120
#define DBGC(...)
Definition: compiler.h:505
struct ntlm_header header
Message header.
Definition: ntlm.h:118
Authenticate message.
Definition: ntlm.h:34
void * memcpy(void *dest, const void *src, size_t len) __nonnull
struct ntlm_data nt
NT response.
Definition: ntlm.h:16
#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
struct ntlm_data workstation
Workstation name.
Definition: ntlm.h:128
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:240
uint8_t * tmp
Definition: entropy.h:156
struct ntlm_data domain
Domain name.
Definition: ntlm.h:124
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:219
struct ntlm_header header
Message header.
Definition: ntlm.h:90
struct ntlm_data nt
NT response.
Definition: ntlm.h:122
uint32_t flags
Negotiation flags.
Definition: ntlm.h:132
struct ntlm_data user
User name.
Definition: ntlm.h:126
uint32_t len
Length.
Definition: ena.h:14
uint32_t type
Message type.
Definition: ntlm.h:21
struct ntlm_data workstation
Workstation name.
Definition: ntlm.h:18
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 cpu_to_le32, DBGC, DBGC_HDA, domain, ntlm_authenticate::domain, ntlm_negotiate::flags, ntlm_authenticate::flags, ntlm_authenticate::header, ntlm_negotiate::header, info, len, ntlm_authenticate::lm, lm, ntlm_header::magic, memcpy(), memset(), ntlm_authenticate::nt, nt, ntlm_append(), ntlm_append_string(), NTLM_AUTHENTICATE, tmp, ntlm_header::type, ntlm_authenticate::user, workstation, and ntlm_authenticate::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 328 of file ntlm.c.

330  {
331 
332  return ntlm_authenticate ( info, domain, username, workstation,
333  NULL, NULL, NULL );
334 }
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:269
struct ntlm_data workstation
Workstation name.
Definition: ntlm.h:18
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
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.