s3-auth split the auth_generic functions into a seperate file
[ddiss/samba.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 static NTSTATUS gensec_ntlmssp3_server_session_info(struct gensec_security *gensec_security,
35                                         TALLOC_CTX *mem_ctx,
36                                         struct auth_session_info **session_info)
37 {
38         struct gensec_ntlmssp_context *gensec_ntlmssp =
39                 talloc_get_type_abort(gensec_security->private_data,
40                                       struct gensec_ntlmssp_context);
41         NTSTATUS nt_status;
42
43         nt_status = create_local_token(mem_ctx,
44                                        gensec_ntlmssp->server_info,
45                                        &gensec_ntlmssp->ntlmssp_state->session_key,
46                                        gensec_ntlmssp->ntlmssp_state->user,
47                                        session_info);
48         if (!NT_STATUS_IS_OK(nt_status)) {
49                 DEBUG(10, ("create_local_token failed: %s\n",
50                            nt_errstr(nt_status)));
51                 return nt_status;
52         }
53
54         return NT_STATUS_OK;
55 }
56
57 static NTSTATUS gensec_ntlmssp3_server_update(struct gensec_security *gensec_security,
58                                               TALLOC_CTX *out_mem_ctx,
59                                               struct tevent_context *ev,
60                                               const DATA_BLOB request,
61                                               DATA_BLOB *reply)
62 {
63         NTSTATUS status;
64         struct gensec_ntlmssp_context *gensec_ntlmssp =
65                 talloc_get_type_abort(gensec_security->private_data,
66                                       struct gensec_ntlmssp_context);
67
68         status = ntlmssp_update(gensec_ntlmssp->ntlmssp_state, request, reply);
69         if (NT_STATUS_IS_OK(status) ||
70             NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
71                 talloc_steal(out_mem_ctx, reply->data);
72         }
73
74         return status;
75 }
76
77 /**
78  * Return the challenge as determined by the authentication subsystem 
79  * @return an 8 byte random challenge
80  */
81
82 static NTSTATUS auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_state,
83                                            uint8_t chal[8])
84 {
85         struct gensec_ntlmssp_context *gensec_ntlmssp =
86                 (struct gensec_ntlmssp_context *)ntlmssp_state->callback_private;
87         gensec_ntlmssp->auth_context->get_ntlm_challenge(
88                 gensec_ntlmssp->auth_context, chal);
89         return NT_STATUS_OK;
90 }
91
92 /**
93  * Some authentication methods 'fix' the challenge, so we may not be able to set it
94  *
95  * @return If the effective challenge used by the auth subsystem may be modified
96  */
97 static bool auth_ntlmssp_may_set_challenge(const struct ntlmssp_state *ntlmssp_state)
98 {
99         struct gensec_ntlmssp_context *gensec_ntlmssp =
100                 (struct gensec_ntlmssp_context *)ntlmssp_state->callback_private;
101         struct auth_context *auth_context = gensec_ntlmssp->auth_context;
102
103         return auth_context->challenge_may_be_modified;
104 }
105
106 /**
107  * NTLM2 authentication modifies the effective challenge, 
108  * @param challenge The new challenge value
109  */
110 static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge)
111 {
112         struct gensec_ntlmssp_context *gensec_ntlmssp =
113                 (struct gensec_ntlmssp_context *)ntlmssp_state->callback_private;
114         struct auth_context *auth_context = gensec_ntlmssp->auth_context;
115
116         SMB_ASSERT(challenge->length == 8);
117
118         auth_context->challenge = data_blob_talloc(auth_context,
119                                                    challenge->data, challenge->length);
120
121         auth_context->challenge_set_by = "NTLMSSP callback (NTLM2)";
122
123         DEBUG(5, ("auth_context challenge set by %s\n", auth_context->challenge_set_by));
124         DEBUG(5, ("challenge is: \n"));
125         dump_data(5, auth_context->challenge.data, auth_context->challenge.length);
126         return NT_STATUS_OK;
127 }
128
129 /**
130  * Check the password on an NTLMSSP login.  
131  *
132  * Return the session keys used on the connection.
133  */
134
135 static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, TALLOC_CTX *mem_ctx,
136                                             DATA_BLOB *session_key, DATA_BLOB *lm_session_key)
137 {
138         struct gensec_ntlmssp_context *gensec_ntlmssp =
139                 (struct gensec_ntlmssp_context *)ntlmssp_state->callback_private;
140         struct auth_usersupplied_info *user_info = NULL;
141         NTSTATUS nt_status;
142         bool username_was_mapped;
143
144         /* the client has given us its machine name (which we otherwise would not get on port 445).
145            we need to possibly reload smb.conf if smb.conf includes depend on the machine name */
146
147         set_remote_machine_name(gensec_ntlmssp->ntlmssp_state->client.netbios_name, True);
148
149         /* setup the string used by %U */
150         /* sub_set_smb_name checks for weird internally */
151         sub_set_smb_name(gensec_ntlmssp->ntlmssp_state->user);
152
153         lp_load(get_dyn_CONFIGFILE(), false, false, true, true);
154
155         nt_status = make_user_info_map(&user_info,
156                                        gensec_ntlmssp->ntlmssp_state->user,
157                                        gensec_ntlmssp->ntlmssp_state->domain,
158                                        gensec_ntlmssp->ntlmssp_state->client.netbios_name,
159                                        gensec_get_remote_address(gensec_ntlmssp->gensec_security),
160                                        gensec_ntlmssp->ntlmssp_state->lm_resp.data ? &gensec_ntlmssp->ntlmssp_state->lm_resp : NULL,
161                                        gensec_ntlmssp->ntlmssp_state->nt_resp.data ? &gensec_ntlmssp->ntlmssp_state->nt_resp : NULL,
162                                        NULL, NULL, NULL,
163                                        AUTH_PASSWORD_RESPONSE);
164
165         if (!NT_STATUS_IS_OK(nt_status)) {
166                 return nt_status;
167         }
168
169         user_info->logon_parameters = MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT | MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
170
171         nt_status = gensec_ntlmssp->auth_context->check_ntlm_password(gensec_ntlmssp->auth_context,
172                                                                           user_info, &gensec_ntlmssp->server_info);
173
174         username_was_mapped = user_info->was_mapped;
175
176         free_user_info(&user_info);
177
178         if (!NT_STATUS_IS_OK(nt_status)) {
179                 nt_status = do_map_to_guest_server_info(nt_status,
180                                                         &gensec_ntlmssp->server_info,
181                                                         gensec_ntlmssp->ntlmssp_state->user,
182                                                         gensec_ntlmssp->ntlmssp_state->domain);
183                 return nt_status;
184         }
185
186         if (!NT_STATUS_IS_OK(nt_status)) {
187                 return nt_status;
188         }
189
190         gensec_ntlmssp->server_info->nss_token |= username_was_mapped;
191
192         /* Clear out the session keys, and pass them to the caller.
193          * They will not be used in this form again - instead the
194          * NTLMSSP code will decide on the final correct session key,
195          * and supply it to create_local_token() */
196         if (gensec_ntlmssp->server_info->session_key.length) {
197                 DEBUG(10, ("Got NT session key of length %u\n",
198                         (unsigned int)gensec_ntlmssp->server_info->session_key.length));
199                 *session_key = gensec_ntlmssp->server_info->session_key;
200                 talloc_steal(mem_ctx, gensec_ntlmssp->server_info->session_key.data);
201                 gensec_ntlmssp->server_info->session_key = data_blob_null;
202         }
203         if (gensec_ntlmssp->server_info->lm_session_key.length) {
204                 DEBUG(10, ("Got LM session key of length %u\n",
205                         (unsigned int)gensec_ntlmssp->server_info->lm_session_key.length));
206                 *lm_session_key = gensec_ntlmssp->server_info->lm_session_key;
207                 talloc_steal(mem_ctx, gensec_ntlmssp->server_info->lm_session_key.data);
208                 gensec_ntlmssp->server_info->lm_session_key = data_blob_null;
209         }
210         return nt_status;
211 }
212
213 static NTSTATUS gensec_ntlmssp3_server_start(struct gensec_security *gensec_security)
214 {
215         NTSTATUS nt_status;
216         bool is_standalone;
217         const char *netbios_name;
218         const char *netbios_domain;
219         const char *dns_name;
220         char *dns_domain;
221         struct gensec_ntlmssp_context *gensec_ntlmssp;
222
223         if ((enum server_role)lp_server_role() == ROLE_STANDALONE) {
224                 is_standalone = true;
225         } else {
226                 is_standalone = false;
227         }
228
229         netbios_name = lp_netbios_name();
230         netbios_domain = lp_workgroup();
231         /* This should be a 'netbios domain -> DNS domain' mapping */
232         dns_domain = get_mydnsdomname(talloc_tos());
233         if (dns_domain) {
234                 strlower_m(dns_domain);
235         }
236         dns_name = get_mydnsfullname();
237
238         nt_status = gensec_ntlmssp_start(gensec_security);
239         NT_STATUS_NOT_OK_RETURN(nt_status);
240
241         gensec_ntlmssp =
242                 talloc_get_type_abort(gensec_security->private_data,
243                                       struct gensec_ntlmssp_context);
244
245         nt_status = ntlmssp_server_start(gensec_ntlmssp,
246                                          is_standalone,
247                                          netbios_name,
248                                          netbios_domain,
249                                          dns_name,
250                                          dns_domain,
251                                          &gensec_ntlmssp->ntlmssp_state);
252         if (!NT_STATUS_IS_OK(nt_status)) {
253                 return nt_status;
254         }
255
256         gensec_ntlmssp->ntlmssp_state->callback_private = gensec_ntlmssp;
257
258         gensec_ntlmssp->ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge;
259         gensec_ntlmssp->ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge;
260         gensec_ntlmssp->ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge;
261         gensec_ntlmssp->ntlmssp_state->check_password = auth_ntlmssp_check_password;
262
263         if (gensec_ntlmssp->gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
264                 gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
265         }
266         if (gensec_ntlmssp->gensec_security->want_features & GENSEC_FEATURE_SIGN) {
267                 gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
268         }
269         if (gensec_ntlmssp->gensec_security->want_features & GENSEC_FEATURE_SEAL) {
270                 gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
271                 gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
272         }
273
274         return NT_STATUS_OK;
275 }
276
277 static const char *gensec_ntlmssp3_server_oids[] = {
278         GENSEC_OID_NTLMSSP,
279         NULL
280 };
281
282 const struct gensec_security_ops gensec_ntlmssp3_server_ops = {
283         .name           = "ntlmssp3_server",
284         .sasl_name      = GENSEC_SASL_NAME_NTLMSSP, /* "NTLM" */
285         .auth_type      = DCERPC_AUTH_TYPE_NTLMSSP,
286         .oid            = gensec_ntlmssp3_server_oids,
287         .server_start   = gensec_ntlmssp3_server_start,
288         .magic          = gensec_ntlmssp_magic,
289         .update         = gensec_ntlmssp3_server_update,
290         .sig_size       = gensec_ntlmssp_sig_size,
291         .sign_packet    = gensec_ntlmssp_sign_packet,
292         .check_packet   = gensec_ntlmssp_check_packet,
293         .seal_packet    = gensec_ntlmssp_seal_packet,
294         .unseal_packet  = gensec_ntlmssp_unseal_packet,
295         .wrap           = gensec_ntlmssp_wrap,
296         .unwrap         = gensec_ntlmssp_unwrap,
297         .session_key    = gensec_ntlmssp_session_key,
298         .session_info   = gensec_ntlmssp3_server_session_info,
299         .have_feature   = gensec_ntlmssp_have_feature,
300         .enabled        = true,
301         .priority       = GENSEC_NTLMSSP
302 };
303