r3630: More work on DCOM server side
[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, (const char *)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         /* IF we are not doing Signing or Sealing, we can actually do
190          * NTLM2.  When we crack the crypto puzzle, then we can enable
191          * this always, in the constant flags */
192
193         if (!(gensec_security->want_features & GENSEC_WANT_SIGN) && !(gensec_security->want_features & GENSEC_WANT_SEAL)) {
194                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;
195         }
196
197         ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state;
198         nt_status = make_auth_context_subsystem(gensec_security, &gensec_ntlmssp_state->auth_context);
199         if (!NT_STATUS_IS_OK(nt_status)) {
200                 return nt_status;
201         }
202
203         ntlmssp_state->auth_context = gensec_ntlmssp_state;
204         ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge;
205         ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge;
206         ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge;
207         ntlmssp_state->check_password = auth_ntlmssp_check_password;
208         ntlmssp_state->server_role = lp_server_role();
209         
210         return NT_STATUS_OK;
211 }
212
213 static NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
214 {
215         struct gensec_ntlmssp_state *gensec_ntlmssp_state;
216         char *password = NULL;
217         
218         NTSTATUS status;
219         status = gensec_ntlmssp_start(gensec_security);
220         if (!NT_STATUS_IS_OK(status)) {
221                 return status;
222         }
223
224         gensec_ntlmssp_state = gensec_security->private_data;
225         status = ntlmssp_client_start(gensec_security, 
226                                       &gensec_ntlmssp_state->ntlmssp_state);
227         if (!NT_STATUS_IS_OK(status)) {
228                 return status;
229         }
230
231         if (gensec_security->want_features & GENSEC_WANT_SESSION_KEY) {
232                 /*
233                  * We need to set this to allow a later SetPassword
234                  * via the SAMR pipe to succeed. Strange.... We could
235                  * also add  NTLMSSP_NEGOTIATE_SEAL here. JRA.
236                  * 
237                  * Without this, Windows will not create the master key
238                  * that it thinks is only used for NTLMSSP signing and 
239                  * sealing.  (It is actually pulled out and used directly) 
240                  */
241                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
242         }
243         if (gensec_security->want_features & GENSEC_WANT_SIGN) {
244                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
245         }
246         if (gensec_security->want_features & GENSEC_WANT_SEAL) {
247                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
248         }
249
250         /* IF we are not doing Signing or Sealing, we can actually do
251          * NTLM2.  When we crack the crypto puzzle, then we can enable
252          * this always, in the constant flags */
253
254         if (!(gensec_security->want_features & GENSEC_WANT_SIGN) && !(gensec_security->want_features & GENSEC_WANT_SEAL)) {
255                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;
256         }
257
258         status = ntlmssp_set_domain(gensec_ntlmssp_state->ntlmssp_state, 
259                                     gensec_security->user.domain);
260         if (!NT_STATUS_IS_OK(status)) {
261                 return status;
262         }
263         
264         status = ntlmssp_set_username(gensec_ntlmssp_state->ntlmssp_state, 
265                                       gensec_security->user.name);
266         if (!NT_STATUS_IS_OK(status)) {
267                 return status;
268         }
269
270         status = gensec_get_password(gensec_security, gensec_ntlmssp_state, &password);
271         if (!NT_STATUS_IS_OK(status)) {
272                 return status;
273         }
274
275         if (password) {
276                 status = ntlmssp_set_password(gensec_ntlmssp_state->ntlmssp_state, 
277                                               password);
278                 if (!NT_STATUS_IS_OK(status)) {
279                         return status;
280                 }
281         }
282
283         gensec_security->private_data = gensec_ntlmssp_state;
284
285         return status;
286 }
287
288 /*
289   wrappers for the ntlmssp_*() functions
290 */
291 static NTSTATUS gensec_ntlmssp_unseal_packet(struct gensec_security *gensec_security, 
292                                              TALLOC_CTX *mem_ctx, 
293                                              uint8_t *data, size_t length, 
294                                              const uint8_t *whole_pdu, size_t pdu_length, 
295                                              DATA_BLOB *sig)
296 {
297         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
298
299         return ntlmssp_unseal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
300 }
301
302 static NTSTATUS gensec_ntlmssp_check_packet(struct gensec_security *gensec_security, 
303                                             TALLOC_CTX *mem_ctx, 
304                                             const uint8_t *data, size_t length, 
305                                             const uint8_t *whole_pdu, size_t pdu_length, 
306                                             const DATA_BLOB *sig)
307 {
308         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
309
310         return ntlmssp_check_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
311 }
312
313 static NTSTATUS gensec_ntlmssp_seal_packet(struct gensec_security *gensec_security, 
314                                            TALLOC_CTX *mem_ctx, 
315                                            uint8_t *data, size_t length, 
316                                            const uint8_t *whole_pdu, size_t pdu_length, 
317                                            DATA_BLOB *sig)
318 {
319         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
320
321         return ntlmssp_seal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
322 }
323
324 static NTSTATUS gensec_ntlmssp_sign_packet(struct gensec_security *gensec_security, 
325                                            TALLOC_CTX *mem_ctx, 
326                                            const uint8_t *data, size_t length, 
327                                            const uint8_t *whole_pdu, size_t pdu_length, 
328                                            DATA_BLOB *sig)
329 {
330         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
331
332         return ntlmssp_sign_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
333 }
334
335 static size_t gensec_ntlmssp_sig_size(struct gensec_security *gensec_security) 
336 {
337         return NTLMSSP_SIG_SIZE;
338 }
339
340 static NTSTATUS gensec_ntlmssp_session_key(struct gensec_security *gensec_security, 
341                                            DATA_BLOB *session_key)
342 {
343         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
344
345         return ntlmssp_session_key(gensec_ntlmssp_state->ntlmssp_state, session_key);
346 }
347
348 /**
349  * Next state function for the wrapped NTLMSSP state machine
350  * 
351  * @param gensec_security GENSEC state, initialised to NTLMSSP
352  * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
353  * @param in The request, as a DATA_BLOB
354  * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
355  * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent, 
356  *                or NT_STATUS_OK if the user is authenticated. 
357  */
358
359 static NTSTATUS gensec_ntlmssp_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, 
360                                       const DATA_BLOB in, DATA_BLOB *out) 
361 {
362         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
363
364         return ntlmssp_update(gensec_ntlmssp_state->ntlmssp_state, out_mem_ctx, in, out);
365 }
366
367 /** 
368  * Return the credentials of a logged on user, including session keys
369  * etc.
370  *
371  * Only valid after a successful authentication
372  *
373  * May only be called once per authentication.
374  *
375  */
376
377 static NTSTATUS gensec_ntlmssp_session_info(struct gensec_security *gensec_security,
378                                             struct auth_session_info **session_info) 
379 {
380         NTSTATUS nt_status;
381         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
382         nt_status = make_session_info(gensec_ntlmssp_state, gensec_ntlmssp_state->server_info, session_info);
383
384         if (!NT_STATUS_IS_OK(nt_status)) {
385                 return nt_status;
386         }
387
388         (*session_info)->session_key = data_blob_talloc(*session_info, 
389                                                         gensec_ntlmssp_state->ntlmssp_state->session_key.data,
390                                                         gensec_ntlmssp_state->ntlmssp_state->session_key.length);
391
392         (*session_info)->workstation = talloc_strdup(*session_info, 
393                                                      gensec_ntlmssp_state->ntlmssp_state->workstation);
394
395         return NT_STATUS_OK;
396 }
397
398 static void gensec_ntlmssp_end(struct gensec_security *gensec_security)
399 {
400         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
401
402         if (gensec_ntlmssp_state->ntlmssp_state) {
403                 ntlmssp_end(&gensec_ntlmssp_state->ntlmssp_state);
404         }
405
406         if (gensec_ntlmssp_state->auth_context) {
407                 free_auth_context(&gensec_ntlmssp_state->auth_context);
408         }
409         if (gensec_ntlmssp_state->server_info) {
410                 free_server_info(&gensec_ntlmssp_state->server_info);
411         }
412         talloc_free(gensec_ntlmssp_state);
413         gensec_security->private_data = NULL;
414 }
415
416 static const struct gensec_security_ops gensec_ntlmssp_security_ops = {
417         .name           = "ntlmssp",
418         .sasl_name      = "NTLM",
419         .auth_type      = DCERPC_AUTH_TYPE_NTLMSSP,
420         .oid            = OID_NTLMSSP,
421         .client_start   = gensec_ntlmssp_client_start,
422         .server_start   = gensec_ntlmssp_server_start,
423         .update         = gensec_ntlmssp_update,
424         .seal_packet    = gensec_ntlmssp_seal_packet,
425         .sig_size       = gensec_ntlmssp_sig_size,
426         .sign_packet    = gensec_ntlmssp_sign_packet,
427         .check_packet   = gensec_ntlmssp_check_packet,
428         .unseal_packet  = gensec_ntlmssp_unseal_packet,
429         .session_key    = gensec_ntlmssp_session_key,
430         .session_info   = gensec_ntlmssp_session_info,
431         .end            = gensec_ntlmssp_end
432 };
433
434
435 NTSTATUS gensec_ntlmssp_init(void)
436 {
437         NTSTATUS ret;
438         ret = register_backend("gensec", &gensec_ntlmssp_security_ops);
439         if (!NT_STATUS_IS_OK(ret)) {
440                 DEBUG(0,("Failed to register '%s' gensec backend!\n",
441                         gensec_ntlmssp_security_ops.name));
442                 return ret;
443         }
444
445         return ret;
446 }