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