2 Unix SMB/Netbios implementation.
4 handle NLTMSSP, server side
6 Copyright (C) Andrew Tridgell 2001
7 Copyright (C) Andrew Bartlett 2001-2005,2011
8 Copyright (C) Stefan Metzmacher 2005
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "libcli/security/security.h"
27 #include "lib/util/tevent_ntstatus.h"
28 #include "source3/lib/substitute.h"
30 NTSTATUS
auth3_generate_session_info(struct auth4_context
*auth_context
,
32 void *server_returned_info
,
33 const char *original_user_name
,
34 uint32_t session_info_flags
,
35 struct auth_session_info
**session_info
)
37 struct auth_user_info_dc
*user_info
= NULL
;
38 struct auth_serversupplied_info
*server_info
= NULL
;
42 * This is a hack, some callers...
44 * Some callers pass auth_user_info_dc, the SCHANNEL and
45 * NCALRPC_AS_SYSTEM gensec modules.
47 * While the rest passes auth3_check_password() returned.
49 user_info
= talloc_get_type(server_returned_info
,
50 struct auth_user_info_dc
);
51 if (user_info
!= NULL
) {
52 const struct dom_sid
*sid
;
56 * This should only be called from SCHANNEL or NCALRPC_AS_SYSTEM
58 if (user_info
->num_sids
!= 1) {
59 return NT_STATUS_INTERNAL_ERROR
;
61 sid
= &user_info
->sids
[PRIMARY_USER_SID_INDEX
].sid
;
63 cmp
= dom_sid_compare(sid
, &global_sid_System
);
65 return make_session_info_system(mem_ctx
, session_info
);
68 cmp
= dom_sid_compare(sid
, &global_sid_Anonymous
);
70 return make_session_info_anonymous(mem_ctx
, session_info
);
73 return NT_STATUS_INTERNAL_ERROR
;
76 server_info
= talloc_get_type_abort(server_returned_info
,
77 struct auth_serversupplied_info
);
78 nt_status
= create_local_token(mem_ctx
,
83 if (!NT_STATUS_IS_OK(nt_status
)) {
84 DEBUG(10, ("create_local_token failed: %s\n",
85 nt_errstr(nt_status
)));
93 * Return the challenge as determined by the authentication subsystem
94 * @return an 8 byte random challenge
97 NTSTATUS
auth3_get_challenge(struct auth4_context
*auth4_context
,
100 struct auth_context
*auth_context
= talloc_get_type_abort(auth4_context
->private_data
,
101 struct auth_context
);
102 auth_get_ntlm_challenge(auth_context
, chal
);
107 * NTLM2 authentication modifies the effective challenge,
108 * @param challenge The new challenge value
110 NTSTATUS
auth3_set_challenge(struct auth4_context
*auth4_context
, const uint8_t *chal
,
111 const char *challenge_set_by
)
113 struct auth_context
*auth_context
= talloc_get_type_abort(auth4_context
->private_data
,
114 struct auth_context
);
117 ok
= auth3_context_set_challenge(auth_context
, chal
, challenge_set_by
);
120 * This can only fail for ENOMEM
122 return NT_STATUS_NO_MEMORY
;
125 DEBUG(5, ("auth_context challenge set by %s\n", auth_context
->challenge_set_by
));
126 DEBUG(5, ("challenge is: \n"));
127 dump_data(5, auth_context
->challenge
.data
, auth_context
->challenge
.length
);
132 * Check the password on an NTLMSSP login.
134 * Return the session keys used on the connection.
137 struct auth3_check_password_state
{
138 uint8_t authoritative
;
140 DATA_BLOB nt_session_key
;
141 DATA_BLOB lm_session_key
;
144 struct tevent_req
*auth3_check_password_send(
146 struct tevent_context
*ev
,
147 struct auth4_context
*auth4_context
,
148 const struct auth_usersupplied_info
*user_info
)
150 struct tevent_req
*req
= NULL
;
151 struct auth3_check_password_state
*state
= NULL
;
152 struct auth_context
*auth_context
= talloc_get_type_abort(
153 auth4_context
->private_data
, struct auth_context
);
154 struct auth_usersupplied_info
*mapped_user_info
= NULL
;
155 struct auth_serversupplied_info
*server_info
= NULL
;
156 char *sanitized_username
= NULL
;
158 bool username_was_mapped
;
160 req
= tevent_req_create(
161 mem_ctx
, &state
, struct auth3_check_password_state
);
167 * Be authoritative by default.
169 state
->authoritative
= 1;
171 /* The client has given us its machine name (which we only get over NBT transport).
172 We need to possibly reload smb.conf if smb.conf includes depend on the machine name. */
174 set_remote_machine_name(user_info
->workstation_name
, True
);
176 nt_status
= make_user_info_map(talloc_tos(),
178 user_info
->client
.account_name
,
179 user_info
->client
.domain_name
,
180 user_info
->workstation_name
,
181 user_info
->remote_host
,
182 user_info
->local_host
,
183 user_info
->service_description
,
184 user_info
->password
.response
.lanman
.data
? &user_info
->password
.response
.lanman
: NULL
,
185 user_info
->password
.response
.nt
.data
? &user_info
->password
.response
.nt
: NULL
,
187 AUTH_PASSWORD_RESPONSE
);
189 if (tevent_req_nterror(req
, nt_status
)) {
190 return tevent_req_post(req
, ev
);
193 mapped_user_info
->logon_parameters
= user_info
->logon_parameters
;
195 mapped_user_info
->flags
= user_info
->flags
;
197 sanitized_username
= talloc_alpha_strcpy(
199 user_info
->client
.account_name
,
200 SAFE_NETBIOS_CHARS
"$");
201 if (sanitized_username
== NULL
) {
202 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
203 return tevent_req_post(req
, ev
);
206 nt_status
= auth_check_ntlm_password(state
,
210 &state
->authoritative
);
212 if (!NT_STATUS_IS_OK(nt_status
)) {
213 DBG_INFO("Checking NTLMSSP password for %s\\%s failed: "
214 "%s, authoritative=%"PRIu8
"\n",
215 user_info
->client
.domain_name
,
216 user_info
->client
.account_name
,
217 nt_errstr(nt_status
),
218 state
->authoritative
);
221 username_was_mapped
= mapped_user_info
->was_mapped
;
223 TALLOC_FREE(mapped_user_info
);
225 if (!NT_STATUS_IS_OK(nt_status
)) {
226 nt_status
= do_map_to_guest_server_info(
229 user_info
->client
.account_name
,
230 user_info
->client
.domain_name
,
232 if (!tevent_req_nterror(req
, nt_status
)) {
233 state
->authoritative
= 1;
235 /* setup the string used by %U */
236 set_current_user_info(
238 server_info
->unix_name
,
239 server_info
->info3
->base
.logon_domain
.string
);
241 lp_load_with_shares(get_dyn_CONFIGFILE());
243 tevent_req_done(req
);
245 state
->server_info
= server_info
;
246 return tevent_req_post(req
, ev
);
249 server_info
->nss_token
|= username_was_mapped
;
251 /* setup the string used by %U */
252 set_current_user_info(sanitized_username
,
253 server_info
->unix_name
,
254 server_info
->info3
->base
.logon_domain
.string
);
256 lp_load_with_shares(get_dyn_CONFIGFILE());
258 /* Clear out the session keys, and pass them to the caller.
259 * They will not be used in this form again - instead the
260 * NTLMSSP code will decide on the final correct session key,
261 * and supply it to create_local_token() */
263 DBG_DEBUG("Got NT session key of length %zu\n",
264 server_info
->session_key
.length
);
265 state
->nt_session_key
= (DATA_BLOB
) {
267 state
, &server_info
->session_key
.data
),
268 .length
= server_info
->session_key
.length
,
270 server_info
->session_key
= data_blob_null
;
272 DBG_DEBUG("Got LM session key of length %zu\n",
273 server_info
->lm_session_key
.length
);
274 state
->lm_session_key
= (DATA_BLOB
) {
276 state
, &server_info
->lm_session_key
.data
),
277 .length
= server_info
->lm_session_key
.length
,
279 server_info
->lm_session_key
= data_blob_null
;
281 state
->server_info
= server_info
;
283 tevent_req_done(req
);
284 return tevent_req_post(req
, ev
);
287 NTSTATUS
auth3_check_password_recv(struct tevent_req
*req
,
289 uint8_t *pauthoritative
,
290 void **server_returned_info
,
291 DATA_BLOB
*nt_session_key
,
292 DATA_BLOB
*lm_session_key
)
294 struct auth3_check_password_state
*state
= tevent_req_data(
295 req
, struct auth3_check_password_state
);
298 if (pauthoritative
!= NULL
) {
299 *pauthoritative
= state
->authoritative
;
302 if (tevent_req_is_nterror(req
, &status
)) {
306 if (server_returned_info
!= NULL
) {
307 *server_returned_info
= talloc_move(
308 mem_ctx
, &state
->server_info
);
310 if (nt_session_key
!= NULL
) {
311 *nt_session_key
= (DATA_BLOB
) {
313 mem_ctx
, &state
->nt_session_key
.data
),
314 .length
= state
->nt_session_key
.length
,
317 if (lm_session_key
!= NULL
) {
318 *lm_session_key
= (DATA_BLOB
) {
320 mem_ctx
, &state
->lm_session_key
.data
),
321 .length
= state
->lm_session_key
.length
,