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