r2645: converted the NTLMSSP code to the new style of talloc
[samba.git] / source4 / libcli / auth / gensec_ntlmssp.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    dcerpc authentication operations
5
6    Copyright (C) Andrew Tridgell 2003
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
8    
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.
13    
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.
18    
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.
22 */
23
24 #include "includes.h"
25
26 struct gensec_ntlmssp_state {
27         struct auth_context *auth_context;
28         struct auth_serversupplied_info *server_info;
29         struct ntlmssp_state *ntlmssp_state;
30 };
31
32
33 /**
34  * Return the challenge as determined by the authentication subsystem 
35  * @return an 8 byte random challenge
36  */
37
38 static const uint8_t *auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_state)
39 {
40         struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
41
42         return gensec_ntlmssp_state->auth_context->get_ntlm_challenge(gensec_ntlmssp_state->auth_context);
43 }
44
45 /**
46  * Some authentication methods 'fix' the challenge, so we may not be able to set it
47  *
48  * @return If the effective challenge used by the auth subsystem may be modified
49  */
50 static BOOL auth_ntlmssp_may_set_challenge(const struct ntlmssp_state *ntlmssp_state)
51 {
52         struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
53
54         return gensec_ntlmssp_state->auth_context->challenge_may_be_modified;
55 }
56
57 /**
58  * NTLM2 authentication modifies the effective challenge, 
59  * @param challenge The new challenge value
60  */
61 static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge)
62 {
63         struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
64         struct auth_context *auth_context = gensec_ntlmssp_state->auth_context;
65
66         SMB_ASSERT(challenge->length == 8);
67
68         auth_context->challenge = data_blob_talloc(auth_context->mem_ctx, 
69                                                    challenge->data, challenge->length);
70
71         auth_context->challenge_set_by = "NTLMSSP callback (NTLM2)";
72
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);
76         return NT_STATUS_OK;
77 }
78
79 /**
80  * Check the password on an NTLMSSP login.  
81  *
82  * Return the session keys used on the connection.
83  */
84
85 static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key) 
86 {
87         struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
88         struct auth_usersupplied_info *user_info = NULL;
89         NTSTATUS nt_status;
90
91 #if 0
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 */
94
95         set_remote_machine_name(gensec_ntlmssp_state->ntlmssp_state->workstation, True);
96
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);
100
101         reload_services(True);
102
103 #endif
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, 
110                                        NULL, NULL, NULL,
111                                        True);
112
113         if (!NT_STATUS_IS_OK(nt_status)) {
114                 return nt_status;
115         }
116
117         nt_status = gensec_ntlmssp_state->auth_context->check_ntlm_password(gensec_ntlmssp_state->auth_context, 
118                                                                           user_info, &gensec_ntlmssp_state->server_info); 
119
120         free_user_info(&user_info);
121
122         if (!NT_STATUS_IS_OK(nt_status)) {
123                 return nt_status;
124         }
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);
130         }
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);
136         }
137         return nt_status;
138 }
139
140 static NTSTATUS gensec_ntlmssp_start(struct gensec_security *gensec_security)
141 {
142         struct gensec_ntlmssp_state *gensec_ntlmssp_state;
143         
144         gensec_ntlmssp_state = talloc_p(gensec_security, struct gensec_ntlmssp_state);
145         if (!gensec_ntlmssp_state) {
146                 return NT_STATUS_NO_MEMORY;
147         }
148
149         gensec_ntlmssp_state->ntlmssp_state = NULL;
150         gensec_ntlmssp_state->auth_context = NULL;
151         gensec_ntlmssp_state->server_info = NULL;
152
153         gensec_security->private_data = gensec_ntlmssp_state;
154         return NT_STATUS_OK;
155 }
156
157 static NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security)
158 {
159         NTSTATUS nt_status;
160         NTSTATUS status;
161         struct ntlmssp_state *ntlmssp_state;
162         struct gensec_ntlmssp_state *gensec_ntlmssp_state;
163
164         status = gensec_ntlmssp_start(gensec_security);
165         if (!NT_STATUS_IS_OK(status)) {
166                 return status;
167         }
168
169         gensec_ntlmssp_state = gensec_security->private_data;
170
171         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_server_start(gensec_security,
172                                                               &gensec_ntlmssp_state->ntlmssp_state))) {
173                 return nt_status;
174         }
175
176         if (gensec_security->want_features & GENSEC_WANT_SIGN) {
177                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
178         }
179         if (gensec_security->want_features & GENSEC_WANT_SEAL) {
180                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
181         }
182
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 */
186
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;
189         }
190
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))) {
193                 return nt_status;
194         }
195
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();
202         
203         return NT_STATUS_OK;
204 }
205
206 static NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
207 {
208         struct gensec_ntlmssp_state *gensec_ntlmssp_state;
209         char *password = NULL;
210         
211         NTSTATUS status;
212         status = gensec_ntlmssp_start(gensec_security);
213         if (!NT_STATUS_IS_OK(status)) {
214                 return status;
215         }
216
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)) {
221                 return status;
222         }
223
224         if (gensec_security->want_features & GENSEC_WANT_SESSION_KEY) {
225                 /*
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.
229                  * 
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) 
233                  */
234                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
235         }
236         if (gensec_security->want_features & GENSEC_WANT_SIGN) {
237                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
238         }
239         if (gensec_security->want_features & GENSEC_WANT_SEAL) {
240                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
241         }
242
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 */
246
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;
249         }
250
251         status = ntlmssp_set_domain(gensec_ntlmssp_state->ntlmssp_state, 
252                                     gensec_security->user.domain);
253         if (!NT_STATUS_IS_OK(status)) {
254                 return status;
255         }
256         
257         status = ntlmssp_set_username(gensec_ntlmssp_state->ntlmssp_state, 
258                                       gensec_security->user.name);
259         if (!NT_STATUS_IS_OK(status)) {
260                 return status;
261         }
262
263         status = gensec_get_password(gensec_security, gensec_ntlmssp_state, &password);
264         if (!NT_STATUS_IS_OK(status)) {
265                 return status;
266         }
267
268         if (password) {
269                 status = ntlmssp_set_password(gensec_ntlmssp_state->ntlmssp_state, 
270                                               password);
271                 if (!NT_STATUS_IS_OK(status)) {
272                         return status;
273                 }
274         }
275
276         gensec_security->private_data = gensec_ntlmssp_state;
277
278         return status;
279 }
280
281 /*
282   wrappers for the ntlmssp_*() functions
283 */
284 static NTSTATUS gensec_ntlmssp_unseal_packet(struct gensec_security *gensec_security, 
285                                              TALLOC_CTX *mem_ctx, 
286                                              uint8_t *data, size_t length, 
287                                              const uint8_t *whole_pdu, size_t pdu_length, 
288                                              DATA_BLOB *sig)
289 {
290         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
291
292         return ntlmssp_unseal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
293 }
294
295 static NTSTATUS gensec_ntlmssp_check_packet(struct gensec_security *gensec_security, 
296                                             TALLOC_CTX *mem_ctx, 
297                                             const uint8_t *data, size_t length, 
298                                             const uint8_t *whole_pdu, size_t pdu_length, 
299                                             const DATA_BLOB *sig)
300 {
301         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
302
303         return ntlmssp_check_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
304 }
305
306 static NTSTATUS gensec_ntlmssp_seal_packet(struct gensec_security *gensec_security, 
307                                            TALLOC_CTX *mem_ctx, 
308                                            uint8_t *data, size_t length, 
309                                            const uint8_t *whole_pdu, size_t pdu_length, 
310                                            DATA_BLOB *sig)
311 {
312         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
313
314         return ntlmssp_seal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
315 }
316
317 static NTSTATUS gensec_ntlmssp_sign_packet(struct gensec_security *gensec_security, 
318                                            TALLOC_CTX *mem_ctx, 
319                                            const uint8_t *data, size_t length, 
320                                            const uint8_t *whole_pdu, size_t pdu_length, 
321                                            DATA_BLOB *sig)
322 {
323         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
324
325         return ntlmssp_sign_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
326 }
327
328 static size_t gensec_ntlmssp_sig_size(struct gensec_security *gensec_security) 
329 {
330         return NTLMSSP_SIG_SIZE;
331 }
332
333 static NTSTATUS gensec_ntlmssp_session_key(struct gensec_security *gensec_security, 
334                                            DATA_BLOB *session_key)
335 {
336         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
337
338         return ntlmssp_session_key(gensec_ntlmssp_state->ntlmssp_state, session_key);
339 }
340
341 /**
342  * Next state function for the wrapped NTLMSSP state machine
343  * 
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. 
350  */
351
352 static NTSTATUS gensec_ntlmssp_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, 
353                                       const DATA_BLOB in, DATA_BLOB *out) 
354 {
355         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
356
357         return ntlmssp_update(gensec_ntlmssp_state->ntlmssp_state, out_mem_ctx, in, out);
358 }
359
360 /** 
361  * Return the credentials of a logged on user, including session keys
362  * etc.
363  *
364  * Only valid after a successful authentication
365  *
366  * May only be called once per authentication.
367  *
368  */
369
370 static NTSTATUS gensec_ntlmssp_session_info(struct gensec_security *gensec_security,
371                                      struct auth_session_info **session_info) 
372 {
373         NTSTATUS nt_status;
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);
376
377         if (!NT_STATUS_IS_OK(nt_status)) {
378                 return nt_status;
379         }
380
381         /* the session_info owns this now */
382         gensec_ntlmssp_state->server_info = NULL;
383
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);
387
388         (*session_info)->workstation = talloc_strdup(*session_info, 
389                                                      gensec_ntlmssp_state->ntlmssp_state->workstation);
390
391         return NT_STATUS_OK;
392 }
393
394 static void gensec_ntlmssp_end(struct gensec_security *gensec_security)
395 {
396         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
397
398         if (gensec_ntlmssp_state->ntlmssp_state) {
399                 ntlmssp_end(&gensec_ntlmssp_state->ntlmssp_state);
400         }
401
402         if (gensec_ntlmssp_state->auth_context) {
403                 free_auth_context(&gensec_ntlmssp_state->auth_context);
404         }
405         if (gensec_ntlmssp_state->server_info) {
406                 free_server_info(&gensec_ntlmssp_state->server_info);
407         }
408         talloc_free(gensec_ntlmssp_state);
409         gensec_security->private_data = NULL;
410 }
411
412 static const struct gensec_security_ops gensec_ntlmssp_security_ops = {
413         .name           = "ntlmssp",
414         .sasl_name      = "NTLM",
415         .auth_type      = DCERPC_AUTH_TYPE_NTLMSSP,
416         .oid            = OID_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
428 };
429
430
431 NTSTATUS gensec_ntlmssp_init(void)
432 {
433         NTSTATUS ret;
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));
438                 return ret;
439         }
440
441         /* ugly cludge, but we need the auth subsystem for this to work */
442         auth_init();
443
444         return ret;
445 }