s3-auth move the s3 auth context onto gensec_ntlmssp once we start
[ira/wip.git] / source3 / auth / auth_ntlmssp.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 3.0
4    handle NLTMSSP, server side
5
6    Copyright (C) Andrew Tridgell      2001
7    Copyright (C) Andrew Bartlett 2001-2003,2011
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 3 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, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "auth.h"
25 #include "../auth/ntlmssp/ntlmssp.h"
26 #include "ntlmssp_wrap.h"
27 #include "../librpc/gen_ndr/netlogon.h"
28 #include "../librpc/gen_ndr/dcerpc.h"
29 #include "../lib/tsocket/tsocket.h"
30 #include "auth/gensec/gensec.h"
31 #include "librpc/rpc/dcerpc.h"
32 #include "lib/param/param.h"
33
34 NTSTATUS auth_ntlmssp_session_info(TALLOC_CTX *mem_ctx,
35                                    struct auth_ntlmssp_state *auth_ntlmssp_state,
36                                    struct auth_session_info **session_info)
37 {
38         NTSTATUS nt_status;
39         nt_status = gensec_session_info(auth_ntlmssp_state->gensec_security,
40                                         mem_ctx,
41                                         session_info);
42         return nt_status;
43 }
44
45 static NTSTATUS gensec_ntlmssp3_server_session_info(struct gensec_security *gensec_security,
46                                         TALLOC_CTX *mem_ctx,
47                                         struct auth_session_info **session_info)
48 {
49         struct gensec_ntlmssp_context *gensec_ntlmssp =
50                 talloc_get_type_abort(gensec_security->private_data,
51                                       struct gensec_ntlmssp_context);
52         NTSTATUS nt_status;
53
54         nt_status = create_local_token(mem_ctx,
55                                        gensec_ntlmssp->server_info,
56                                        &gensec_ntlmssp->ntlmssp_state->session_key,
57                                        gensec_ntlmssp->ntlmssp_state->user,
58                                        session_info);
59         if (!NT_STATUS_IS_OK(nt_status)) {
60                 DEBUG(10, ("create_local_token failed: %s\n",
61                            nt_errstr(nt_status)));
62                 return nt_status;
63         }
64
65         return NT_STATUS_OK;
66 }
67
68 static NTSTATUS gensec_ntlmssp3_server_update(struct gensec_security *gensec_security,
69                                               TALLOC_CTX *out_mem_ctx,
70                                               struct tevent_context *ev,
71                                               const DATA_BLOB request,
72                                               DATA_BLOB *reply)
73 {
74         NTSTATUS status;
75         struct gensec_ntlmssp_context *gensec_ntlmssp =
76                 talloc_get_type_abort(gensec_security->private_data,
77                                       struct gensec_ntlmssp_context);
78
79         status = ntlmssp_update(gensec_ntlmssp->ntlmssp_state, request, reply);
80         if (NT_STATUS_IS_OK(status) ||
81             NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
82                 talloc_steal(out_mem_ctx, reply->data);
83         }
84
85         return status;
86 }
87
88 /**
89  * Return the challenge as determined by the authentication subsystem 
90  * @return an 8 byte random challenge
91  */
92
93 static NTSTATUS auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_state,
94                                            uint8_t chal[8])
95 {
96         struct gensec_ntlmssp_context *gensec_ntlmssp =
97                 (struct gensec_ntlmssp_context *)ntlmssp_state->callback_private;
98         gensec_ntlmssp->auth_context->get_ntlm_challenge(
99                 gensec_ntlmssp->auth_context, chal);
100         return NT_STATUS_OK;
101 }
102
103 /**
104  * Some authentication methods 'fix' the challenge, so we may not be able to set it
105  *
106  * @return If the effective challenge used by the auth subsystem may be modified
107  */
108 static bool auth_ntlmssp_may_set_challenge(const struct ntlmssp_state *ntlmssp_state)
109 {
110         struct gensec_ntlmssp_context *gensec_ntlmssp =
111                 (struct gensec_ntlmssp_context *)ntlmssp_state->callback_private;
112         struct auth_context *auth_context = gensec_ntlmssp->auth_context;
113
114         return auth_context->challenge_may_be_modified;
115 }
116
117 /**
118  * NTLM2 authentication modifies the effective challenge, 
119  * @param challenge The new challenge value
120  */
121 static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge)
122 {
123         struct gensec_ntlmssp_context *gensec_ntlmssp =
124                 (struct gensec_ntlmssp_context *)ntlmssp_state->callback_private;
125         struct auth_context *auth_context = gensec_ntlmssp->auth_context;
126
127         SMB_ASSERT(challenge->length == 8);
128
129         auth_context->challenge = data_blob_talloc(auth_context,
130                                                    challenge->data, challenge->length);
131
132         auth_context->challenge_set_by = "NTLMSSP callback (NTLM2)";
133
134         DEBUG(5, ("auth_context challenge set by %s\n", auth_context->challenge_set_by));
135         DEBUG(5, ("challenge is: \n"));
136         dump_data(5, auth_context->challenge.data, auth_context->challenge.length);
137         return NT_STATUS_OK;
138 }
139
140 /**
141  * Check the password on an NTLMSSP login.  
142  *
143  * Return the session keys used on the connection.
144  */
145
146 static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, TALLOC_CTX *mem_ctx,
147                                             DATA_BLOB *session_key, DATA_BLOB *lm_session_key)
148 {
149         struct gensec_ntlmssp_context *gensec_ntlmssp =
150                 (struct gensec_ntlmssp_context *)ntlmssp_state->callback_private;
151         struct auth_usersupplied_info *user_info = NULL;
152         NTSTATUS nt_status;
153         bool username_was_mapped;
154
155         /* the client has given us its machine name (which we otherwise would not get on port 445).
156            we need to possibly reload smb.conf if smb.conf includes depend on the machine name */
157
158         set_remote_machine_name(gensec_ntlmssp->ntlmssp_state->client.netbios_name, True);
159
160         /* setup the string used by %U */
161         /* sub_set_smb_name checks for weird internally */
162         sub_set_smb_name(gensec_ntlmssp->ntlmssp_state->user);
163
164         lp_load(get_dyn_CONFIGFILE(), false, false, true, true);
165
166         nt_status = make_user_info_map(&user_info,
167                                        gensec_ntlmssp->ntlmssp_state->user,
168                                        gensec_ntlmssp->ntlmssp_state->domain,
169                                        gensec_ntlmssp->ntlmssp_state->client.netbios_name,
170                                        gensec_get_remote_address(gensec_ntlmssp->gensec_security),
171                                        gensec_ntlmssp->ntlmssp_state->lm_resp.data ? &gensec_ntlmssp->ntlmssp_state->lm_resp : NULL,
172                                        gensec_ntlmssp->ntlmssp_state->nt_resp.data ? &gensec_ntlmssp->ntlmssp_state->nt_resp : NULL,
173                                        NULL, NULL, NULL,
174                                        AUTH_PASSWORD_RESPONSE);
175
176         if (!NT_STATUS_IS_OK(nt_status)) {
177                 return nt_status;
178         }
179
180         user_info->logon_parameters = MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT | MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
181
182         nt_status = gensec_ntlmssp->auth_context->check_ntlm_password(gensec_ntlmssp->auth_context,
183                                                                           user_info, &gensec_ntlmssp->server_info);
184
185         username_was_mapped = user_info->was_mapped;
186
187         free_user_info(&user_info);
188
189         if (!NT_STATUS_IS_OK(nt_status)) {
190                 nt_status = do_map_to_guest_server_info(nt_status,
191                                                         &gensec_ntlmssp->server_info,
192                                                         gensec_ntlmssp->ntlmssp_state->user,
193                                                         gensec_ntlmssp->ntlmssp_state->domain);
194                 return nt_status;
195         }
196
197         if (!NT_STATUS_IS_OK(nt_status)) {
198                 return nt_status;
199         }
200
201         gensec_ntlmssp->server_info->nss_token |= username_was_mapped;
202
203         /* Clear out the session keys, and pass them to the caller.
204          * They will not be used in this form again - instead the
205          * NTLMSSP code will decide on the final correct session key,
206          * and supply it to create_local_token() */
207         if (gensec_ntlmssp->server_info->session_key.length) {
208                 DEBUG(10, ("Got NT session key of length %u\n",
209                         (unsigned int)gensec_ntlmssp->server_info->session_key.length));
210                 *session_key = gensec_ntlmssp->server_info->session_key;
211                 talloc_steal(mem_ctx, gensec_ntlmssp->server_info->session_key.data);
212                 gensec_ntlmssp->server_info->session_key = data_blob_null;
213         }
214         if (gensec_ntlmssp->server_info->lm_session_key.length) {
215                 DEBUG(10, ("Got LM session key of length %u\n",
216                         (unsigned int)gensec_ntlmssp->server_info->lm_session_key.length));
217                 *lm_session_key = gensec_ntlmssp->server_info->lm_session_key;
218                 talloc_steal(mem_ctx, gensec_ntlmssp->server_info->lm_session_key.data);
219                 gensec_ntlmssp->server_info->lm_session_key = data_blob_null;
220         }
221         return nt_status;
222 }
223
224 NTSTATUS auth_ntlmssp_prepare(const struct tsocket_address *remote_address,
225                               struct auth_ntlmssp_state **auth_ntlmssp_state)
226 {
227         struct auth_context *auth_context;
228         struct auth_ntlmssp_state *ans;
229         NTSTATUS nt_status;
230
231         ans = talloc_zero(NULL, struct auth_ntlmssp_state);
232         if (!ans) {
233                 DEBUG(0,("auth_ntlmssp_start: talloc failed!\n"));
234                 return NT_STATUS_NO_MEMORY;
235         }
236
237         nt_status = make_auth_context_subsystem(talloc_tos(), &auth_context);
238         if (!NT_STATUS_IS_OK(nt_status)) {
239                 TALLOC_FREE(ans);
240                 return nt_status;
241         }
242
243         ans->auth_context = talloc_steal(ans, auth_context);
244
245         if (auth_context->prepare_gensec) {
246                 nt_status = auth_context->prepare_gensec(ans,
247                                                          &ans->gensec_security);
248                 if (!NT_STATUS_IS_OK(nt_status)) {
249                         TALLOC_FREE(ans);
250                         return nt_status;
251                 }
252                 *auth_ntlmssp_state = ans;
253                 return NT_STATUS_OK;
254         } else {
255                 struct gensec_settings *gensec_settings;
256                 struct loadparm_context *lp_ctx;
257
258                 lp_ctx = loadparm_init_s3(ans, loadparm_s3_context());
259                 if (lp_ctx == NULL) {
260                         DEBUG(10, ("loadparm_init_s3 failed\n"));
261                         TALLOC_FREE(ans);
262                         return NT_STATUS_INVALID_SERVER_STATE;
263                 }
264
265                 gensec_settings = lpcfg_gensec_settings(ans, lp_ctx);
266                 if (lp_ctx == NULL) {
267                         DEBUG(10, ("lpcfg_gensec_settings failed\n"));
268                         TALLOC_FREE(ans);
269                         return NT_STATUS_NO_MEMORY;
270                 }
271
272                 nt_status = gensec_server_start(ans, gensec_settings,
273                                                 NULL, &ans->gensec_security);
274
275                 if (!NT_STATUS_IS_OK(nt_status)) {
276                         TALLOC_FREE(ans);
277                         return nt_status;
278                 }
279                 talloc_unlink(ans, lp_ctx);
280                 talloc_unlink(ans, gensec_settings);
281         }
282
283         nt_status = gensec_set_remote_address(ans->gensec_security,
284                                               remote_address);
285         if (!NT_STATUS_IS_OK(nt_status)) {
286                 TALLOC_FREE(ans);
287                 return nt_status;
288         }
289
290         *auth_ntlmssp_state = ans;
291         return NT_STATUS_OK;
292 }
293
294 static NTSTATUS gensec_ntlmssp3_server_start(struct gensec_security *gensec_security)
295 {
296         NTSTATUS nt_status;
297         bool is_standalone;
298         const char *netbios_name;
299         const char *netbios_domain;
300         const char *dns_name;
301         char *dns_domain;
302         struct gensec_ntlmssp_context *gensec_ntlmssp;
303
304         if ((enum server_role)lp_server_role() == ROLE_STANDALONE) {
305                 is_standalone = true;
306         } else {
307                 is_standalone = false;
308         }
309
310         netbios_name = lp_netbios_name();
311         netbios_domain = lp_workgroup();
312         /* This should be a 'netbios domain -> DNS domain' mapping */
313         dns_domain = get_mydnsdomname(talloc_tos());
314         if (dns_domain) {
315                 strlower_m(dns_domain);
316         }
317         dns_name = get_mydnsfullname();
318
319         nt_status = gensec_ntlmssp_start(gensec_security);
320         NT_STATUS_NOT_OK_RETURN(nt_status);
321
322         gensec_ntlmssp =
323                 talloc_get_type_abort(gensec_security->private_data,
324                                       struct gensec_ntlmssp_context);
325
326         nt_status = ntlmssp_server_start(gensec_ntlmssp,
327                                          is_standalone,
328                                          netbios_name,
329                                          netbios_domain,
330                                          dns_name,
331                                          dns_domain,
332                                          &gensec_ntlmssp->ntlmssp_state);
333         if (!NT_STATUS_IS_OK(nt_status)) {
334                 return nt_status;
335         }
336
337         gensec_ntlmssp->ntlmssp_state->callback_private = gensec_ntlmssp;
338
339         gensec_ntlmssp->ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge;
340         gensec_ntlmssp->ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge;
341         gensec_ntlmssp->ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge;
342         gensec_ntlmssp->ntlmssp_state->check_password = auth_ntlmssp_check_password;
343
344         if (gensec_ntlmssp->gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
345                 gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
346         }
347         if (gensec_ntlmssp->gensec_security->want_features & GENSEC_FEATURE_SIGN) {
348                 gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
349         }
350         if (gensec_ntlmssp->gensec_security->want_features & GENSEC_FEATURE_SEAL) {
351                 gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
352                 gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
353         }
354
355         return NT_STATUS_OK;
356 }
357
358 static const char *gensec_ntlmssp3_server_oids[] = {
359         GENSEC_OID_NTLMSSP,
360         NULL
361 };
362
363 static const struct gensec_security_ops gensec_ntlmssp3_server_ops = {
364         .name           = "ntlmssp3_server",
365         .sasl_name      = GENSEC_SASL_NAME_NTLMSSP, /* "NTLM" */
366         .auth_type      = DCERPC_AUTH_TYPE_NTLMSSP,
367         .oid            = gensec_ntlmssp3_server_oids,
368         .server_start   = gensec_ntlmssp3_server_start,
369         .magic          = gensec_ntlmssp_magic,
370         .update         = gensec_ntlmssp3_server_update,
371         .sig_size       = gensec_ntlmssp_sig_size,
372         .sign_packet    = gensec_ntlmssp_sign_packet,
373         .check_packet   = gensec_ntlmssp_check_packet,
374         .seal_packet    = gensec_ntlmssp_seal_packet,
375         .unseal_packet  = gensec_ntlmssp_unseal_packet,
376         .wrap           = gensec_ntlmssp_wrap,
377         .unwrap         = gensec_ntlmssp_unwrap,
378         .session_key    = gensec_ntlmssp_session_key,
379         .session_info   = gensec_ntlmssp3_server_session_info,
380         .have_feature   = gensec_ntlmssp_have_feature,
381         .enabled        = true,
382         .priority       = GENSEC_NTLMSSP
383 };
384
385 NTSTATUS auth_generic_start(struct auth_ntlmssp_state *auth_ntlmssp_state, const char *oid)
386 {
387         struct gensec_ntlmssp_context *gensec_ntlmssp;
388         NTSTATUS status;
389
390         if (auth_ntlmssp_state->auth_context->gensec_start_mech_by_oid) {
391                 return auth_ntlmssp_state->auth_context->gensec_start_mech_by_oid(
392                                 auth_ntlmssp_state->gensec_security, oid);
393         }
394
395         if (strcmp(oid, GENSEC_OID_NTLMSSP) != 0) {
396                 return NT_STATUS_NOT_IMPLEMENTED;
397         }
398
399         status = gensec_start_mech_by_ops(auth_ntlmssp_state->gensec_security,
400                                           &gensec_ntlmssp3_server_ops);
401         if (!NT_STATUS_IS_OK(status)) {
402                 return status;
403         }
404
405         gensec_ntlmssp =
406                 talloc_get_type_abort(auth_ntlmssp_state->gensec_security->private_data,
407                                       struct gensec_ntlmssp_context);
408
409         gensec_ntlmssp->auth_context = talloc_move(gensec_ntlmssp, &auth_ntlmssp_state->auth_context);
410
411         return NT_STATUS_OK;
412 }
413
414 NTSTATUS auth_generic_authtype_start(struct auth_ntlmssp_state *auth_ntlmssp_state,
415                                      uint8_t auth_type, uint8_t auth_level)
416 {
417         struct gensec_ntlmssp_context *gensec_ntlmssp;
418         NTSTATUS status;
419
420         if (auth_ntlmssp_state->auth_context->gensec_start_mech_by_authtype) {
421                 return auth_ntlmssp_state->auth_context->gensec_start_mech_by_authtype(
422                                 auth_ntlmssp_state->gensec_security,
423                                 auth_type, auth_level);
424         }
425
426         if (auth_type != DCERPC_AUTH_TYPE_NTLMSSP) {
427                 /* The caller will then free the auth_ntlmssp_state,
428                  * undoing what was done in auth_ntlmssp_prepare().
429                  *
430                  * We can't do that logic here, as
431                  * auth_ntlmssp_want_feature() may have been called in
432                  * between.
433                  */
434                 return NT_STATUS_NOT_IMPLEMENTED;
435         }
436
437         gensec_want_feature(auth_ntlmssp_state->gensec_security,
438                             GENSEC_FEATURE_DCE_STYLE);
439         gensec_want_feature(auth_ntlmssp_state->gensec_security,
440                             GENSEC_FEATURE_ASYNC_REPLIES);
441         if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
442                 gensec_want_feature(auth_ntlmssp_state->gensec_security,
443                                     GENSEC_FEATURE_SIGN);
444         } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
445                 gensec_want_feature(auth_ntlmssp_state->gensec_security,
446                                     GENSEC_FEATURE_SIGN);
447                 gensec_want_feature(auth_ntlmssp_state->gensec_security,
448                                     GENSEC_FEATURE_SEAL);
449         } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
450                 /* Default features */
451         } else {
452                 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
453                          auth_level));
454                 return NT_STATUS_INVALID_PARAMETER;
455         }
456
457         status = gensec_start_mech_by_ops(auth_ntlmssp_state->gensec_security,
458                                           &gensec_ntlmssp3_server_ops);
459         if (!NT_STATUS_IS_OK(status)) {
460                 return status;
461         }
462
463         gensec_ntlmssp =
464                 talloc_get_type_abort(auth_ntlmssp_state->gensec_security->private_data,
465                                       struct gensec_ntlmssp_context);
466
467         gensec_ntlmssp->auth_context = talloc_move(gensec_ntlmssp, &auth_ntlmssp_state->auth_context);
468
469         return NT_STATUS_OK;
470 }
471
472 NTSTATUS auth_ntlmssp_start(struct auth_ntlmssp_state *auth_ntlmssp_state)
473 {
474         return auth_generic_start(auth_ntlmssp_state, GENSEC_OID_NTLMSSP);
475 }