r4504: Setting
[Samba/gebeck_regimport.git] / source4 / libcli / auth / gensec_ntlmssp.c
blob53d01042599473f553e69fc479bbc132bb42045d
1 /*
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.
24 #include "includes.h"
25 #include "auth/auth.h"
27 struct gensec_ntlmssp_state {
28 struct auth_context *auth_context;
29 struct auth_serversupplied_info *server_info;
30 struct ntlmssp_state *ntlmssp_state;
31 uint32 have_features;
35 /**
36 * Return the challenge as determined by the authentication subsystem
37 * @return an 8 byte random challenge
40 static const uint8_t *auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_state)
42 struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
44 return gensec_ntlmssp_state->auth_context->get_ntlm_challenge(gensec_ntlmssp_state->auth_context);
47 /**
48 * Some authentication methods 'fix' the challenge, so we may not be able to set it
50 * @return If the effective challenge used by the auth subsystem may be modified
52 static BOOL auth_ntlmssp_may_set_challenge(const struct ntlmssp_state *ntlmssp_state)
54 struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
56 return gensec_ntlmssp_state->auth_context->challenge_may_be_modified;
59 /**
60 * NTLM2 authentication modifies the effective challenge,
61 * @param challenge The new challenge value
63 static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge)
65 struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
66 struct auth_context *auth_context = gensec_ntlmssp_state->auth_context;
68 SMB_ASSERT(challenge->length == 8);
70 auth_context->challenge = data_blob_talloc(auth_context,
71 challenge->data, challenge->length);
73 auth_context->challenge_set_by = "NTLMSSP callback (NTLM2)";
75 DEBUG(5, ("auth_context challenge set by %s\n", auth_context->challenge_set_by));
76 DEBUG(5, ("challenge is: \n"));
77 dump_data(5, auth_context->challenge.data, auth_context->challenge.length);
78 return NT_STATUS_OK;
81 /**
82 * Check the password on an NTLMSSP login.
84 * Return the session keys used on the connection.
87 static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key)
89 struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
90 struct auth_usersupplied_info *user_info = NULL;
91 NTSTATUS nt_status;
93 #if 0
94 /* the client has given us its machine name (which we otherwise would not get on port 445).
95 we need to possibly reload smb.conf if smb.conf includes depend on the machine name */
97 set_remote_machine_name(gensec_ntlmssp_state->ntlmssp_state->workstation, True);
99 /* setup the string used by %U */
100 /* sub_set_smb_name checks for weird internally */
101 sub_set_smb_name(gensec_ntlmssp_state->ntlmssp_state->user);
103 reload_services(True);
105 #endif
106 nt_status = make_user_info_map(ntlmssp_state,
107 &user_info,
108 gensec_ntlmssp_state->ntlmssp_state->user,
109 gensec_ntlmssp_state->ntlmssp_state->domain,
110 gensec_ntlmssp_state->ntlmssp_state->workstation,
111 gensec_ntlmssp_state->ntlmssp_state->lm_resp.data ? &gensec_ntlmssp_state->ntlmssp_state->lm_resp : NULL,
112 gensec_ntlmssp_state->ntlmssp_state->nt_resp.data ? &gensec_ntlmssp_state->ntlmssp_state->nt_resp : NULL,
113 NULL, NULL, NULL,
114 True);
116 if (!NT_STATUS_IS_OK(nt_status)) {
117 return nt_status;
120 nt_status = gensec_ntlmssp_state->
121 auth_context->check_ntlm_password(gensec_ntlmssp_state->auth_context,
122 user_info,
123 gensec_ntlmssp_state,
124 &gensec_ntlmssp_state->server_info);
126 free_user_info(&user_info);
128 if (!NT_STATUS_IS_OK(nt_status)) {
129 return nt_status;
131 if (gensec_ntlmssp_state->server_info->user_session_key.length) {
132 DEBUG(10, ("Got NT session key of length %u\n", gensec_ntlmssp_state->server_info->user_session_key.length));
133 *user_session_key = data_blob_talloc(ntlmssp_state,
134 gensec_ntlmssp_state->server_info->user_session_key.data,
135 gensec_ntlmssp_state->server_info->user_session_key.length);
137 if (gensec_ntlmssp_state->server_info->lm_session_key.length) {
138 DEBUG(10, ("Got LM session key of length %u\n", gensec_ntlmssp_state->server_info->lm_session_key.length));
139 *lm_session_key = data_blob_talloc(ntlmssp_state,
140 gensec_ntlmssp_state->server_info->lm_session_key.data,
141 gensec_ntlmssp_state->server_info->lm_session_key.length);
143 return nt_status;
146 static int gensec_ntlmssp_destroy(void *ptr)
148 struct gensec_ntlmssp_state *gensec_ntlmssp_state = ptr;
150 if (gensec_ntlmssp_state->ntlmssp_state) {
151 ntlmssp_end(&gensec_ntlmssp_state->ntlmssp_state);
154 if (gensec_ntlmssp_state->auth_context) {
155 free_auth_context(&gensec_ntlmssp_state->auth_context);
157 if (gensec_ntlmssp_state->server_info) {
158 free_server_info(&gensec_ntlmssp_state->server_info);
160 return 0;
163 static NTSTATUS gensec_ntlmssp_start(struct gensec_security *gensec_security)
165 struct gensec_ntlmssp_state *gensec_ntlmssp_state;
167 gensec_ntlmssp_state = talloc_p(gensec_security, struct gensec_ntlmssp_state);
168 if (!gensec_ntlmssp_state) {
169 return NT_STATUS_NO_MEMORY;
172 gensec_ntlmssp_state->ntlmssp_state = NULL;
173 gensec_ntlmssp_state->auth_context = NULL;
174 gensec_ntlmssp_state->server_info = NULL;
175 gensec_ntlmssp_state->have_features = 0;
177 talloc_set_destructor(gensec_ntlmssp_state, gensec_ntlmssp_destroy);
179 gensec_security->private_data = gensec_ntlmssp_state;
180 return NT_STATUS_OK;
183 static NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security)
185 NTSTATUS nt_status;
186 NTSTATUS status;
187 struct ntlmssp_state *ntlmssp_state;
188 struct gensec_ntlmssp_state *gensec_ntlmssp_state;
190 status = gensec_ntlmssp_start(gensec_security);
191 if (!NT_STATUS_IS_OK(status)) {
192 return status;
195 gensec_ntlmssp_state = gensec_security->private_data;
197 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_server_start(gensec_ntlmssp_state,
198 &gensec_ntlmssp_state->ntlmssp_state))) {
199 return nt_status;
202 if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
203 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
205 if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
206 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
209 ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state;
210 nt_status = make_auth_context_subsystem(gensec_ntlmssp_state, &gensec_ntlmssp_state->auth_context);
211 if (!NT_STATUS_IS_OK(nt_status)) {
212 return nt_status;
215 ntlmssp_state->auth_context = gensec_ntlmssp_state;
216 ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge;
217 ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge;
218 ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge;
219 ntlmssp_state->check_password = auth_ntlmssp_check_password;
220 ntlmssp_state->server_role = lp_server_role();
222 return NT_STATUS_OK;
225 static NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
227 struct gensec_ntlmssp_state *gensec_ntlmssp_state;
228 char *password = NULL;
230 NTSTATUS status;
231 status = gensec_ntlmssp_start(gensec_security);
232 if (!NT_STATUS_IS_OK(status)) {
233 return status;
236 gensec_ntlmssp_state = gensec_security->private_data;
237 status = ntlmssp_client_start(gensec_ntlmssp_state,
238 &gensec_ntlmssp_state->ntlmssp_state);
239 if (!NT_STATUS_IS_OK(status)) {
240 return status;
243 if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
245 * We need to set this to allow a later SetPassword
246 * via the SAMR pipe to succeed. Strange.... We could
247 * also add NTLMSSP_NEGOTIATE_SEAL here. JRA.
249 * Without this, Windows will not create the master key
250 * that it thinks is only used for NTLMSSP signing and
251 * sealing. (It is actually pulled out and used directly)
253 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
255 if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
256 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
258 if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
259 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
262 status = ntlmssp_set_domain(gensec_ntlmssp_state->ntlmssp_state,
263 gensec_security->user.domain);
264 if (!NT_STATUS_IS_OK(status)) {
265 return status;
268 status = ntlmssp_set_username(gensec_ntlmssp_state->ntlmssp_state,
269 gensec_security->user.name);
270 if (!NT_STATUS_IS_OK(status)) {
271 return status;
274 if (gensec_security->user.name) {
275 status = gensec_get_password(gensec_security, gensec_ntlmssp_state, &password);
276 if (!NT_STATUS_IS_OK(status)) {
277 return status;
281 if (password) {
282 status = ntlmssp_set_password(gensec_ntlmssp_state->ntlmssp_state,
283 password);
284 if (!NT_STATUS_IS_OK(status)) {
285 return status;
289 gensec_security->private_data = gensec_ntlmssp_state;
291 return status;
295 wrappers for the ntlmssp_*() functions
297 static NTSTATUS gensec_ntlmssp_unseal_packet(struct gensec_security *gensec_security,
298 TALLOC_CTX *mem_ctx,
299 uint8_t *data, size_t length,
300 const uint8_t *whole_pdu, size_t pdu_length,
301 DATA_BLOB *sig)
303 struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
305 return ntlmssp_unseal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
308 static NTSTATUS gensec_ntlmssp_check_packet(struct gensec_security *gensec_security,
309 TALLOC_CTX *mem_ctx,
310 const uint8_t *data, size_t length,
311 const uint8_t *whole_pdu, size_t pdu_length,
312 const DATA_BLOB *sig)
314 struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
316 return ntlmssp_check_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
319 static NTSTATUS gensec_ntlmssp_seal_packet(struct gensec_security *gensec_security,
320 TALLOC_CTX *mem_ctx,
321 uint8_t *data, size_t length,
322 const uint8_t *whole_pdu, size_t pdu_length,
323 DATA_BLOB *sig)
325 struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
327 return ntlmssp_seal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
330 static NTSTATUS gensec_ntlmssp_sign_packet(struct gensec_security *gensec_security,
331 TALLOC_CTX *mem_ctx,
332 const uint8_t *data, size_t length,
333 const uint8_t *whole_pdu, size_t pdu_length,
334 DATA_BLOB *sig)
336 struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
338 return ntlmssp_sign_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
341 static size_t gensec_ntlmssp_sig_size(struct gensec_security *gensec_security)
343 return NTLMSSP_SIG_SIZE;
346 static NTSTATUS gensec_ntlmssp_wrap(struct gensec_security *gensec_security,
347 TALLOC_CTX *mem_ctx,
348 const DATA_BLOB *in,
349 DATA_BLOB *out)
351 struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
352 DATA_BLOB sig;
353 NTSTATUS nt_status;
355 if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
357 *out = data_blob_talloc(mem_ctx, NULL, in->length + NTLMSSP_SIG_SIZE);
358 memcpy(out->data + NTLMSSP_SIG_SIZE, in->data, in->length);
360 nt_status = ntlmssp_seal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx,
361 out->data + NTLMSSP_SIG_SIZE,
362 out->length - NTLMSSP_SIG_SIZE,
363 out->data + NTLMSSP_SIG_SIZE,
364 out->length - NTLMSSP_SIG_SIZE,
365 &sig);
367 if (NT_STATUS_IS_OK(nt_status)) {
368 memcpy(out->data, sig.data, NTLMSSP_SIG_SIZE);
370 return nt_status;
372 } else if ((gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN)
373 || (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) {
375 *out = data_blob_talloc(mem_ctx, NULL, in->length + NTLMSSP_SIG_SIZE);
376 memcpy(out->data + NTLMSSP_SIG_SIZE, in->data, in->length);
378 nt_status = ntlmssp_sign_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx,
379 out->data + NTLMSSP_SIG_SIZE,
380 out->length - NTLMSSP_SIG_SIZE,
381 out->data + NTLMSSP_SIG_SIZE,
382 out->length - NTLMSSP_SIG_SIZE,
383 &sig);
385 if (NT_STATUS_IS_OK(nt_status)) {
386 memcpy(out->data, sig.data, NTLMSSP_SIG_SIZE);
388 return nt_status;
390 } else {
391 *out = *in;
392 return NT_STATUS_OK;
397 static NTSTATUS gensec_ntlmssp_unwrap(struct gensec_security *gensec_security,
398 TALLOC_CTX *mem_ctx,
399 const DATA_BLOB *in,
400 DATA_BLOB *out)
402 struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
403 DATA_BLOB sig;
405 if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
406 if (in->length < NTLMSSP_SIG_SIZE) {
407 return NT_STATUS_INVALID_PARAMETER;
409 sig.data = in->data;
410 sig.length = NTLMSSP_SIG_SIZE;
412 *out = data_blob_talloc(mem_ctx, in->data + NTLMSSP_SIG_SIZE, in->length - NTLMSSP_SIG_SIZE);
414 return ntlmssp_unseal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx,
415 out->data, out->length,
416 out->data, out->length,
417 &sig);
419 } else if ((gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN)
420 || (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) {
421 if (in->length < NTLMSSP_SIG_SIZE) {
422 return NT_STATUS_INVALID_PARAMETER;
424 sig.data = in->data;
425 sig.length = NTLMSSP_SIG_SIZE;
427 *out = data_blob_talloc(mem_ctx, in->data + NTLMSSP_SIG_SIZE, in->length - NTLMSSP_SIG_SIZE);
429 return ntlmssp_check_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx,
430 out->data, out->length,
431 out->data, out->length,
432 &sig);
433 } else {
434 *out = *in;
435 return NT_STATUS_OK;
439 static NTSTATUS gensec_ntlmssp_session_key(struct gensec_security *gensec_security,
440 DATA_BLOB *session_key)
442 struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
444 return ntlmssp_session_key(gensec_ntlmssp_state->ntlmssp_state, session_key);
448 * Next state function for the wrapped NTLMSSP state machine
450 * @param gensec_security GENSEC state, initialised to NTLMSSP
451 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
452 * @param in The request, as a DATA_BLOB
453 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
454 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
455 * or NT_STATUS_OK if the user is authenticated.
458 static NTSTATUS gensec_ntlmssp_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx,
459 const DATA_BLOB in, DATA_BLOB *out)
461 struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
462 NTSTATUS status;
464 status = ntlmssp_update(gensec_ntlmssp_state->ntlmssp_state, out_mem_ctx, in, out);
466 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
467 return status;
470 gensec_ntlmssp_state->have_features = 0;
472 if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) {
473 gensec_ntlmssp_state->have_features |= GENSEC_FEATURE_SIGN;
476 if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
477 gensec_ntlmssp_state->have_features |= GENSEC_FEATURE_SEAL;
480 if (gensec_ntlmssp_state->ntlmssp_state->session_key.data) {
481 gensec_ntlmssp_state->have_features |= GENSEC_FEATURE_SESSION_KEY;
484 return status;
487 /**
488 * Return the credentials of a logged on user, including session keys
489 * etc.
491 * Only valid after a successful authentication
493 * May only be called once per authentication.
497 static NTSTATUS gensec_ntlmssp_session_info(struct gensec_security *gensec_security,
498 struct auth_session_info **session_info)
500 NTSTATUS nt_status;
501 struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
502 nt_status = make_session_info(gensec_ntlmssp_state, gensec_ntlmssp_state->server_info, session_info);
504 if (!NT_STATUS_IS_OK(nt_status)) {
505 return nt_status;
508 (*session_info)->session_key = data_blob_talloc(*session_info,
509 gensec_ntlmssp_state->ntlmssp_state->session_key.data,
510 gensec_ntlmssp_state->ntlmssp_state->session_key.length);
512 (*session_info)->workstation = talloc_strdup(*session_info,
513 gensec_ntlmssp_state->ntlmssp_state->workstation);
515 return NT_STATUS_OK;
518 static BOOL gensec_ntlmssp_have_feature(struct gensec_security *gensec_security,
519 uint32 feature)
521 struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
522 if (gensec_ntlmssp_state->have_features & feature) {
523 return True;
526 return False;
529 static const struct gensec_security_ops gensec_ntlmssp_security_ops = {
530 .name = "ntlmssp",
531 .sasl_name = "NTLM",
532 .auth_type = DCERPC_AUTH_TYPE_NTLMSSP,
533 .oid = GENSEC_OID_NTLMSSP,
534 .client_start = gensec_ntlmssp_client_start,
535 .server_start = gensec_ntlmssp_server_start,
536 .update = gensec_ntlmssp_update,
537 .seal_packet = gensec_ntlmssp_seal_packet,
538 .sig_size = gensec_ntlmssp_sig_size,
539 .sign_packet = gensec_ntlmssp_sign_packet,
540 .check_packet = gensec_ntlmssp_check_packet,
541 .unseal_packet = gensec_ntlmssp_unseal_packet,
542 .wrap = gensec_ntlmssp_wrap,
543 .unwrap = gensec_ntlmssp_unwrap,
544 .session_key = gensec_ntlmssp_session_key,
545 .session_info = gensec_ntlmssp_session_info,
546 .have_feature = gensec_ntlmssp_have_feature,
547 .enabled = True
551 NTSTATUS gensec_ntlmssp_init(void)
553 NTSTATUS ret;
554 ret = gensec_register(&gensec_ntlmssp_security_ops);
555 if (!NT_STATUS_IS_OK(ret)) {
556 DEBUG(0,("Failed to register '%s' gensec backend!\n",
557 gensec_ntlmssp_security_ops.name));
558 return ret;
561 return ret;