s3-auth: Simplify how we free the auth_context
[mat/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
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 "../libcli/auth/ntlmssp.h"
25
26 struct auth_ntlmssp_state {
27         TALLOC_CTX *mem_ctx;
28         struct auth_context *auth_context;
29         struct auth_serversupplied_info *server_info;
30         struct ntlmssp_state *ntlmssp_state;
31 };
32
33 NTSTATUS auth_ntlmssp_sign_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
34                                   TALLOC_CTX *sig_mem_ctx,
35                                   const uint8_t *data, size_t length,
36                                   const uint8_t *whole_pdu, size_t pdu_length,
37                                   DATA_BLOB *sig)
38 {
39         return ntlmssp_sign_packet(auth_ntlmssp_state->ntlmssp_state, sig_mem_ctx, data, length, whole_pdu, pdu_length, sig);
40 }
41
42 NTSTATUS auth_ntlmssp_check_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
43                                    const uint8_t *data, size_t length,
44                                    const uint8_t *whole_pdu, size_t pdu_length,
45                                    const DATA_BLOB *sig)
46 {
47         return ntlmssp_check_packet(auth_ntlmssp_state->ntlmssp_state, data, length, whole_pdu, pdu_length, sig);
48 }
49
50 NTSTATUS auth_ntlmssp_seal_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
51                                   TALLOC_CTX *sig_mem_ctx,
52                                   uint8_t *data, size_t length,
53                                   const uint8_t *whole_pdu, size_t pdu_length,
54                                   DATA_BLOB *sig)
55 {
56         return ntlmssp_seal_packet(auth_ntlmssp_state->ntlmssp_state, sig_mem_ctx, data, length, whole_pdu, pdu_length, sig);
57 }
58
59 NTSTATUS auth_ntlmssp_unseal_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
60                                     uint8_t *data, size_t length,
61                                     const uint8_t *whole_pdu, size_t pdu_length,
62                                     const DATA_BLOB *sig)
63 {
64         return ntlmssp_unseal_packet(auth_ntlmssp_state->ntlmssp_state, data, length, whole_pdu, pdu_length, sig);
65 }
66
67 bool auth_ntlmssp_negotiated_sign(struct auth_ntlmssp_state *auth_ntlmssp_state)
68 {
69         return auth_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN;
70 }
71
72 bool auth_ntlmssp_negotiated_seal(struct auth_ntlmssp_state *auth_ntlmssp_state)
73 {
74         return auth_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL;
75 }
76
77 void auth_ntlmssp_want_sign(struct auth_ntlmssp_state *auth_ntlmssp_state)
78 {
79
80 }
81
82 void auth_ntlmssp_want_seal(struct auth_ntlmssp_state *auth_ntlmssp_state)
83 {
84
85 }
86
87 NTSTATUS auth_ntlmssp_server_info(TALLOC_CTX *mem_ctx,
88                                   struct auth_ntlmssp_state *auth_ntlmssp_state,
89                                   struct auth_serversupplied_info **_server_info)
90 {
91         struct auth_serversupplied_info *server_info = auth_ntlmssp_state->server_info;
92         data_blob_free(&server_info->user_session_key);
93         server_info->user_session_key =
94                 data_blob_talloc(
95                         server_info,
96                         auth_ntlmssp_state->ntlmssp_state->session_key.data,
97                         auth_ntlmssp_state->ntlmssp_state->session_key.length);
98         if (auth_ntlmssp_state->ntlmssp_state->session_key.length && !server_info->user_session_key.data) {
99                 *_server_info = NULL;
100                 return NT_STATUS_NO_MEMORY;
101         }
102         auth_ntlmssp_state->server_info = NULL;
103         *_server_info = talloc_steal(mem_ctx, server_info);
104         return NT_STATUS_OK;
105 }
106
107 struct ntlmssp_state *auth_ntlmssp_get_ntlmssp_state(struct auth_ntlmssp_state *auth_ntlmssp_state)
108 {
109         return auth_ntlmssp_state->ntlmssp_state;
110 }
111
112 /* Needed for 'map to guest' and 'smb username' processing */
113 const char *auth_ntlmssp_get_username(struct auth_ntlmssp_state *auth_ntlmssp_state)
114 {
115         return auth_ntlmssp_state->ntlmssp_state->user;
116 }
117
118 const char *auth_ntlmssp_get_domain(struct auth_ntlmssp_state *auth_ntlmssp_state)
119 {
120         return auth_ntlmssp_state->ntlmssp_state->domain;
121 }
122
123 const char *auth_ntlmssp_get_client(struct auth_ntlmssp_state *auth_ntlmssp_state)
124 {
125         return auth_ntlmssp_state->ntlmssp_state->client.netbios_name;
126 }
127
128 /**
129  * Return the challenge as determined by the authentication subsystem 
130  * @return an 8 byte random challenge
131  */
132
133 static NTSTATUS auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_state,
134                                            uint8_t chal[8])
135 {
136         struct auth_ntlmssp_state *auth_ntlmssp_state =
137                 (struct auth_ntlmssp_state *)ntlmssp_state->callback_private;
138         auth_ntlmssp_state->auth_context->get_ntlm_challenge(
139                 auth_ntlmssp_state->auth_context, chal);
140         return NT_STATUS_OK;
141 }
142
143 /**
144  * Some authentication methods 'fix' the challenge, so we may not be able to set it
145  *
146  * @return If the effective challenge used by the auth subsystem may be modified
147  */
148 static bool auth_ntlmssp_may_set_challenge(const struct ntlmssp_state *ntlmssp_state)
149 {
150         struct auth_ntlmssp_state *auth_ntlmssp_state =
151                 (struct auth_ntlmssp_state *)ntlmssp_state->callback_private;
152         struct auth_context *auth_context = auth_ntlmssp_state->auth_context;
153
154         return auth_context->challenge_may_be_modified;
155 }
156
157 /**
158  * NTLM2 authentication modifies the effective challenge, 
159  * @param challenge The new challenge value
160  */
161 static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge)
162 {
163         struct auth_ntlmssp_state *auth_ntlmssp_state =
164                 (struct auth_ntlmssp_state *)ntlmssp_state->callback_private;
165         struct auth_context *auth_context = auth_ntlmssp_state->auth_context;
166
167         SMB_ASSERT(challenge->length == 8);
168
169         auth_context->challenge = data_blob_talloc(auth_context,
170                                                    challenge->data, challenge->length);
171
172         auth_context->challenge_set_by = "NTLMSSP callback (NTLM2)";
173
174         DEBUG(5, ("auth_context challenge set by %s\n", auth_context->challenge_set_by));
175         DEBUG(5, ("challenge is: \n"));
176         dump_data(5, auth_context->challenge.data, auth_context->challenge.length);
177         return NT_STATUS_OK;
178 }
179
180 /**
181  * Check the password on an NTLMSSP login.  
182  *
183  * Return the session keys used on the connection.
184  */
185
186 static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key) 
187 {
188         struct auth_ntlmssp_state *auth_ntlmssp_state =
189                 (struct auth_ntlmssp_state *)ntlmssp_state->callback_private;
190         struct auth_usersupplied_info *user_info = NULL;
191         NTSTATUS nt_status;
192         bool username_was_mapped;
193
194         /* the client has given us its machine name (which we otherwise would not get on port 445).
195            we need to possibly reload smb.conf if smb.conf includes depend on the machine name */
196
197         set_remote_machine_name(auth_ntlmssp_state->ntlmssp_state->client.netbios_name, True);
198
199         /* setup the string used by %U */
200         /* sub_set_smb_name checks for weird internally */
201         sub_set_smb_name(auth_ntlmssp_state->ntlmssp_state->user);
202
203         reload_services(True);
204
205         nt_status = make_user_info_map(&user_info, 
206                                        auth_ntlmssp_state->ntlmssp_state->user, 
207                                        auth_ntlmssp_state->ntlmssp_state->domain, 
208                                        auth_ntlmssp_state->ntlmssp_state->client.netbios_name,
209                                        auth_ntlmssp_state->ntlmssp_state->lm_resp.data ? &auth_ntlmssp_state->ntlmssp_state->lm_resp : NULL, 
210                                        auth_ntlmssp_state->ntlmssp_state->nt_resp.data ? &auth_ntlmssp_state->ntlmssp_state->nt_resp : NULL, 
211                                        NULL, NULL, NULL,
212                                        True);
213
214         user_info->logon_parameters = MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT | MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
215
216         if (!NT_STATUS_IS_OK(nt_status)) {
217                 return nt_status;
218         }
219
220         nt_status = auth_ntlmssp_state->auth_context->check_ntlm_password(auth_ntlmssp_state->auth_context, 
221                                                                           user_info, &auth_ntlmssp_state->server_info); 
222
223         username_was_mapped = user_info->was_mapped;
224
225         free_user_info(&user_info);
226
227         if (!NT_STATUS_IS_OK(nt_status)) {
228                 return nt_status;
229         }
230
231         auth_ntlmssp_state->server_info->nss_token |= username_was_mapped;
232
233         nt_status = create_local_token(auth_ntlmssp_state->server_info);
234
235         if (!NT_STATUS_IS_OK(nt_status)) {
236                 DEBUG(10, ("create_local_token failed: %s\n",
237                         nt_errstr(nt_status)));
238                 return nt_status;
239         }
240
241         if (auth_ntlmssp_state->server_info->user_session_key.length) {
242                 DEBUG(10, ("Got NT session key of length %u\n",
243                         (unsigned int)auth_ntlmssp_state->server_info->user_session_key.length));
244                 *user_session_key = data_blob_talloc(auth_ntlmssp_state->mem_ctx, 
245                                                    auth_ntlmssp_state->server_info->user_session_key.data,
246                                                    auth_ntlmssp_state->server_info->user_session_key.length);
247         }
248         if (auth_ntlmssp_state->server_info->lm_session_key.length) {
249                 DEBUG(10, ("Got LM session key of length %u\n",
250                         (unsigned int)auth_ntlmssp_state->server_info->lm_session_key.length));
251                 *lm_session_key = data_blob_talloc(auth_ntlmssp_state->mem_ctx, 
252                                                    auth_ntlmssp_state->server_info->lm_session_key.data,
253                                                    auth_ntlmssp_state->server_info->lm_session_key.length);
254         }
255         return nt_status;
256 }
257
258 NTSTATUS auth_ntlmssp_start(struct auth_ntlmssp_state **auth_ntlmssp_state)
259 {
260         NTSTATUS nt_status;
261         TALLOC_CTX *mem_ctx;
262         bool is_standalone;
263         const char *netbios_name;
264         const char *netbios_domain;
265         const char *dns_name;
266         char *dns_domain;
267         struct auth_ntlmssp_state *ans;
268
269         if ((enum server_types)lp_server_role() == ROLE_STANDALONE) {
270                 is_standalone = true;
271         } else {
272                 is_standalone = false;
273         }
274
275         netbios_name = global_myname();
276         netbios_domain = lp_workgroup();
277         /* This should be a 'netbios domain -> DNS domain' mapping */
278         dns_domain = get_mydnsdomname(talloc_tos());
279         if (dns_domain) {
280                 strlower_m(dns_domain);
281         }
282         dns_name = get_mydnsfullname();
283
284         mem_ctx = talloc_init("AUTH NTLMSSP context");
285
286         ans = talloc_zero(mem_ctx, struct auth_ntlmssp_state);
287         if (!ans) {
288                 DEBUG(0,("auth_ntlmssp_start: talloc failed!\n"));
289                 talloc_destroy(mem_ctx);
290                 return NT_STATUS_NO_MEMORY;
291         }
292
293         ans->mem_ctx = mem_ctx;
294
295         nt_status = ntlmssp_server_start(NULL,
296                                          is_standalone,
297                                          netbios_name,
298                                          netbios_domain,
299                                          dns_name,
300                                          dns_domain,
301                                          &ans->ntlmssp_state);
302         if (!NT_STATUS_IS_OK(nt_status)) {
303                 return nt_status;
304         }
305
306         nt_status = make_auth_context_subsystem(&ans->auth_context);
307         if (!NT_STATUS_IS_OK(nt_status)) {
308                 return nt_status;
309         }
310
311         ans->ntlmssp_state->callback_private = ans;
312         ans->ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge;
313         ans->ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge;
314         ans->ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge;
315         ans->ntlmssp_state->check_password = auth_ntlmssp_check_password;
316
317         *auth_ntlmssp_state = ans;
318         return NT_STATUS_OK;
319 }
320
321 void auth_ntlmssp_end(struct auth_ntlmssp_state **auth_ntlmssp_state)
322 {
323         struct auth_ntlmssp_state *ans = *auth_ntlmssp_state;
324         TALLOC_CTX *mem_ctx;
325
326         if (ans == NULL) {
327                 return;
328         }
329
330         mem_ctx = ans->mem_ctx;
331         if (ans->ntlmssp_state) {
332                 TALLOC_FREE(ans->ntlmssp_state);
333         }
334         if (ans->auth_context) {
335                 TALLOC_FREE(ans->auth_context);
336         }
337         if (ans->server_info) {
338                 TALLOC_FREE(ans->server_info);
339         }
340         talloc_destroy(mem_ctx);
341         *auth_ntlmssp_state = NULL;
342 }
343
344 NTSTATUS auth_ntlmssp_update(struct auth_ntlmssp_state *auth_ntlmssp_state,
345                              const DATA_BLOB request, DATA_BLOB *reply) 
346 {
347         return ntlmssp_update(auth_ntlmssp_state->ntlmssp_state, request, reply);
348 }