s3: Lift the smbd_messaging_context from reload_services
[metze/samba/wip.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 #include "ntlmssp_wrap.h"
26 #include "../librpc/gen_ndr/netlogon.h"
27
28 NTSTATUS auth_ntlmssp_steal_server_info(TALLOC_CTX *mem_ctx,
29                                 struct auth_ntlmssp_state *auth_ntlmssp_state,
30                                 struct auth_serversupplied_info **server_info)
31 {
32         /* Free the current server_info user_session_key and reset it from the
33          * current ntlmssp_state session_key */
34         data_blob_free(&auth_ntlmssp_state->server_info->user_session_key);
35         auth_ntlmssp_state->server_info->user_session_key =
36                 data_blob_talloc(
37                         auth_ntlmssp_state->server_info,
38                         auth_ntlmssp_state->ntlmssp_state->session_key.data,
39                         auth_ntlmssp_state->ntlmssp_state->session_key.length);
40         if (auth_ntlmssp_state->ntlmssp_state->session_key.length &&
41             !auth_ntlmssp_state->server_info->user_session_key.data) {
42                 *server_info = NULL;
43                 return NT_STATUS_NO_MEMORY;
44         }
45         /* Steal server_info away from auth_ntlmssp_state */
46         *server_info = talloc_move(mem_ctx, &auth_ntlmssp_state->server_info);
47         return NT_STATUS_OK;
48 }
49
50 /**
51  * Return the challenge as determined by the authentication subsystem 
52  * @return an 8 byte random challenge
53  */
54
55 static NTSTATUS auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_state,
56                                            uint8_t chal[8])
57 {
58         struct auth_ntlmssp_state *auth_ntlmssp_state =
59                 (struct auth_ntlmssp_state *)ntlmssp_state->callback_private;
60         auth_ntlmssp_state->auth_context->get_ntlm_challenge(
61                 auth_ntlmssp_state->auth_context, chal);
62         return NT_STATUS_OK;
63 }
64
65 /**
66  * Some authentication methods 'fix' the challenge, so we may not be able to set it
67  *
68  * @return If the effective challenge used by the auth subsystem may be modified
69  */
70 static bool auth_ntlmssp_may_set_challenge(const struct ntlmssp_state *ntlmssp_state)
71 {
72         struct auth_ntlmssp_state *auth_ntlmssp_state =
73                 (struct auth_ntlmssp_state *)ntlmssp_state->callback_private;
74         struct auth_context *auth_context = auth_ntlmssp_state->auth_context;
75
76         return auth_context->challenge_may_be_modified;
77 }
78
79 /**
80  * NTLM2 authentication modifies the effective challenge, 
81  * @param challenge The new challenge value
82  */
83 static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge)
84 {
85         struct auth_ntlmssp_state *auth_ntlmssp_state =
86                 (struct auth_ntlmssp_state *)ntlmssp_state->callback_private;
87         struct auth_context *auth_context = auth_ntlmssp_state->auth_context;
88
89         SMB_ASSERT(challenge->length == 8);
90
91         auth_context->challenge = data_blob_talloc(auth_context,
92                                                    challenge->data, challenge->length);
93
94         auth_context->challenge_set_by = "NTLMSSP callback (NTLM2)";
95
96         DEBUG(5, ("auth_context challenge set by %s\n", auth_context->challenge_set_by));
97         DEBUG(5, ("challenge is: \n"));
98         dump_data(5, auth_context->challenge.data, auth_context->challenge.length);
99         return NT_STATUS_OK;
100 }
101
102 /**
103  * Check the password on an NTLMSSP login.  
104  *
105  * Return the session keys used on the connection.
106  */
107
108 static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key) 
109 {
110         struct auth_ntlmssp_state *auth_ntlmssp_state =
111                 (struct auth_ntlmssp_state *)ntlmssp_state->callback_private;
112         struct auth_usersupplied_info *user_info = NULL;
113         NTSTATUS nt_status;
114         bool username_was_mapped;
115
116         /* the client has given us its machine name (which we otherwise would not get on port 445).
117            we need to possibly reload smb.conf if smb.conf includes depend on the machine name */
118
119         set_remote_machine_name(auth_ntlmssp_state->ntlmssp_state->client.netbios_name, True);
120
121         /* setup the string used by %U */
122         /* sub_set_smb_name checks for weird internally */
123         sub_set_smb_name(auth_ntlmssp_state->ntlmssp_state->user);
124
125         reload_services(smbd_messaging_context(), True);
126
127         nt_status = make_user_info_map(&user_info, 
128                                        auth_ntlmssp_state->ntlmssp_state->user, 
129                                        auth_ntlmssp_state->ntlmssp_state->domain, 
130                                        auth_ntlmssp_state->ntlmssp_state->client.netbios_name,
131                                        auth_ntlmssp_state->ntlmssp_state->lm_resp.data ? &auth_ntlmssp_state->ntlmssp_state->lm_resp : NULL, 
132                                        auth_ntlmssp_state->ntlmssp_state->nt_resp.data ? &auth_ntlmssp_state->ntlmssp_state->nt_resp : NULL, 
133                                        NULL, NULL, NULL,
134                                        True);
135
136         user_info->logon_parameters = MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT | MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
137
138         if (!NT_STATUS_IS_OK(nt_status)) {
139                 return nt_status;
140         }
141
142         nt_status = auth_ntlmssp_state->auth_context->check_ntlm_password(auth_ntlmssp_state->auth_context, 
143                                                                           user_info, &auth_ntlmssp_state->server_info); 
144
145         username_was_mapped = user_info->was_mapped;
146
147         free_user_info(&user_info);
148
149         if (!NT_STATUS_IS_OK(nt_status)) {
150                 return nt_status;
151         }
152
153         auth_ntlmssp_state->server_info->nss_token |= username_was_mapped;
154
155         nt_status = create_local_token(auth_ntlmssp_state->server_info);
156
157         if (!NT_STATUS_IS_OK(nt_status)) {
158                 DEBUG(10, ("create_local_token failed: %s\n",
159                         nt_errstr(nt_status)));
160                 return nt_status;
161         }
162
163         if (auth_ntlmssp_state->server_info->user_session_key.length) {
164                 DEBUG(10, ("Got NT session key of length %u\n",
165                         (unsigned int)auth_ntlmssp_state->server_info->user_session_key.length));
166                 *user_session_key = data_blob_talloc(auth_ntlmssp_state,
167                                                    auth_ntlmssp_state->server_info->user_session_key.data,
168                                                    auth_ntlmssp_state->server_info->user_session_key.length);
169         }
170         if (auth_ntlmssp_state->server_info->lm_session_key.length) {
171                 DEBUG(10, ("Got LM session key of length %u\n",
172                         (unsigned int)auth_ntlmssp_state->server_info->lm_session_key.length));
173                 *lm_session_key = data_blob_talloc(auth_ntlmssp_state,
174                                                    auth_ntlmssp_state->server_info->lm_session_key.data,
175                                                    auth_ntlmssp_state->server_info->lm_session_key.length);
176         }
177         return nt_status;
178 }
179
180 static int auth_ntlmssp_state_destructor(void *ptr);
181
182 NTSTATUS auth_ntlmssp_start(struct auth_ntlmssp_state **auth_ntlmssp_state)
183 {
184         NTSTATUS nt_status;
185         bool is_standalone;
186         const char *netbios_name;
187         const char *netbios_domain;
188         const char *dns_name;
189         char *dns_domain;
190         struct auth_ntlmssp_state *ans;
191         struct auth_context *auth_context;
192
193         if ((enum server_types)lp_server_role() == ROLE_STANDALONE) {
194                 is_standalone = true;
195         } else {
196                 is_standalone = false;
197         }
198
199         netbios_name = global_myname();
200         netbios_domain = lp_workgroup();
201         /* This should be a 'netbios domain -> DNS domain' mapping */
202         dns_domain = get_mydnsdomname(talloc_tos());
203         if (dns_domain) {
204                 strlower_m(dns_domain);
205         }
206         dns_name = get_mydnsfullname();
207
208         ans = talloc_zero(NULL, struct auth_ntlmssp_state);
209         if (!ans) {
210                 DEBUG(0,("auth_ntlmssp_start: talloc failed!\n"));
211                 return NT_STATUS_NO_MEMORY;
212         }
213
214         nt_status = ntlmssp_server_start(ans,
215                                          is_standalone,
216                                          netbios_name,
217                                          netbios_domain,
218                                          dns_name,
219                                          dns_domain,
220                                          &ans->ntlmssp_state);
221         if (!NT_STATUS_IS_OK(nt_status)) {
222                 return nt_status;
223         }
224
225         nt_status = make_auth_context_subsystem(&auth_context);
226         if (!NT_STATUS_IS_OK(nt_status)) {
227                 return nt_status;
228         }
229         ans->auth_context = talloc_steal(ans, auth_context);
230
231         ans->ntlmssp_state->callback_private = ans;
232         ans->ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge;
233         ans->ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge;
234         ans->ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge;
235         ans->ntlmssp_state->check_password = auth_ntlmssp_check_password;
236
237         talloc_set_destructor((TALLOC_CTX *)ans, auth_ntlmssp_state_destructor);
238
239         *auth_ntlmssp_state = ans;
240         return NT_STATUS_OK;
241 }
242
243 static int auth_ntlmssp_state_destructor(void *ptr)
244 {
245         struct auth_ntlmssp_state *ans;
246
247         ans = talloc_get_type(ptr, struct auth_ntlmssp_state);
248
249         TALLOC_FREE(ans->server_info);
250         TALLOC_FREE(ans->ntlmssp_state);
251         return 0;
252 }