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.
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;
35 * Return the challenge as determined by the authentication subsystem
36 * @return an 8 byte random challenge
39 static const uint8_t *auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_state)
41 struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
43 return gensec_ntlmssp_state->auth_context->get_ntlm_challenge(gensec_ntlmssp_state->auth_context);
47 * Some authentication methods 'fix' the challenge, so we may not be able to set it
49 * @return If the effective challenge used by the auth subsystem may be modified
51 static BOOL auth_ntlmssp_may_set_challenge(const struct ntlmssp_state *ntlmssp_state)
53 struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
55 return gensec_ntlmssp_state->auth_context->challenge_may_be_modified;
59 * NTLM2 authentication modifies the effective challenge,
60 * @param challenge The new challenge value
62 static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge)
64 struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
65 struct auth_context *auth_context = gensec_ntlmssp_state->auth_context;
67 SMB_ASSERT(challenge->length == 8);
69 auth_context->challenge = data_blob_talloc(auth_context,
70 challenge->data, challenge->length);
72 auth_context->challenge_set_by = "NTLMSSP callback (NTLM2)";
74 DEBUG(5, ("auth_context challenge set by %s\n", auth_context->challenge_set_by));
75 DEBUG(5, ("challenge is: \n"));
76 dump_data(5, auth_context->challenge.data, auth_context->challenge.length);
81 * Check the password on an NTLMSSP login.
83 * Return the session keys used on the connection.
86 static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key)
88 struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
89 struct auth_usersupplied_info *user_info = NULL;
93 /* the client has given us its machine name (which we otherwise would not get on port 445).
94 we need to possibly reload smb.conf if smb.conf includes depend on the machine name */
96 set_remote_machine_name(gensec_ntlmssp_state->ntlmssp_state->workstation, True);
98 /* setup the string used by %U */
99 /* sub_set_smb_name checks for weird internally */
100 sub_set_smb_name(gensec_ntlmssp_state->ntlmssp_state->user);
102 reload_services(True);
105 nt_status = make_user_info_map(ntlmssp_state,
107 gensec_ntlmssp_state->ntlmssp_state->user,
108 gensec_ntlmssp_state->ntlmssp_state->domain,
109 gensec_ntlmssp_state->ntlmssp_state->workstation,
110 gensec_ntlmssp_state->ntlmssp_state->lm_resp.data ? &gensec_ntlmssp_state->ntlmssp_state->lm_resp : NULL,
111 gensec_ntlmssp_state->ntlmssp_state->nt_resp.data ? &gensec_ntlmssp_state->ntlmssp_state->nt_resp : NULL,
115 if (!NT_STATUS_IS_OK(nt_status)) {
119 nt_status = gensec_ntlmssp_state->
120 auth_context->check_ntlm_password(gensec_ntlmssp_state->auth_context,
122 gensec_ntlmssp_state,
123 &gensec_ntlmssp_state->server_info);
125 free_user_info(&user_info);
127 if (!NT_STATUS_IS_OK(nt_status)) {
130 if (gensec_ntlmssp_state->server_info->user_session_key.length) {
131 DEBUG(10, ("Got NT session key of length %u\n", gensec_ntlmssp_state->server_info->user_session_key.length));
132 *user_session_key = data_blob_talloc(ntlmssp_state,
133 gensec_ntlmssp_state->server_info->user_session_key.data,
134 gensec_ntlmssp_state->server_info->user_session_key.length);
136 if (gensec_ntlmssp_state->server_info->lm_session_key.length) {
137 DEBUG(10, ("Got LM session key of length %u\n", gensec_ntlmssp_state->server_info->lm_session_key.length));
138 *lm_session_key = data_blob_talloc(ntlmssp_state,
139 gensec_ntlmssp_state->server_info->lm_session_key.data,
140 gensec_ntlmssp_state->server_info->lm_session_key.length);
145 static int gensec_ntlmssp_destroy(void *ptr)
147 struct gensec_ntlmssp_state *gensec_ntlmssp_state = ptr;
149 if (gensec_ntlmssp_state->ntlmssp_state) {
150 ntlmssp_end(&gensec_ntlmssp_state->ntlmssp_state);
153 if (gensec_ntlmssp_state->auth_context) {
154 free_auth_context(&gensec_ntlmssp_state->auth_context);
156 if (gensec_ntlmssp_state->server_info) {
157 free_server_info(&gensec_ntlmssp_state->server_info);
162 static NTSTATUS gensec_ntlmssp_start(struct gensec_security *gensec_security)
164 struct gensec_ntlmssp_state *gensec_ntlmssp_state;
166 gensec_ntlmssp_state = talloc_p(gensec_security, struct gensec_ntlmssp_state);
167 if (!gensec_ntlmssp_state) {
168 return NT_STATUS_NO_MEMORY;
171 gensec_ntlmssp_state->ntlmssp_state = NULL;
172 gensec_ntlmssp_state->auth_context = NULL;
173 gensec_ntlmssp_state->server_info = NULL;
175 talloc_set_destructor(gensec_ntlmssp_state, gensec_ntlmssp_destroy);
177 gensec_security->private_data = gensec_ntlmssp_state;
181 static NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security)
185 struct ntlmssp_state *ntlmssp_state;
186 struct gensec_ntlmssp_state *gensec_ntlmssp_state;
188 status = gensec_ntlmssp_start(gensec_security);
189 if (!NT_STATUS_IS_OK(status)) {
193 gensec_ntlmssp_state = gensec_security->private_data;
195 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_server_start(gensec_ntlmssp_state,
196 &gensec_ntlmssp_state->ntlmssp_state))) {
200 if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
201 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
203 if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
204 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
207 ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state;
208 nt_status = make_auth_context_subsystem(gensec_ntlmssp_state, &gensec_ntlmssp_state->auth_context);
209 if (!NT_STATUS_IS_OK(nt_status)) {
213 ntlmssp_state->auth_context = gensec_ntlmssp_state;
214 ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge;
215 ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge;
216 ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge;
217 ntlmssp_state->check_password = auth_ntlmssp_check_password;
218 ntlmssp_state->server_role = lp_server_role();
223 static NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
225 struct gensec_ntlmssp_state *gensec_ntlmssp_state;
226 char *password = NULL;
229 status = gensec_ntlmssp_start(gensec_security);
230 if (!NT_STATUS_IS_OK(status)) {
234 gensec_ntlmssp_state = gensec_security->private_data;
235 status = ntlmssp_client_start(gensec_ntlmssp_state,
236 &gensec_ntlmssp_state->ntlmssp_state);
237 if (!NT_STATUS_IS_OK(status)) {
241 if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
243 * We need to set this to allow a later SetPassword
244 * via the SAMR pipe to succeed. Strange.... We could
245 * also add NTLMSSP_NEGOTIATE_SEAL here. JRA.
247 * Without this, Windows will not create the master key
248 * that it thinks is only used for NTLMSSP signing and
249 * sealing. (It is actually pulled out and used directly)
251 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
253 if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
254 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
256 if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
257 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
260 status = ntlmssp_set_domain(gensec_ntlmssp_state->ntlmssp_state,
261 gensec_security->user.domain);
262 if (!NT_STATUS_IS_OK(status)) {
266 status = ntlmssp_set_username(gensec_ntlmssp_state->ntlmssp_state,
267 gensec_security->user.name);
268 if (!NT_STATUS_IS_OK(status)) {
272 if (gensec_security->user.name) {
273 status = gensec_get_password(gensec_security, gensec_ntlmssp_state, &password);
274 if (!NT_STATUS_IS_OK(status)) {
280 status = ntlmssp_set_password(gensec_ntlmssp_state->ntlmssp_state,
282 if (!NT_STATUS_IS_OK(status)) {
287 gensec_security->private_data = gensec_ntlmssp_state;
293 wrappers for the ntlmssp_*() functions
295 static NTSTATUS gensec_ntlmssp_unseal_packet(struct gensec_security *gensec_security,
297 uint8_t *data, size_t length,
298 const uint8_t *whole_pdu, size_t pdu_length,
301 struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
303 return ntlmssp_unseal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
306 static NTSTATUS gensec_ntlmssp_check_packet(struct gensec_security *gensec_security,
308 const uint8_t *data, size_t length,
309 const uint8_t *whole_pdu, size_t pdu_length,
310 const DATA_BLOB *sig)
312 struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
314 return ntlmssp_check_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
317 static NTSTATUS gensec_ntlmssp_seal_packet(struct gensec_security *gensec_security,
319 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_seal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
328 static NTSTATUS gensec_ntlmssp_sign_packet(struct gensec_security *gensec_security,
330 const uint8_t *data, size_t length,
331 const uint8_t *whole_pdu, size_t pdu_length,
334 struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
336 return ntlmssp_sign_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
339 static size_t gensec_ntlmssp_sig_size(struct gensec_security *gensec_security)
341 return NTLMSSP_SIG_SIZE;
344 static NTSTATUS gensec_ntlmssp_session_key(struct gensec_security *gensec_security,
345 DATA_BLOB *session_key)
347 struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
349 return ntlmssp_session_key(gensec_ntlmssp_state->ntlmssp_state, session_key);
353 * Next state function for the wrapped NTLMSSP state machine
355 * @param gensec_security GENSEC state, initialised to NTLMSSP
356 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
357 * @param in The request, as a DATA_BLOB
358 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
359 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
360 * or NT_STATUS_OK if the user is authenticated.
363 static NTSTATUS gensec_ntlmssp_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx,
364 const DATA_BLOB in, DATA_BLOB *out)
366 struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
369 status = ntlmssp_update(gensec_ntlmssp_state->ntlmssp_state, out_mem_ctx, in, out);
371 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
375 if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) {
376 gensec_security->have_features |= GENSEC_FEATURE_SIGN;
379 if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
380 gensec_security->have_features |= GENSEC_FEATURE_SEAL;
383 if (gensec_ntlmssp_state->ntlmssp_state->session_key.data) {
384 gensec_security->have_features |= GENSEC_FEATURE_SESSION_KEY;
391 * Return the credentials of a logged on user, including session keys
394 * Only valid after a successful authentication
396 * May only be called once per authentication.
400 static NTSTATUS gensec_ntlmssp_session_info(struct gensec_security *gensec_security,
401 struct auth_session_info **session_info)
404 struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
405 nt_status = make_session_info(gensec_ntlmssp_state, gensec_ntlmssp_state->server_info, session_info);
407 if (!NT_STATUS_IS_OK(nt_status)) {
411 (*session_info)->session_key = data_blob_talloc(*session_info,
412 gensec_ntlmssp_state->ntlmssp_state->session_key.data,
413 gensec_ntlmssp_state->ntlmssp_state->session_key.length);
415 (*session_info)->workstation = talloc_strdup(*session_info,
416 gensec_ntlmssp_state->ntlmssp_state->workstation);
421 static const struct gensec_security_ops gensec_ntlmssp_security_ops = {
424 .auth_type = DCERPC_AUTH_TYPE_NTLMSSP,
425 .oid = GENSEC_OID_NTLMSSP,
426 .client_start = gensec_ntlmssp_client_start,
427 .server_start = gensec_ntlmssp_server_start,
428 .update = gensec_ntlmssp_update,
429 .seal_packet = gensec_ntlmssp_seal_packet,
430 .sig_size = gensec_ntlmssp_sig_size,
431 .sign_packet = gensec_ntlmssp_sign_packet,
432 .check_packet = gensec_ntlmssp_check_packet,
433 .unseal_packet = gensec_ntlmssp_unseal_packet,
434 .session_key = gensec_ntlmssp_session_key,
435 .session_info = gensec_ntlmssp_session_info,
439 NTSTATUS gensec_ntlmssp_init(void)
442 ret = gensec_register(&gensec_ntlmssp_security_ops);
443 if (!NT_STATUS_IS_OK(ret)) {
444 DEBUG(0,("Failed to register '%s' gensec backend!\n",
445 gensec_ntlmssp_security_ops.name));