2 Unix SMB/CIFS implementation.
4 dcerpc authentication operations
6 Copyright (C) Andrew Tridgell 2003
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 struct gensec_ntlmssp_state {
27 struct auth_context *auth_context;
28 struct auth_serversupplied_info *server_info;
29 struct ntlmssp_state *ntlmssp_state;
34 * Return the challenge as determined by the authentication subsystem
35 * @return an 8 byte random challenge
38 static const uint8_t *auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_state)
40 struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
42 return gensec_ntlmssp_state->auth_context->get_ntlm_challenge(gensec_ntlmssp_state->auth_context);
46 * Some authentication methods 'fix' the challenge, so we may not be able to set it
48 * @return If the effective challenge used by the auth subsystem may be modified
50 static BOOL auth_ntlmssp_may_set_challenge(const struct ntlmssp_state *ntlmssp_state)
52 struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
54 return gensec_ntlmssp_state->auth_context->challenge_may_be_modified;
58 * NTLM2 authentication modifies the effective challenge,
59 * @param challenge The new challenge value
61 static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge)
63 struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
64 struct auth_context *auth_context = gensec_ntlmssp_state->auth_context;
66 SMB_ASSERT(challenge->length == 8);
68 auth_context->challenge = data_blob_talloc(auth_context->mem_ctx,
69 challenge->data, challenge->length);
71 auth_context->challenge_set_by = "NTLMSSP callback (NTLM2)";
73 DEBUG(5, ("auth_context challenge set by %s\n", auth_context->challenge_set_by));
74 DEBUG(5, ("challenge is: \n"));
75 dump_data(5, (const char *)auth_context->challenge.data, auth_context->challenge.length);
80 * Check the password on an NTLMSSP login.
82 * Return the session keys used on the connection.
85 static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key)
87 struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
88 struct auth_usersupplied_info *user_info = NULL;
92 /* the client has given us its machine name (which we otherwise would not get on port 445).
93 we need to possibly reload smb.conf if smb.conf includes depend on the machine name */
95 set_remote_machine_name(gensec_ntlmssp_state->ntlmssp_state->workstation, True);
97 /* setup the string used by %U */
98 /* sub_set_smb_name checks for weird internally */
99 sub_set_smb_name(gensec_ntlmssp_state->ntlmssp_state->user);
101 reload_services(True);
104 nt_status = make_user_info_map(&user_info,
105 gensec_ntlmssp_state->ntlmssp_state->user,
106 gensec_ntlmssp_state->ntlmssp_state->domain,
107 gensec_ntlmssp_state->ntlmssp_state->workstation,
108 gensec_ntlmssp_state->ntlmssp_state->lm_resp.data ? &gensec_ntlmssp_state->ntlmssp_state->lm_resp : NULL,
109 gensec_ntlmssp_state->ntlmssp_state->nt_resp.data ? &gensec_ntlmssp_state->ntlmssp_state->nt_resp : NULL,
113 if (!NT_STATUS_IS_OK(nt_status)) {
117 nt_status = gensec_ntlmssp_state->auth_context->check_ntlm_password(gensec_ntlmssp_state->auth_context,
118 user_info, &gensec_ntlmssp_state->server_info);
120 free_user_info(&user_info);
122 if (!NT_STATUS_IS_OK(nt_status)) {
125 if (gensec_ntlmssp_state->server_info->user_session_key.length) {
126 DEBUG(10, ("Got NT session key of length %u\n", gensec_ntlmssp_state->server_info->user_session_key.length));
127 *user_session_key = data_blob_talloc(ntlmssp_state,
128 gensec_ntlmssp_state->server_info->user_session_key.data,
129 gensec_ntlmssp_state->server_info->user_session_key.length);
131 if (gensec_ntlmssp_state->server_info->lm_session_key.length) {
132 DEBUG(10, ("Got LM session key of length %u\n", gensec_ntlmssp_state->server_info->lm_session_key.length));
133 *lm_session_key = data_blob_talloc(ntlmssp_state,
134 gensec_ntlmssp_state->server_info->lm_session_key.data,
135 gensec_ntlmssp_state->server_info->lm_session_key.length);
140 static NTSTATUS gensec_ntlmssp_start(struct gensec_security *gensec_security)
142 struct gensec_ntlmssp_state *gensec_ntlmssp_state;
144 gensec_ntlmssp_state = talloc_p(gensec_security, struct gensec_ntlmssp_state);
145 if (!gensec_ntlmssp_state) {
146 return NT_STATUS_NO_MEMORY;
149 gensec_ntlmssp_state->ntlmssp_state = NULL;
150 gensec_ntlmssp_state->auth_context = NULL;
151 gensec_ntlmssp_state->server_info = NULL;
153 gensec_security->private_data = gensec_ntlmssp_state;
157 static NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security)
161 struct ntlmssp_state *ntlmssp_state;
162 struct gensec_ntlmssp_state *gensec_ntlmssp_state;
164 status = gensec_ntlmssp_start(gensec_security);
165 if (!NT_STATUS_IS_OK(status)) {
169 gensec_ntlmssp_state = gensec_security->private_data;
171 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_server_start(gensec_security,
172 &gensec_ntlmssp_state->ntlmssp_state))) {
176 if (gensec_security->want_features & GENSEC_WANT_SIGN) {
177 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
179 if (gensec_security->want_features & GENSEC_WANT_SEAL) {
180 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
183 /* IF we are not doing Signing or Sealing, we can actually do
184 * NTLM2. When we crack the crypto puzzle, then we can enable
185 * this always, in the constant flags */
187 if (!(gensec_security->want_features & GENSEC_WANT_SIGN) && !(gensec_security->want_features & GENSEC_WANT_SEAL)) {
188 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;
191 ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state;
192 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&gensec_ntlmssp_state->auth_context))) {
196 ntlmssp_state->auth_context = gensec_ntlmssp_state;
197 ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge;
198 ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge;
199 ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge;
200 ntlmssp_state->check_password = auth_ntlmssp_check_password;
201 ntlmssp_state->server_role = lp_server_role();
206 static NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
208 struct gensec_ntlmssp_state *gensec_ntlmssp_state;
209 char *password = NULL;
212 status = gensec_ntlmssp_start(gensec_security);
213 if (!NT_STATUS_IS_OK(status)) {
217 gensec_ntlmssp_state = gensec_security->private_data;
218 status = ntlmssp_client_start(gensec_security,
219 &gensec_ntlmssp_state->ntlmssp_state);
220 if (!NT_STATUS_IS_OK(status)) {
224 if (gensec_security->want_features & GENSEC_WANT_SESSION_KEY) {
226 * We need to set this to allow a later SetPassword
227 * via the SAMR pipe to succeed. Strange.... We could
228 * also add NTLMSSP_NEGOTIATE_SEAL here. JRA.
230 * Without this, Windows will not create the master key
231 * that it thinks is only used for NTLMSSP signing and
232 * sealing. (It is actually pulled out and used directly)
234 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
236 if (gensec_security->want_features & GENSEC_WANT_SIGN) {
237 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
239 if (gensec_security->want_features & GENSEC_WANT_SEAL) {
240 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
243 /* IF we are not doing Signing or Sealing, we can actually do
244 * NTLM2. When we crack the crypto puzzle, then we can enable
245 * this always, in the constant flags */
247 if (!(gensec_security->want_features & GENSEC_WANT_SIGN) && !(gensec_security->want_features & GENSEC_WANT_SEAL)) {
248 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;
251 status = ntlmssp_set_domain(gensec_ntlmssp_state->ntlmssp_state,
252 gensec_security->user.domain);
253 if (!NT_STATUS_IS_OK(status)) {
257 status = ntlmssp_set_username(gensec_ntlmssp_state->ntlmssp_state,
258 gensec_security->user.name);
259 if (!NT_STATUS_IS_OK(status)) {
263 status = gensec_get_password(gensec_security, gensec_ntlmssp_state, &password);
264 if (!NT_STATUS_IS_OK(status)) {
269 status = ntlmssp_set_password(gensec_ntlmssp_state->ntlmssp_state,
271 if (!NT_STATUS_IS_OK(status)) {
276 gensec_security->private_data = gensec_ntlmssp_state;
282 wrappers for the ntlmssp_*() functions
284 static NTSTATUS gensec_ntlmssp_unseal_packet(struct gensec_security *gensec_security,
286 uint8_t *data, size_t length,
287 const uint8_t *whole_pdu, size_t pdu_length,
290 struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
292 return ntlmssp_unseal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
295 static NTSTATUS gensec_ntlmssp_check_packet(struct gensec_security *gensec_security,
297 const uint8_t *data, size_t length,
298 const uint8_t *whole_pdu, size_t pdu_length,
299 const DATA_BLOB *sig)
301 struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
303 return ntlmssp_check_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
306 static NTSTATUS gensec_ntlmssp_seal_packet(struct gensec_security *gensec_security,
308 uint8_t *data, size_t length,
309 const uint8_t *whole_pdu, size_t pdu_length,
312 struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
314 return ntlmssp_seal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
317 static NTSTATUS gensec_ntlmssp_sign_packet(struct gensec_security *gensec_security,
319 const uint8_t *data, size_t length,
320 const uint8_t *whole_pdu, size_t pdu_length,
323 struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
325 return ntlmssp_sign_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
328 static size_t gensec_ntlmssp_sig_size(struct gensec_security *gensec_security)
330 return NTLMSSP_SIG_SIZE;
333 static NTSTATUS gensec_ntlmssp_session_key(struct gensec_security *gensec_security,
334 DATA_BLOB *session_key)
336 struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
338 return ntlmssp_session_key(gensec_ntlmssp_state->ntlmssp_state, session_key);
342 * Next state function for the wrapped NTLMSSP state machine
344 * @param gensec_security GENSEC state, initialised to NTLMSSP
345 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
346 * @param in The request, as a DATA_BLOB
347 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
348 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
349 * or NT_STATUS_OK if the user is authenticated.
352 static NTSTATUS gensec_ntlmssp_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx,
353 const DATA_BLOB in, DATA_BLOB *out)
355 struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
357 return ntlmssp_update(gensec_ntlmssp_state->ntlmssp_state, out_mem_ctx, in, out);
361 * Return the credentials of a logged on user, including session keys
364 * Only valid after a successful authentication
366 * May only be called once per authentication.
370 static NTSTATUS gensec_ntlmssp_session_info(struct gensec_security *gensec_security,
371 struct auth_session_info **session_info)
374 struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
375 nt_status = make_session_info(gensec_ntlmssp_state->server_info, session_info);
377 if (!NT_STATUS_IS_OK(nt_status)) {
381 /* the session_info owns this now */
382 gensec_ntlmssp_state->server_info = NULL;
384 (*session_info)->session_key = data_blob_talloc(*session_info,
385 gensec_ntlmssp_state->ntlmssp_state->session_key.data,
386 gensec_ntlmssp_state->ntlmssp_state->session_key.length);
388 (*session_info)->workstation = talloc_strdup(*session_info,
389 gensec_ntlmssp_state->ntlmssp_state->workstation);
394 static void gensec_ntlmssp_end(struct gensec_security *gensec_security)
396 struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
398 if (gensec_ntlmssp_state->ntlmssp_state) {
399 ntlmssp_end(&gensec_ntlmssp_state->ntlmssp_state);
402 if (gensec_ntlmssp_state->auth_context) {
403 free_auth_context(&gensec_ntlmssp_state->auth_context);
405 if (gensec_ntlmssp_state->server_info) {
406 free_server_info(&gensec_ntlmssp_state->server_info);
408 talloc_free(gensec_ntlmssp_state);
409 gensec_security->private_data = NULL;
412 static const struct gensec_security_ops gensec_ntlmssp_security_ops = {
415 .auth_type = DCERPC_AUTH_TYPE_NTLMSSP,
417 .client_start = gensec_ntlmssp_client_start,
418 .server_start = gensec_ntlmssp_server_start,
419 .update = gensec_ntlmssp_update,
420 .seal_packet = gensec_ntlmssp_seal_packet,
421 .sig_size = gensec_ntlmssp_sig_size,
422 .sign_packet = gensec_ntlmssp_sign_packet,
423 .check_packet = gensec_ntlmssp_check_packet,
424 .unseal_packet = gensec_ntlmssp_unseal_packet,
425 .session_key = gensec_ntlmssp_session_key,
426 .session_info = gensec_ntlmssp_session_info,
427 .end = gensec_ntlmssp_end
431 NTSTATUS gensec_ntlmssp_init(void)
434 ret = register_backend("gensec", &gensec_ntlmssp_security_ops);
435 if (!NT_STATUS_IS_OK(ret)) {
436 DEBUG(0,("Failed to register '%s' gensec backend!\n",
437 gensec_ntlmssp_security_ops.name));
441 /* ugly cludge, but we need the auth subsystem for this to work */