s3:auth Change auth_ntlmssp_server_info API to return NTSTATUS
[amitay/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
268         if ((enum server_types)lp_server_role() == ROLE_STANDALONE) {
269                 is_standalone = true;
270         } else {
271                 is_standalone = false;
272         }
273
274         netbios_name = global_myname();
275         netbios_domain = lp_workgroup();
276         /* This should be a 'netbios domain -> DNS domain' mapping */
277         dns_domain = get_mydnsdomname(talloc_tos());
278         if (dns_domain) {
279                 strlower_m(dns_domain);
280         }
281         dns_name = get_mydnsfullname();
282
283         mem_ctx = talloc_init("AUTH NTLMSSP context");
284         
285         *auth_ntlmssp_state = TALLOC_ZERO_P(mem_ctx, struct auth_ntlmssp_state);
286         if (!*auth_ntlmssp_state) {
287                 DEBUG(0,("auth_ntlmssp_start: talloc failed!\n"));
288                 talloc_destroy(mem_ctx);
289                 return NT_STATUS_NO_MEMORY;
290         }
291
292         ZERO_STRUCTP(*auth_ntlmssp_state);
293
294         (*auth_ntlmssp_state)->mem_ctx = mem_ctx;
295
296         nt_status = ntlmssp_server_start(NULL,
297                                          is_standalone,
298                                          netbios_name,
299                                          netbios_domain,
300                                          dns_name,
301                                          dns_domain,
302                                          &(*auth_ntlmssp_state)->ntlmssp_state);
303         if (!NT_STATUS_IS_OK(nt_status)) {
304                 return nt_status;
305         }
306
307         if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&(*auth_ntlmssp_state)->auth_context))) {
308                 return nt_status;
309         }
310
311         (*auth_ntlmssp_state)->ntlmssp_state->callback_private = (*auth_ntlmssp_state);
312         (*auth_ntlmssp_state)->ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge;
313         (*auth_ntlmssp_state)->ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge;
314         (*auth_ntlmssp_state)->ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge;
315         (*auth_ntlmssp_state)->ntlmssp_state->check_password = auth_ntlmssp_check_password;
316
317         return NT_STATUS_OK;
318 }
319
320 void auth_ntlmssp_end(struct auth_ntlmssp_state **auth_ntlmssp_state)
321 {
322         TALLOC_CTX *mem_ctx;
323
324         if (*auth_ntlmssp_state == NULL) {
325                 return;
326         }
327
328         mem_ctx = (*auth_ntlmssp_state)->mem_ctx;
329         if ((*auth_ntlmssp_state)->ntlmssp_state) {
330                 ntlmssp_end(&(*auth_ntlmssp_state)->ntlmssp_state);
331         }
332         if ((*auth_ntlmssp_state)->auth_context) {
333                 ((*auth_ntlmssp_state)->auth_context->free)(&(*auth_ntlmssp_state)->auth_context);
334         }
335         if ((*auth_ntlmssp_state)->server_info) {
336                 TALLOC_FREE((*auth_ntlmssp_state)->server_info);
337         }
338         talloc_destroy(mem_ctx);
339         *auth_ntlmssp_state = NULL;
340 }
341
342 NTSTATUS auth_ntlmssp_update(struct auth_ntlmssp_state *auth_ntlmssp_state,
343                              const DATA_BLOB request, DATA_BLOB *reply) 
344 {
345         return ntlmssp_update(auth_ntlmssp_state->ntlmssp_state, request, reply);
346 }