1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
|
/*
* Copyright (c) Edward Thomson. All rights reserved.
*
* This file is part of ntlmclient, distributed under the MIT license.
* For full terms and copyright information, and for third-party
* copyright information, see the included LICENSE.txt file.
*/
#ifndef INCLUDE_NTLMCLIENT_H__
#define INCLUDE_NTLMCLIENT_H__
#include <stdlib.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define NTLM_CLIENT_VERSION "0.0.1"
#define NTLM_CLIENT_VERSION_MAJOR 0
#define NTLM_CLIENT_VERSION_MINOR 0
#define NTLM_CLIENT_VERSION_TEENY 1
typedef struct ntlm_client ntlm_client;
/*
* Flags for initializing the `ntlm_client` context. A combination of
* these flags can be provided to `ntlm_client_init`.
*/
typedef enum {
/** Default settings for the `ntlm_client`. */
NTLM_CLIENT_DEFAULTS = 0,
/**
* Disable Unicode negotiation. By default, strings are converted
* into UTF-16 when supplied to the remote host, but if this flag
* is specified, localizable strings (like username and password)
* will only be sent to the server as they were provided to the
* library. Since the NTLM protocol does not deliver the locale
* information, these will be interpreted by the remote host in
* whatever locale is configured, and likely be corrupted unless
* you limit yourself to ASCII.
*
* You are discouraged from setting this flag.
*/
NTLM_CLIENT_DISABLE_UNICODE = (1 << 0),
/*
* Enable LM ("Lan Manager") authentication support. By default,
* LM authentication is disabled, since most remote servers have
* disabled support for it, and because it is both trivially
* brute-forced _and_ subject to rainbow table lookups. If this
* flag is enabled, LM is still not used unless NTLM2 support is
* also disabled.
*
* You are discouraged from setting this flag.
*/
NTLM_CLIENT_ENABLE_LM = (1 << 1),
/*
* Enable NTLM ("Lan Manager") authentication support. By default,
* NTLM authentication is disabled, since most remote servers have
* disabled support for it, due to its weakness. If this flag is
* enabled, NTLM is still not used unless NTLM2 support is also
* disabled.
*
* You are discouraged from setting this flag.
*/
NTLM_CLIENT_ENABLE_NTLM = (1 << 2),
/*
* Disable NTLM2 authentication support. By default, _only_ NTLM2
* support is enabled, since most remote servers will only support
* it due to its (relative) lack of weakness. If this flag is
* set, either NTLM or LM (or both) must be explicitly enabled or
* there will be no mechanisms available to use.
*
* You are discouraged from setting this flag.
*/
NTLM_CLIENT_DISABLE_NTLM2 = (1 << 3),
/*
* Request the target's name. By default, you are expected to
* provide the name of the target you are authenticating to (eg,
* the remote hostname). If set, the remote host will provide
* its idea of its hostname in the challenge message. You may
* then set the authentication target based on it.
*/
NTLM_CLIENT_DISABLE_REQUEST_TARGET = (1 << 4),
} ntlm_client_flags;
/** Declare a public function exported for application use. */
#if __GNUC__ >= 4 && !defined(NTLM_STATIC)
# define NTLM_EXTERN(type) extern \
__attribute__((visibility("default"))) \
type
#elif defined(_MSC_VER) && !defined(NTLM_STATIC)
# define NTLM_EXTERN(type) __declspec(dllexport) type
#else
# define NTLM_EXTERN(type) extern type
#endif
/**
* Initializes an `ntlm_client` context, which can begin sending
* and receiving NTLM authentication messages.
*
* @param flags the `ntlm_client_flag_t`s to use for negotiation.
* @return the `ntlm_client` context, or `NULL` if out-of-memory.
*/
NTLM_EXTERN(ntlm_client *) ntlm_client_init(ntlm_client_flags flags);
/**
* Gets the error message for the most recent error that occurred. If
* a function returns an error, more details can be retrieved with this
* function. The string returned is a constant string; it should not
* be freed.
*
* @return a constant string containing the error message.
*/
NTLM_EXTERN(const char *) ntlm_client_errmsg(ntlm_client *ntlm);
/**
* Sets the local hostname and domain. These strings should be in
* ASCII. They will be provided to the remote host during the
* negotiation phase.
*
* @param ntlm the `ntlm_client` context to configure
* @param hostname the hostname of the local machine
* @param domain the domain of the local machine
* @return 0 on success, non-zero on failure
*/
NTLM_EXTERN(int) ntlm_client_set_hostname(
ntlm_client *ntlm,
const char *hostname,
const char *domain);
/**
* Sets the local operating system version. These numbers are expected
* to correspond to Windows operating system versions; for example
* major version 6, minor version 2, build 9200 would correspond to
* Windows 8 (aka "NT 6.2").
*
* It is not likely that you need to set the local version.
*
* @param ntlm the `ntlm_client` context to configure
* @param major the major version number of the local operating system
* @param minor the minor version number of the local operating system
* @param build the build number of the local operating system
* @return 0 on success, non-zero on failure
*/
NTLM_EXTERN(int) ntlm_client_set_version(
ntlm_client *ntlm,
uint8_t major,
uint8_t minor,
uint16_t build);
/**
* Sets the username and password to authenticate with to the remote
* host. Username and password may be specified in UTF-8 but the
* domain should be in ASCII. These will not be sent to the remote host
* but will instead be used to compute the LM, NTLM or NTLM2 responses,
* which will be provided to the remote host during the response phase.
*
* @param ntlm the `ntlm_client` context to configure
* @param username the username to authenticate with
* @param domain the domain of the user authenticating
* @param password the password to authenticate with
* @return 0 on success, non-zero on failure
*/
NTLM_EXTERN(int) ntlm_client_set_credentials(
ntlm_client *ntlm,
const char *username,
const char *domain,
const char *password);
/**
* Sets the authentication target, your idea of the remote host's
* name. The target should be provided as ASCII. It will be
* provided to the remote host during the response phase.
*
* @param ntlm the `ntlm_client` context to configure
* @param target the name of the authentication target
* @return 0 on success, non-zero on failure
*/
NTLM_EXTERN(int) ntlm_client_set_target(
ntlm_client *ntlm,
const char *target);
/**
* Gets the remote host's nonce, as it was provided in the challenge
* message. This is an opaque 8 byte value that is used to compute
* the LM, NTLM and NTLM2 responses.
*
* @param ntlm the `ntlm_client` context to query
* @return the challenge from the remote host
*/
NTLM_EXTERN(uint64_t) ntlm_client_challenge_nonce(
ntlm_client *ntlm);
/**
* Gets the remote hosts's target name, which can be used as the
* authentication target. This will be given as it was provided
* in the challenge message.
*
* @param ntlm the `ntlm_client` context to query
* @return the remote host's target name
*/
NTLM_EXTERN(const char *) ntlm_client_target(ntlm_client *ntlm);
/**
* Gets the remote hosts's name, which is generally its short name.
* This will be given as it was provided in the challenge message.
*
* @param ntlm the `ntlm_client` context to query
* @return the remote host's server name
*/
NTLM_EXTERN(const char *) ntlm_client_target_server(ntlm_client *ntlm);
/**
* Gets the remote hosts's domain, which is generally the short or
* NT-style domain name. This will be given as it was provided in
* the challenge message.
*
* @param ntlm the `ntlm_client` context to query
* @return the remote host's domain
*/
NTLM_EXTERN(const char *) ntlm_client_target_domain(ntlm_client *ntlm);
/**
* Gets the remote hosts's DNS name, which is generally the long-style
* Active Directory or fully-qualified hostname. This will be given
* as it was provided in the challenge message.
*
* @param ntlm the `ntlm_client` context to query
* @return the remote host's DNS name
*/
NTLM_EXTERN(const char *) ntlm_client_target_server_dns(ntlm_client *ntlm);
/**
* Gets the remote hosts's DNS domain, which is generally the long-style
* Active Directory or fully-qualified domain name. This will be given
* as it was provided in the challenge message.
*
* @param ntlm the `ntlm_client` context to query
* @return the remote host's DNS domain
*/
NTLM_EXTERN(const char *) ntlm_client_target_domain_dns(ntlm_client *ntlm);
/**
* Computes a negotiation message (aka a "Type 1" message) to begin
* NTLM authentication with the server. The local hostname should be
* set before calling this function (if necessary). This message
* should be delivered to the server to indicate a willingness to begin
* NTLM authentication. This buffer should not be freed by the caller.
*
* @param out a pointer to the negotiation message
* @param out_len a pointer to the length of the negotiation message
* @param ntlm the `ntlm_client` context
* @return 0 on success, non-zero on failure
*/
NTLM_EXTERN(int) ntlm_client_negotiate(
const unsigned char **out,
size_t *out_len,
ntlm_client *ntlm);
/**
* Parses a challenge message (aka a "Type 2" message) from the server.
* This must be called in order to calculate the response to the
* authentication.
*
* @param ntlm the `ntlm_client` context
* @param message the challenge message from the server
* @param message_len the length of the challenge message
* @return 0 on success, non-zero on failure
*/
NTLM_EXTERN(int) ntlm_client_set_challenge(
ntlm_client *ntlm,
const unsigned char *message,
size_t message_len);
/**
* Computes a response message (aka a "Type 3" message) to complete
* NTLM authentication with the server. The credentials should be
* set before calling this function. This message should be delivered
* to the server to complete authentication. This buffer should not
* be freed by the caller.
*
* @param out a pointer to the response message
* @param out_len a pointer to the length of the response message
* @param ntlm the `ntlm_client` context
* @return 0 on success, non-zero on failure
*/
NTLM_EXTERN(int) ntlm_client_response(
const unsigned char **out,
size_t *out_len,
ntlm_client *ntlm);
/**
* Resets an `ntlm_client` context completely, so that authentication
* may be retried. You must set _all_ parameters again, including the
* target, username, password, etc. Once these values are configured
* again, the negotiation can begin.
*
* @param ntlm the `ntlm_client` context to reset
*/
NTLM_EXTERN(void) ntlm_client_reset(ntlm_client *ntlm);
/**
* Frees an `ntlm_client` context. This should be done to free memory
* belonging to the context. The context cannot be reused.
*
* @param ntlm the `ntlm_client` context to free
*/
NTLM_EXTERN(void) ntlm_client_free(ntlm_client *ntlm);
#ifdef __cplusplus
}
#endif
#endif /* INCLUDE_NTLMCLIENT_H__ */
|