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"
29 NTSTATUS
auth3_generate_session_info(struct auth4_context
*auth_context
,
31 void *server_returned_info
,
32 const char *original_user_name
,
33 uint32_t session_info_flags
,
34 struct auth_session_info
**session_info
)
36 struct auth_user_info_dc
*user_info
= NULL
;
37 struct auth_serversupplied_info
*server_info
= NULL
;
41 * This is a hack, some callers...
43 * Some callers pass auth_user_info_dc, the SCHANNEL and
44 * NCALRPC_AS_SYSTEM gensec modules.
46 * While the reset passes auth3_check_password() returned.
48 user_info
= talloc_get_type(server_returned_info
,
49 struct auth_user_info_dc
);
50 if (user_info
!= NULL
) {
51 const struct dom_sid
*sid
;
55 * This should only be called from SCHANNEL or NCALRPC_AS_SYSTEM
57 if (user_info
->num_sids
!= 1) {
58 return NT_STATUS_INTERNAL_ERROR
;
60 sid
= &user_info
->sids
[PRIMARY_USER_SID_INDEX
];
62 cmp
= dom_sid_compare(sid
, &global_sid_System
);
64 return make_session_info_system(mem_ctx
, session_info
);
67 cmp
= dom_sid_compare(sid
, &global_sid_Anonymous
);
69 return make_session_info_anonymous(mem_ctx
, session_info
);
72 return NT_STATUS_INTERNAL_ERROR
;
75 server_info
= talloc_get_type_abort(server_returned_info
,
76 struct auth_serversupplied_info
);
77 nt_status
= create_local_token(mem_ctx
,
82 if (!NT_STATUS_IS_OK(nt_status
)) {
83 DEBUG(10, ("create_local_token failed: %s\n",
84 nt_errstr(nt_status
)));
92 * Return the challenge as determined by the authentication subsystem
93 * @return an 8 byte random challenge
96 NTSTATUS
auth3_get_challenge(struct auth4_context
*auth4_context
,
99 struct auth_context
*auth_context
= talloc_get_type_abort(auth4_context
->private_data
,
100 struct auth_context
);
101 auth_get_ntlm_challenge(auth_context
, chal
);
106 * NTLM2 authentication modifies the effective challenge,
107 * @param challenge The new challenge value
109 NTSTATUS
auth3_set_challenge(struct auth4_context
*auth4_context
, const uint8_t *chal
,
110 const char *challenge_set_by
)
112 struct auth_context
*auth_context
= talloc_get_type_abort(auth4_context
->private_data
,
113 struct auth_context
);
115 auth_context
->challenge
= data_blob_talloc(auth_context
,
117 NT_STATUS_HAVE_NO_MEMORY(auth_context
->challenge
.data
);
119 auth_context
->challenge_set_by
= talloc_strdup(auth_context
, challenge_set_by
);
120 NT_STATUS_HAVE_NO_MEMORY(auth_context
->challenge_set_by
);
122 DEBUG(5, ("auth_context challenge set by %s\n", auth_context
->challenge_set_by
));
123 DEBUG(5, ("challenge is: \n"));
124 dump_data(5, auth_context
->challenge
.data
, auth_context
->challenge
.length
);
129 * Check the password on an NTLMSSP login.
131 * Return the session keys used on the connection.
134 struct auth3_check_password_state
{
135 uint8_t authoritative
;
137 DATA_BLOB nt_session_key
;
138 DATA_BLOB lm_session_key
;
141 struct tevent_req
*auth3_check_password_send(
143 struct tevent_context
*ev
,
144 struct auth4_context
*auth4_context
,
145 const struct auth_usersupplied_info
*user_info
)
147 struct tevent_req
*req
= NULL
;
148 struct auth3_check_password_state
*state
= NULL
;
149 struct auth_context
*auth_context
= talloc_get_type_abort(
150 auth4_context
->private_data
, struct auth_context
);
151 struct auth_usersupplied_info
*mapped_user_info
= NULL
;
152 struct auth_serversupplied_info
*server_info
= NULL
;
153 char *sanitized_username
= NULL
;
155 bool username_was_mapped
;
157 req
= tevent_req_create(
158 mem_ctx
, &state
, struct auth3_check_password_state
);
164 * Be authoritative by default.
166 state
->authoritative
= 1;
168 /* The client has given us its machine name (which we only get over NBT transport).
169 We need to possibly reload smb.conf if smb.conf includes depend on the machine name. */
171 set_remote_machine_name(user_info
->workstation_name
, True
);
173 nt_status
= make_user_info_map(talloc_tos(),
175 user_info
->client
.account_name
,
176 user_info
->client
.domain_name
,
177 user_info
->workstation_name
,
178 user_info
->remote_host
,
179 user_info
->local_host
,
180 user_info
->service_description
,
181 user_info
->password
.response
.lanman
.data
? &user_info
->password
.response
.lanman
: NULL
,
182 user_info
->password
.response
.nt
.data
? &user_info
->password
.response
.nt
: NULL
,
184 AUTH_PASSWORD_RESPONSE
);
186 if (tevent_req_nterror(req
, nt_status
)) {
187 return tevent_req_post(req
, ev
);
190 mapped_user_info
->logon_parameters
= user_info
->logon_parameters
;
192 mapped_user_info
->flags
= user_info
->flags
;
194 sanitized_username
= talloc_alpha_strcpy(
196 user_info
->client
.account_name
,
197 SAFE_NETBIOS_CHARS
"$");
198 if (sanitized_username
== NULL
) {
199 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
200 return tevent_req_post(req
, ev
);
203 nt_status
= auth_check_ntlm_password(state
,
207 &state
->authoritative
);
209 if (!NT_STATUS_IS_OK(nt_status
)) {
210 DBG_INFO("Checking NTLMSSP password for %s\\%s failed: "
211 "%s, authoritative=%"PRIu8
"\n",
212 user_info
->client
.domain_name
,
213 user_info
->client
.account_name
,
214 nt_errstr(nt_status
),
215 state
->authoritative
);
218 username_was_mapped
= mapped_user_info
->was_mapped
;
220 TALLOC_FREE(mapped_user_info
);
222 if (!NT_STATUS_IS_OK(nt_status
)) {
223 nt_status
= do_map_to_guest_server_info(
226 user_info
->client
.account_name
,
227 user_info
->client
.domain_name
,
229 if (!tevent_req_nterror(req
, nt_status
)) {
230 state
->authoritative
= 1;
232 /* setup the string used by %U */
233 set_current_user_info(
235 server_info
->unix_name
,
236 server_info
->info3
->base
.logon_domain
.string
);
238 lp_load_with_shares(get_dyn_CONFIGFILE());
240 tevent_req_done(req
);
242 state
->server_info
= server_info
;
243 return tevent_req_post(req
, ev
);
246 server_info
->nss_token
|= username_was_mapped
;
248 /* setup the string used by %U */
249 set_current_user_info(sanitized_username
,
250 server_info
->unix_name
,
251 server_info
->info3
->base
.logon_domain
.string
);
253 lp_load_with_shares(get_dyn_CONFIGFILE());
255 /* Clear out the session keys, and pass them to the caller.
256 * They will not be used in this form again - instead the
257 * NTLMSSP code will decide on the final correct session key,
258 * and supply it to create_local_token() */
260 DBG_DEBUG("Got NT session key of length %zu\n",
261 server_info
->session_key
.length
);
262 state
->nt_session_key
= (DATA_BLOB
) {
264 state
, &server_info
->session_key
.data
),
265 .length
= server_info
->session_key
.length
,
267 server_info
->session_key
= data_blob_null
;
269 DBG_DEBUG("Got LM session key of length %zu\n",
270 server_info
->lm_session_key
.length
);
271 state
->lm_session_key
= (DATA_BLOB
) {
273 state
, &server_info
->lm_session_key
.data
),
274 .length
= server_info
->lm_session_key
.length
,
276 server_info
->lm_session_key
= data_blob_null
;
278 state
->server_info
= server_info
;
280 tevent_req_done(req
);
281 return tevent_req_post(req
, ev
);
284 NTSTATUS
auth3_check_password_recv(struct tevent_req
*req
,
286 uint8_t *pauthoritative
,
287 void **server_returned_info
,
288 DATA_BLOB
*nt_session_key
,
289 DATA_BLOB
*lm_session_key
)
291 struct auth3_check_password_state
*state
= tevent_req_data(
292 req
, struct auth3_check_password_state
);
295 if (pauthoritative
!= NULL
) {
296 *pauthoritative
= state
->authoritative
;
299 if (tevent_req_is_nterror(req
, &status
)) {
303 if (server_returned_info
!= NULL
) {
304 *server_returned_info
= talloc_move(
305 mem_ctx
, &state
->server_info
);
307 if (nt_session_key
!= NULL
) {
308 *nt_session_key
= (DATA_BLOB
) {
310 mem_ctx
, &state
->nt_session_key
.data
),
311 .length
= state
->nt_session_key
.length
,
314 if (lm_session_key
!= NULL
) {
315 *lm_session_key
= (DATA_BLOB
) {
317 mem_ctx
, &state
->lm_session_key
.data
),
318 .length
= state
->lm_session_key
.length
,