r3959: fix compiler warnings
[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 #include "auth/auth.h"
26 #include "asn_1.h"
27
28 struct gensec_ntlmssp_state {
29         struct auth_context *auth_context;
30         struct auth_serversupplied_info *server_info;
31         struct ntlmssp_state *ntlmssp_state;
32 };
33
34
35 /**
36  * Return the challenge as determined by the authentication subsystem 
37  * @return an 8 byte random challenge
38  */
39
40 static const uint8_t *auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_state)
41 {
42         struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
43
44         return gensec_ntlmssp_state->auth_context->get_ntlm_challenge(gensec_ntlmssp_state->auth_context);
45 }
46
47 /**
48  * Some authentication methods 'fix' the challenge, so we may not be able to set it
49  *
50  * @return If the effective challenge used by the auth subsystem may be modified
51  */
52 static BOOL auth_ntlmssp_may_set_challenge(const struct ntlmssp_state *ntlmssp_state)
53 {
54         struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
55
56         return gensec_ntlmssp_state->auth_context->challenge_may_be_modified;
57 }
58
59 /**
60  * NTLM2 authentication modifies the effective challenge, 
61  * @param challenge The new challenge value
62  */
63 static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge)
64 {
65         struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
66         struct auth_context *auth_context = gensec_ntlmssp_state->auth_context;
67
68         SMB_ASSERT(challenge->length == 8);
69
70         auth_context->challenge = data_blob_talloc(auth_context, 
71                                                    challenge->data, challenge->length);
72
73         auth_context->challenge_set_by = "NTLMSSP callback (NTLM2)";
74
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;
79 }
80
81 /**
82  * Check the password on an NTLMSSP login.  
83  *
84  * Return the session keys used on the connection.
85  */
86
87 static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key) 
88 {
89         struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
90         struct auth_usersupplied_info *user_info = NULL;
91         NTSTATUS nt_status;
92
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 */
96
97         set_remote_machine_name(gensec_ntlmssp_state->ntlmssp_state->workstation, True);
98
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);
102
103         reload_services(True);
104
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);
115
116         if (!NT_STATUS_IS_OK(nt_status)) {
117                 return nt_status;
118         }
119
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); 
125
126         free_user_info(&user_info);
127
128         if (!NT_STATUS_IS_OK(nt_status)) {
129                 return nt_status;
130         }
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);
136         }
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);
142         }
143         return nt_status;
144 }
145
146 static NTSTATUS gensec_ntlmssp_start(struct gensec_security *gensec_security)
147 {
148         struct gensec_ntlmssp_state *gensec_ntlmssp_state;
149         
150         gensec_ntlmssp_state = talloc_p(gensec_security, struct gensec_ntlmssp_state);
151         if (!gensec_ntlmssp_state) {
152                 return NT_STATUS_NO_MEMORY;
153         }
154
155         gensec_ntlmssp_state->ntlmssp_state = NULL;
156         gensec_ntlmssp_state->auth_context = NULL;
157         gensec_ntlmssp_state->server_info = NULL;
158
159         gensec_security->private_data = gensec_ntlmssp_state;
160         return NT_STATUS_OK;
161 }
162
163 static NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security)
164 {
165         NTSTATUS nt_status;
166         NTSTATUS status;
167         struct ntlmssp_state *ntlmssp_state;
168         struct gensec_ntlmssp_state *gensec_ntlmssp_state;
169
170         status = gensec_ntlmssp_start(gensec_security);
171         if (!NT_STATUS_IS_OK(status)) {
172                 return status;
173         }
174
175         gensec_ntlmssp_state = gensec_security->private_data;
176
177         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_server_start(gensec_security,
178                                                               &gensec_ntlmssp_state->ntlmssp_state))) {
179                 return nt_status;
180         }
181
182         if (gensec_security->want_features & GENSEC_WANT_SIGN) {
183                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
184         }
185         if (gensec_security->want_features & GENSEC_WANT_SEAL) {
186                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
187         }
188
189         ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state;
190         nt_status = make_auth_context_subsystem(gensec_security, &gensec_ntlmssp_state->auth_context);
191         if (!NT_STATUS_IS_OK(nt_status)) {
192                 return nt_status;
193         }
194
195         ntlmssp_state->auth_context = gensec_ntlmssp_state;
196         ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge;
197         ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge;
198         ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge;
199         ntlmssp_state->check_password = auth_ntlmssp_check_password;
200         ntlmssp_state->server_role = lp_server_role();
201         
202         return NT_STATUS_OK;
203 }
204
205 static NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
206 {
207         struct gensec_ntlmssp_state *gensec_ntlmssp_state;
208         char *password = NULL;
209         
210         NTSTATUS status;
211         status = gensec_ntlmssp_start(gensec_security);
212         if (!NT_STATUS_IS_OK(status)) {
213                 return status;
214         }
215
216         gensec_ntlmssp_state = gensec_security->private_data;
217         status = ntlmssp_client_start(gensec_security, 
218                                       &gensec_ntlmssp_state->ntlmssp_state);
219         if (!NT_STATUS_IS_OK(status)) {
220                 return status;
221         }
222
223         if (gensec_security->want_features & GENSEC_WANT_SESSION_KEY) {
224                 /*
225                  * We need to set this to allow a later SetPassword
226                  * via the SAMR pipe to succeed. Strange.... We could
227                  * also add  NTLMSSP_NEGOTIATE_SEAL here. JRA.
228                  * 
229                  * Without this, Windows will not create the master key
230                  * that it thinks is only used for NTLMSSP signing and 
231                  * sealing.  (It is actually pulled out and used directly) 
232                  */
233                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
234         }
235         if (gensec_security->want_features & GENSEC_WANT_SIGN) {
236                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
237         }
238         if (gensec_security->want_features & GENSEC_WANT_SEAL) {
239                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
240         }
241
242         status = ntlmssp_set_domain(gensec_ntlmssp_state->ntlmssp_state, 
243                                     gensec_security->user.domain);
244         if (!NT_STATUS_IS_OK(status)) {
245                 return status;
246         }
247         
248         status = ntlmssp_set_username(gensec_ntlmssp_state->ntlmssp_state, 
249                                       gensec_security->user.name);
250         if (!NT_STATUS_IS_OK(status)) {
251                 return status;
252         }
253
254         status = gensec_get_password(gensec_security, gensec_ntlmssp_state, &password);
255         if (!NT_STATUS_IS_OK(status)) {
256                 return status;
257         }
258
259         if (password) {
260                 status = ntlmssp_set_password(gensec_ntlmssp_state->ntlmssp_state, 
261                                               password);
262                 if (!NT_STATUS_IS_OK(status)) {
263                         return status;
264                 }
265         }
266
267         gensec_security->private_data = gensec_ntlmssp_state;
268
269         return status;
270 }
271
272 /*
273   wrappers for the ntlmssp_*() functions
274 */
275 static NTSTATUS gensec_ntlmssp_unseal_packet(struct gensec_security *gensec_security, 
276                                              TALLOC_CTX *mem_ctx, 
277                                              uint8_t *data, size_t length, 
278                                              const uint8_t *whole_pdu, size_t pdu_length, 
279                                              DATA_BLOB *sig)
280 {
281         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
282
283         return ntlmssp_unseal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
284 }
285
286 static NTSTATUS gensec_ntlmssp_check_packet(struct gensec_security *gensec_security, 
287                                             TALLOC_CTX *mem_ctx, 
288                                             const uint8_t *data, size_t length, 
289                                             const uint8_t *whole_pdu, size_t pdu_length, 
290                                             const DATA_BLOB *sig)
291 {
292         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
293
294         return ntlmssp_check_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
295 }
296
297 static NTSTATUS gensec_ntlmssp_seal_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)
302 {
303         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
304
305         return ntlmssp_seal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
306 }
307
308 static NTSTATUS gensec_ntlmssp_sign_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                                            DATA_BLOB *sig)
313 {
314         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
315
316         return ntlmssp_sign_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
317 }
318
319 static size_t gensec_ntlmssp_sig_size(struct gensec_security *gensec_security) 
320 {
321         return NTLMSSP_SIG_SIZE;
322 }
323
324 static NTSTATUS gensec_ntlmssp_session_key(struct gensec_security *gensec_security, 
325                                            DATA_BLOB *session_key)
326 {
327         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
328
329         return ntlmssp_session_key(gensec_ntlmssp_state->ntlmssp_state, session_key);
330 }
331
332 /**
333  * Next state function for the wrapped NTLMSSP state machine
334  * 
335  * @param gensec_security GENSEC state, initialised to NTLMSSP
336  * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
337  * @param in The request, as a DATA_BLOB
338  * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
339  * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent, 
340  *                or NT_STATUS_OK if the user is authenticated. 
341  */
342
343 static NTSTATUS gensec_ntlmssp_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, 
344                                       const DATA_BLOB in, DATA_BLOB *out) 
345 {
346         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
347
348         return ntlmssp_update(gensec_ntlmssp_state->ntlmssp_state, out_mem_ctx, in, out);
349 }
350
351 /** 
352  * Return the credentials of a logged on user, including session keys
353  * etc.
354  *
355  * Only valid after a successful authentication
356  *
357  * May only be called once per authentication.
358  *
359  */
360
361 static NTSTATUS gensec_ntlmssp_session_info(struct gensec_security *gensec_security,
362                                             struct auth_session_info **session_info) 
363 {
364         NTSTATUS nt_status;
365         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
366         nt_status = make_session_info(gensec_ntlmssp_state, gensec_ntlmssp_state->server_info, session_info);
367
368         if (!NT_STATUS_IS_OK(nt_status)) {
369                 return nt_status;
370         }
371
372         (*session_info)->session_key = data_blob_talloc(*session_info, 
373                                                         gensec_ntlmssp_state->ntlmssp_state->session_key.data,
374                                                         gensec_ntlmssp_state->ntlmssp_state->session_key.length);
375
376         (*session_info)->workstation = talloc_strdup(*session_info, 
377                                                      gensec_ntlmssp_state->ntlmssp_state->workstation);
378
379         return NT_STATUS_OK;
380 }
381
382 static void gensec_ntlmssp_end(struct gensec_security *gensec_security)
383 {
384         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
385
386         if (gensec_ntlmssp_state->ntlmssp_state) {
387                 ntlmssp_end(&gensec_ntlmssp_state->ntlmssp_state);
388         }
389
390         if (gensec_ntlmssp_state->auth_context) {
391                 free_auth_context(&gensec_ntlmssp_state->auth_context);
392         }
393         if (gensec_ntlmssp_state->server_info) {
394                 free_server_info(&gensec_ntlmssp_state->server_info);
395         }
396         talloc_free(gensec_ntlmssp_state);
397         gensec_security->private_data = NULL;
398 }
399
400 static const struct gensec_security_ops gensec_ntlmssp_security_ops = {
401         .name           = "ntlmssp",
402         .sasl_name      = "NTLM",
403         .auth_type      = DCERPC_AUTH_TYPE_NTLMSSP,
404         .oid            = OID_NTLMSSP,
405         .client_start   = gensec_ntlmssp_client_start,
406         .server_start   = gensec_ntlmssp_server_start,
407         .update         = gensec_ntlmssp_update,
408         .seal_packet    = gensec_ntlmssp_seal_packet,
409         .sig_size       = gensec_ntlmssp_sig_size,
410         .sign_packet    = gensec_ntlmssp_sign_packet,
411         .check_packet   = gensec_ntlmssp_check_packet,
412         .unseal_packet  = gensec_ntlmssp_unseal_packet,
413         .session_key    = gensec_ntlmssp_session_key,
414         .session_info   = gensec_ntlmssp_session_info,
415         .end            = gensec_ntlmssp_end
416 };
417
418
419 NTSTATUS gensec_ntlmssp_init(void)
420 {
421         NTSTATUS ret;
422         ret = gensec_register(&gensec_ntlmssp_security_ops);
423         if (!NT_STATUS_IS_OK(ret)) {
424                 DEBUG(0,("Failed to register '%s' gensec backend!\n",
425                         gensec_ntlmssp_security_ops.name));
426                 return ret;
427         }
428
429         return ret;
430 }