iPXE
httpntlm.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 );
25FILE_SECBOOT ( PERMITTED );
26
27/**
28 * @file
29 *
30 * Hyper Text Transfer Protocol (HTTP) NTLM authentication
31 *
32 */
33
34#include <string.h>
35#include <errno.h>
36#include <ipxe/uri.h>
37#include <ipxe/base64.h>
38#include <ipxe/ntlm.h>
39#include <ipxe/netbios.h>
40#include <ipxe/http.h>
41
43
44/** Workstation name used for NTLM authentication */
45static const char http_ntlm_workstation[] = "iPXE";
46
47/**
48 * Parse HTTP "WWW-Authenticate" header for NTLM authentication
49 *
50 * @v http HTTP transaction
51 * @v line Remaining header line
52 * @ret rc Return status code
53 */
54static int http_parse_ntlm_auth ( struct http_transaction *http, char *line ) {
56 char *copy;
57 int len;
58 int rc;
59
60 /* Create temporary copy of Base64-encoded challenge message */
61 copy = strdup ( line );
62 if ( ! copy ) {
63 rc = -ENOMEM;
64 goto err_alloc;
65 }
66
67 /* Decode challenge message, overwriting the original */
68 len = base64_decode ( copy, line, strlen ( line ) );
69 if ( len < 0 ) {
70 rc = len;
71 DBGC ( http, "HTTP %p could not decode NTLM challenge "
72 "\"%s\": %s\n", http, copy, strerror ( rc ) );
73 goto err_decode;
74 }
75
76 /* Parse challenge, if present */
77 if ( len ) {
78 rsp->challenge = ( ( void * ) line );
79 if ( ( rc = ntlm_challenge ( rsp->challenge, len,
80 &rsp->info ) ) != 0 ) {
81 DBGC ( http, "HTTP %p could not parse NTLM challenge: "
82 "%s\n", http, strerror ( rc ) );
83 goto err_challenge;
84 }
85 }
86
87 /* Allow HTTP request to be retried if the request had not
88 * already tried authentication. Note that NTLM requires an
89 * additional round trip to obtain the challenge message,
90 * which is not present in the initial WWW-Authenticate.
91 */
92 if ( ( http->request.auth.auth == NULL ) ||
93 ( ( http->request.auth.auth == &http_ntlm_auth ) &&
94 ( http->request.auth.ntlm.len == 0 ) && len ) ) {
96 }
97
98 /* Success */
99 rc = 0;
100
101 err_challenge:
102 err_decode:
103 free ( copy );
104 err_alloc:
105 return rc;
106}
107
108/**
109 * Perform HTTP NTLM authentication
110 *
111 * @v http HTTP transaction
112 * @ret rc Return status code
113 */
114static int http_ntlm_authenticate ( struct http_transaction *http ) {
115 struct http_request_auth_ntlm *req = &http->request.auth.ntlm;
117 struct ntlm_key key;
118 const char *domain;
119 char *username;
120 const char *password;
121
122 /* If we have no challenge yet, then just send a Negotiate message */
123 if ( ! rsp->challenge ) {
124 DBGC ( http, "HTTP %p sending NTLM Negotiate\n", http );
125 return 0;
126 }
127
128 /* Record username */
129 if ( ! http->uri->user ) {
130 DBGC ( http, "HTTP %p has no username for NTLM "
131 "authentication\n", http );
132 return -EACCES;
133 }
134 req->username = http->uri->user;
135 password = ( http->uri->password ? http->uri->password : "" );
136
137 /* Split NetBIOS [domain\]username */
138 username = ( ( char * ) req->username );
139 domain = netbios_domain ( &username );
140
141 /* Generate key */
142 ntlm_key ( domain, username, password, &key );
143
144 /* Generate responses */
145 ntlm_response ( &rsp->info, &key, NULL, &req->lm, &req->nt );
146
147 /* Calculate Authenticate message length */
148 req->len = ntlm_authenticate_len ( &rsp->info, domain, username,
150
151 /* Restore NetBIOS [domain\]username */
152 netbios_domain_undo ( domain, username );
153
154 return 0;
155}
156
157/**
158 * Construct HTTP "Authorization" header for NTLM authentication
159 *
160 * @v http HTTP transaction
161 * @v buf Buffer
162 * @v len Length of buffer
163 * @ret len Length of header value, or negative error
164 */
165static int http_format_ntlm_auth ( struct http_transaction *http,
166 char *buf, size_t len ) {
167 struct http_request_auth_ntlm *req = &http->request.auth.ntlm;
169 struct ntlm_authenticate *auth;
170 const char *domain;
171 char *username;
172 size_t check;
173
174 /* If we have no challenge yet, then just send a Negotiate message */
175 if ( ! rsp->challenge ) {
177 sizeof ( ntlm_negotiate ), buf, len );
178 }
179
180 /* Skip allocation if just calculating length */
181 if ( ! len )
182 return base64_encoded_len ( req->len );
183
184 /* Allocate temporary buffer for Authenticate message */
185 auth = malloc ( req->len );
186 if ( ! auth )
187 return -ENOMEM;
188
189 /* Split NetBIOS [domain\]username */
190 username = ( ( char * ) req->username );
192
193 /* Construct raw Authenticate message */
194 check = ntlm_authenticate ( &rsp->info, domain, username,
196 &req->nt, auth );
197 assert ( check == req->len );
198
199 /* Restore NetBIOS [domain\]username */
201
202 /* Base64-encode Authenticate message */
203 len = base64_encode ( auth, req->len, buf, len );
204
205 /* Free raw Authenticate message */
206 free ( auth );
207
208 return len;
209}
210
211/** HTTP NTLM authentication scheme */
212struct http_authentication http_ntlm_auth __http_authentication = {
213 .name = "NTLM",
214 .parse = http_parse_ntlm_auth,
215 .authenticate = http_ntlm_authenticate,
216 .format = http_format_ntlm_auth,
217};
218
219/* Drag in HTTP authentication support */
220REQUIRING_SYMBOL ( http_ntlm_auth );
221REQUIRE_OBJECT ( httpauth );
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
union @162305117151260234136356364136041353210355154177 key
Sense key.
Definition scsi.h:3
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
size_t base64_encode(const void *raw, size_t raw_len, char *data, size_t len)
Base64-encode data.
Definition base64.c:52
int base64_decode(const char *encoded, void *data, size_t len)
Base64-decode string.
Definition base64.c:92
Base64 encoding.
static size_t base64_encoded_len(size_t raw_len)
Calculate length of base64-encoded data.
Definition base64.h:22
ring len
Length.
Definition dwmac.h:226
Error codes.
#define DBGC(...)
Definition compiler.h:505
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define REQUIRE_OBJECT(object)
Require an object.
Definition compiler.h:202
#define ENOMEM
Not enough space.
Definition errno.h:535
#define EACCES
Permission denied.
Definition errno.h:299
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
#define REQUIRING_SYMBOL(symbol)
Specify the file's requiring symbol.
Definition compiler.h:140
Hyper Text Transport Protocol.
@ HTTP_RESPONSE_RETRY
Transaction may be retried on failure.
Definition http.h:361
#define __http_authentication
Declare an HTTP authentication scheme.
Definition http.h:551
static int http_ntlm_authenticate(struct http_transaction *http)
Perform HTTP NTLM authentication.
Definition httpntlm.c:114
static int http_parse_ntlm_auth(struct http_transaction *http, char *line)
Parse HTTP "WWW-Authenticate" header for NTLM authentication.
Definition httpntlm.c:54
static const char http_ntlm_workstation[]
Workstation name used for NTLM authentication.
Definition httpntlm.c:45
static int http_format_ntlm_auth(struct http_transaction *http, char *buf, size_t len)
Construct HTTP "Authorization" header for NTLM authentication.
Definition httpntlm.c:165
String functions.
uint64_t rsp
Definition librm.h:18
static struct dynamic_item username
Definition login_ui.c:36
static struct dynamic_item password
Definition login_ui.c:37
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:621
const char * netbios_domain(char **username)
Split NetBIOS [domain]username into separate domain and username fields.
Definition netbios.c:47
NetBIOS user names.
static void netbios_domain_undo(const char *domain, char *username)
Restore NetBIOS [domain]username.
Definition netbios.h:24
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(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:267
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.
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
char * strdup(const char *src)
Duplicate string.
Definition string.c:394
size_t strlen(const char *src)
Get length of string.
Definition string.c:244
An HTTP authentication scheme.
Definition http.h:519
HTTP request NTLM authentication descriptor.
Definition http.h:176
struct ntlm_lm_response lm
LAN Manager response.
Definition http.h:180
size_t len
Authenticate message length.
Definition http.h:184
struct ntlm_nt_response nt
NT response.
Definition http.h:182
const char * username
Username.
Definition http.h:178
struct http_authentication * auth
Authentication scheme (if any)
Definition http.h:190
struct http_request_auth_ntlm ntlm
NTLM authentication descriptor.
Definition http.h:198
struct http_request_auth auth
Authentication descriptor.
Definition http.h:223
HTTP response NTLM authorization descriptor.
Definition http.h:288
struct http_response_auth_ntlm ntlm
NTLM authorization descriptor.
Definition http.h:306
unsigned int flags
Flags.
Definition http.h:351
struct http_response_auth auth
Authorization descriptor.
Definition http.h:347
An HTTP transaction.
Definition http.h:416
struct http_response response
Response.
Definition http.h:439
struct uri * uri
Request URI.
Definition http.h:435
struct http_request request
Request.
Definition http.h:437
An Authenticate message.
Definition ntlm.h:117
struct ntlm_data domain
Domain name.
Definition ntlm.h:125
A Challenge message.
Definition ntlm.h:101
An NTLM verification key.
Definition ntlm.h:176
A Negotiate message.
Definition ntlm.h:89
const char * user
User name.
Definition uri.h:73
const char * password
Password.
Definition uri.h:75
Uniform Resource Identifiers.