s3:smbd: use PROTOCOL_SMB2_02 instead PROTOCOL_SMB2
[Samba/gebeck_regimport.git] / source3 / smbd / sesssetup.c
blob74d9e1cebf3e05f7d3a39079f8e9c12bd025018c
1 /*
2 Unix SMB/CIFS implementation.
3 handle SMBsessionsetup
4 Copyright (C) Andrew Tridgell 1998-2001
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
7 Copyright (C) Luke Howard 2003
8 Copyright (C) Volker Lendecke 2007
9 Copyright (C) Jeremy Allison 2007
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "smbd/smbd.h"
28 #include "smbd/globals.h"
29 #include "../libcli/auth/spnego.h"
30 #include "../libcli/auth/ntlmssp.h"
31 #include "ntlmssp_wrap.h"
32 #include "../librpc/gen_ndr/krb5pac.h"
33 #include "libads/kerberos_proto.h"
34 #include "../lib/util/asn1.h"
35 #include "auth.h"
36 #include "messages.h"
37 #include "smbprofile.h"
39 /* For split krb5 SPNEGO blobs. */
40 struct pending_auth_data {
41 struct pending_auth_data *prev, *next;
42 uint16 vuid; /* Tag for this entry. */
43 uint16 smbpid; /* Alternate tag for this entry. */
44 size_t needed_len;
45 DATA_BLOB partial_data;
49 on a logon error possibly map the error to success if "map to guest"
50 is set approriately
52 NTSTATUS do_map_to_guest(NTSTATUS status,
53 struct auth_serversupplied_info **server_info,
54 const char *user, const char *domain)
56 user = user ? user : "";
57 domain = domain ? domain : "";
59 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
60 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
61 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
62 DEBUG(3,("No such user %s [%s] - using guest account\n",
63 user, domain));
64 status = make_server_info_guest(NULL, server_info);
68 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
69 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
70 DEBUG(3,("Registered username %s for guest access\n",
71 user));
72 status = make_server_info_guest(NULL, server_info);
76 return status;
79 /****************************************************************************
80 Add the standard 'Samba' signature to the end of the session setup.
81 ****************************************************************************/
83 static int push_signature(uint8 **outbuf)
85 char *lanman;
86 int result, tmp;
88 result = 0;
90 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
92 if (tmp == -1) return -1;
93 result += tmp;
95 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
96 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
97 SAFE_FREE(lanman);
99 else {
100 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
103 if (tmp == -1) return -1;
104 result += tmp;
106 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
108 if (tmp == -1) return -1;
109 result += tmp;
111 return result;
114 /****************************************************************************
115 Send a security blob via a session setup reply.
116 ****************************************************************************/
118 static void reply_sesssetup_blob(struct smb_request *req,
119 DATA_BLOB blob,
120 NTSTATUS nt_status)
122 if (!NT_STATUS_IS_OK(nt_status) &&
123 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
124 reply_nterror(req, nt_status_squash(nt_status));
125 return;
128 nt_status = nt_status_squash(nt_status);
129 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
130 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
131 SSVAL(req->outbuf, smb_vwv3, blob.length);
133 if ((message_push_blob(&req->outbuf, blob) == -1)
134 || (push_signature(&req->outbuf) == -1)) {
135 reply_nterror(req, NT_STATUS_NO_MEMORY);
139 /****************************************************************************
140 Do a 'guest' logon, getting back the
141 ****************************************************************************/
143 static NTSTATUS check_guest_password(const struct tsocket_address *remote_address,
144 struct auth_serversupplied_info **server_info)
146 struct auth_context *auth_context;
147 struct auth_usersupplied_info *user_info = NULL;
149 NTSTATUS nt_status;
150 static unsigned char chal[8] = { 0, };
152 DEBUG(3,("Got anonymous request\n"));
154 nt_status = make_auth_context_fixed(talloc_tos(), &auth_context, chal);
155 if (!NT_STATUS_IS_OK(nt_status)) {
156 return nt_status;
159 if (!make_user_info_guest(remote_address, &user_info)) {
160 TALLOC_FREE(auth_context);
161 return NT_STATUS_NO_MEMORY;
164 nt_status = auth_context->check_ntlm_password(auth_context,
165 user_info,
166 server_info);
167 TALLOC_FREE(auth_context);
168 free_user_info(&user_info);
169 return nt_status;
173 #ifdef HAVE_KRB5
175 #if 0
176 /* Experiment that failed. See "only happens with a KDC" comment below. */
177 /****************************************************************************
178 Cerate a clock skew error blob for a Windows client.
179 ****************************************************************************/
181 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
183 krb5_context context = NULL;
184 krb5_error_code kerr = 0;
185 krb5_data reply;
186 krb5_principal host_princ = NULL;
187 char *host_princ_s = NULL;
188 bool ret = False;
190 *pblob_out = data_blob_null;
192 initialize_krb5_error_table();
193 kerr = krb5_init_context(&context);
194 if (kerr) {
195 return False;
197 /* Create server principal. */
198 asprintf(&host_princ_s, "%s$@%s", lp_netbios_name(), lp_realm());
199 if (!host_princ_s) {
200 goto out;
202 strlower_m(host_princ_s);
204 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
205 if (kerr) {
206 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
207 "for name %s: Error %s\n",
208 host_princ_s, error_message(kerr) ));
209 goto out;
212 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
213 host_princ, &reply);
214 if (kerr) {
215 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
216 "failed: Error %s\n",
217 error_message(kerr) ));
218 goto out;
221 *pblob_out = data_blob(reply.data, reply.length);
222 kerberos_free_data_contents(context,&reply);
223 ret = True;
225 out:
227 if (host_princ_s) {
228 SAFE_FREE(host_princ_s);
230 if (host_princ) {
231 krb5_free_principal(context, host_princ);
233 krb5_free_context(context);
234 return ret;
236 #endif
238 /****************************************************************************
239 Reply to a session setup spnego negotiate packet for kerberos.
240 ****************************************************************************/
242 static void reply_spnego_kerberos(struct smb_request *req,
243 DATA_BLOB *secblob,
244 const char *mechOID,
245 uint16 vuid,
246 bool *p_invalidate_vuid)
248 TALLOC_CTX *mem_ctx;
249 DATA_BLOB ticket;
250 struct passwd *pw;
251 int sess_vuid = req->vuid;
252 NTSTATUS ret = NT_STATUS_OK;
253 DATA_BLOB ap_rep, ap_rep_wrapped, response;
254 struct auth_serversupplied_info *session_info = NULL;
255 DATA_BLOB session_key = data_blob_null;
256 uint8 tok_id[2];
257 DATA_BLOB nullblob = data_blob_null;
258 bool map_domainuser_to_guest = False;
259 bool username_was_mapped;
260 struct PAC_LOGON_INFO *logon_info = NULL;
261 struct smbd_server_connection *sconn = req->sconn;
262 char *principal;
263 char *user;
264 char *domain;
265 char *real_username;
267 ZERO_STRUCT(ticket);
268 ZERO_STRUCT(ap_rep);
269 ZERO_STRUCT(ap_rep_wrapped);
270 ZERO_STRUCT(response);
272 /* Normally we will always invalidate the intermediate vuid. */
273 *p_invalidate_vuid = True;
275 mem_ctx = talloc_init("reply_spnego_kerberos");
276 if (mem_ctx == NULL) {
277 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
278 return;
281 if (!spnego_parse_krb5_wrap(mem_ctx, *secblob, &ticket, tok_id)) {
282 talloc_destroy(mem_ctx);
283 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
284 return;
287 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
288 &principal, &logon_info, &ap_rep,
289 &session_key, True);
291 data_blob_free(&ticket);
293 if (!NT_STATUS_IS_OK(ret)) {
294 #if 0
295 /* Experiment that failed.
296 * See "only happens with a KDC" comment below. */
298 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
301 * Windows in this case returns
302 * NT_STATUS_MORE_PROCESSING_REQUIRED
303 * with a negTokenTarg blob containing an krb5_error
304 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
305 * The client then fixes its clock and continues rather
306 * than giving an error. JRA.
307 * -- Looks like this only happens with a KDC. JRA.
310 bool ok = make_krb5_skew_error(&ap_rep);
311 if (!ok) {
312 talloc_destroy(mem_ctx);
313 return ERROR_NT(nt_status_squash(
314 NT_STATUS_LOGON_FAILURE));
316 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
317 TOK_ID_KRB_ERROR);
318 response = spnego_gen_auth_response(&ap_rep_wrapped,
319 ret, OID_KERBEROS5_OLD);
320 reply_sesssetup_blob(conn, inbuf, outbuf, response,
321 NT_STATUS_MORE_PROCESSING_REQUIRED);
324 * In this one case we don't invalidate the
325 * intermediate vuid as we're expecting the client
326 * to re-use it for the next sessionsetupX packet. JRA.
329 *p_invalidate_vuid = False;
331 data_blob_free(&ap_rep);
332 data_blob_free(&ap_rep_wrapped);
333 data_blob_free(&response);
334 talloc_destroy(mem_ctx);
335 return -1; /* already replied */
337 #else
338 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
339 ret = NT_STATUS_LOGON_FAILURE;
341 #endif
342 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
343 nt_errstr(ret)));
344 talloc_destroy(mem_ctx);
345 reply_nterror(req, nt_status_squash(ret));
346 return;
349 ret = get_user_from_kerberos_info(talloc_tos(),
350 sconn->remote_hostname,
351 principal, logon_info,
352 &username_was_mapped,
353 &map_domainuser_to_guest,
354 &user, &domain,
355 &real_username, &pw);
356 if (!NT_STATUS_IS_OK(ret)) {
357 data_blob_free(&ap_rep);
358 data_blob_free(&session_key);
359 talloc_destroy(mem_ctx);
360 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
361 return;
364 /* save the PAC data if we have it */
365 if (logon_info) {
366 netsamlogon_cache_store(user, &logon_info->info3);
369 /* setup the string used by %U */
370 sub_set_smb_name(real_username);
372 /* reload services so that the new %U is taken into account */
373 reload_services(sconn->msg_ctx, sconn->sock, True);
375 ret = make_session_info_krb5(mem_ctx,
376 user, domain, real_username, pw,
377 logon_info, map_domainuser_to_guest,
378 username_was_mapped,
379 &session_key,
380 &session_info);
381 data_blob_free(&session_key);
382 if (!NT_STATUS_IS_OK(ret)) {
383 DEBUG(1, ("make_server_info_krb5 failed!\n"));
384 data_blob_free(&ap_rep);
385 TALLOC_FREE(mem_ctx);
386 reply_nterror(req, nt_status_squash(ret));
387 return;
390 if (!is_partial_auth_vuid(sconn, sess_vuid)) {
391 sess_vuid = register_initial_vuid(sconn);
394 /* register_existing_vuid keeps the server info */
395 /* register_existing_vuid takes ownership of session_key on success,
396 * no need to free after this on success. A better interface would copy
397 * it.... */
399 sess_vuid = register_existing_vuid(sconn, sess_vuid,
400 session_info, nullblob, user);
402 reply_outbuf(req, 4, 0);
403 SSVAL(req->outbuf,smb_uid,sess_vuid);
405 if (sess_vuid == UID_FIELD_INVALID ) {
406 ret = NT_STATUS_LOGON_FAILURE;
407 } else {
408 /* current_user_info is changed on new vuid */
409 reload_services(sconn->msg_ctx, sconn->sock, True);
411 SSVAL(req->outbuf, smb_vwv3, 0);
413 if (session_info->guest) {
414 SSVAL(req->outbuf,smb_vwv2,1);
417 SSVAL(req->outbuf, smb_uid, sess_vuid);
419 /* Successful logon. Keep this vuid. */
420 *p_invalidate_vuid = False;
423 /* wrap that up in a nice GSS-API wrapping */
424 if (NT_STATUS_IS_OK(ret)) {
425 ap_rep_wrapped = spnego_gen_krb5_wrap(talloc_tos(), ap_rep,
426 TOK_ID_KRB_AP_REP);
427 } else {
428 ap_rep_wrapped = data_blob_null;
430 response = spnego_gen_auth_response(talloc_tos(), &ap_rep_wrapped, ret,
431 mechOID);
432 reply_sesssetup_blob(req, response, ret);
434 data_blob_free(&ap_rep);
435 data_blob_free(&ap_rep_wrapped);
436 data_blob_free(&response);
437 TALLOC_FREE(mem_ctx);
440 #endif
442 /****************************************************************************
443 Send a session setup reply, wrapped in SPNEGO.
444 Get vuid and check first.
445 End the NTLMSSP exchange context if we are OK/complete fail
446 This should be split into two functions, one to handle each
447 leg of the NTLM auth steps.
448 ***************************************************************************/
450 static void reply_spnego_ntlmssp(struct smb_request *req,
451 uint16 vuid,
452 struct auth_ntlmssp_state **auth_ntlmssp_state,
453 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
454 const char *OID,
455 bool wrap)
457 bool do_invalidate = true;
458 DATA_BLOB response;
459 struct auth_serversupplied_info *session_info = NULL;
460 struct smbd_server_connection *sconn = req->sconn;
462 if (NT_STATUS_IS_OK(nt_status)) {
463 nt_status = auth_ntlmssp_steal_session_info(talloc_tos(),
464 (*auth_ntlmssp_state), &session_info);
465 } else {
466 /* Note that this session_info won't have a session
467 * key. But for map to guest, that's exactly the right
468 * thing - we can't reasonably guess the key the
469 * client wants, as the password was wrong */
470 nt_status = do_map_to_guest(nt_status,
471 &session_info,
472 auth_ntlmssp_get_username(*auth_ntlmssp_state),
473 auth_ntlmssp_get_domain(*auth_ntlmssp_state));
476 reply_outbuf(req, 4, 0);
478 SSVAL(req->outbuf, smb_uid, vuid);
480 if (NT_STATUS_IS_OK(nt_status)) {
481 DATA_BLOB nullblob = data_blob_null;
483 if (!is_partial_auth_vuid(sconn, vuid)) {
484 nt_status = NT_STATUS_LOGON_FAILURE;
485 goto out;
488 /* register_existing_vuid keeps the server info */
489 if (register_existing_vuid(sconn, vuid,
490 session_info, nullblob,
491 auth_ntlmssp_get_username(*auth_ntlmssp_state)) !=
492 vuid) {
493 /* The problem is, *auth_ntlmssp_state points
494 * into the vuser this will have
495 * talloc_free()'ed in
496 * register_existing_vuid() */
497 do_invalidate = false;
498 nt_status = NT_STATUS_LOGON_FAILURE;
499 goto out;
502 /* current_user_info is changed on new vuid */
503 reload_services(sconn->msg_ctx, sconn->sock, True);
505 SSVAL(req->outbuf, smb_vwv3, 0);
507 if (session_info->guest) {
508 SSVAL(req->outbuf,smb_vwv2,1);
512 out:
514 if (wrap) {
515 response = spnego_gen_auth_response(talloc_tos(),
516 ntlmssp_blob,
517 nt_status, OID);
518 } else {
519 response = *ntlmssp_blob;
522 reply_sesssetup_blob(req, response, nt_status);
523 if (wrap) {
524 data_blob_free(&response);
527 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
528 and the other end, that we are not finished yet. */
530 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
531 /* NB. This is *NOT* an error case. JRA */
532 if (do_invalidate) {
533 TALLOC_FREE(*auth_ntlmssp_state);
534 if (!NT_STATUS_IS_OK(nt_status)) {
535 /* Kill the intermediate vuid */
536 invalidate_vuid(sconn, vuid);
542 /****************************************************************************
543 Is this a krb5 mechanism ?
544 ****************************************************************************/
546 NTSTATUS parse_spnego_mechanisms(TALLOC_CTX *ctx,
547 DATA_BLOB blob_in,
548 DATA_BLOB *pblob_out,
549 char **kerb_mechOID)
551 char *OIDs[ASN1_MAX_OIDS];
552 int i;
553 NTSTATUS ret = NT_STATUS_OK;
555 *kerb_mechOID = NULL;
557 /* parse out the OIDs and the first sec blob */
558 if (!spnego_parse_negTokenInit(ctx, blob_in, OIDs, NULL, pblob_out) ||
559 (OIDs[0] == NULL)) {
560 return NT_STATUS_LOGON_FAILURE;
563 /* only look at the first OID for determining the mechToken --
564 according to RFC2478, we should choose the one we want
565 and renegotiate, but i smell a client bug here..
567 Problem observed when connecting to a member (samba box)
568 of an AD domain as a user in a Samba domain. Samba member
569 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
570 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
571 NTLMSSP mechtoken. --jerry */
573 #ifdef HAVE_KRB5
574 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
575 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
576 *kerb_mechOID = talloc_strdup(ctx, OIDs[0]);
577 if (*kerb_mechOID == NULL) {
578 ret = NT_STATUS_NO_MEMORY;
581 #endif
583 for (i=0;OIDs[i];i++) {
584 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
585 talloc_free(OIDs[i]);
587 return ret;
590 /****************************************************************************
591 Fall back from krb5 to NTLMSSP.
592 ****************************************************************************/
594 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
595 uint16 vuid)
597 DATA_BLOB response;
599 reply_outbuf(req, 4, 0);
600 SSVAL(req->outbuf,smb_uid,vuid);
602 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
603 "but set to downgrade to NTLMSSP\n"));
605 response = spnego_gen_auth_response(talloc_tos(), NULL,
606 NT_STATUS_MORE_PROCESSING_REQUIRED,
607 OID_NTLMSSP);
608 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
609 data_blob_free(&response);
612 /****************************************************************************
613 Reply to a session setup spnego negotiate packet.
614 ****************************************************************************/
616 static void reply_spnego_negotiate(struct smb_request *req,
617 uint16 vuid,
618 DATA_BLOB blob1,
619 struct auth_ntlmssp_state **auth_ntlmssp_state)
621 DATA_BLOB secblob;
622 DATA_BLOB chal;
623 char *kerb_mech = NULL;
624 NTSTATUS status;
625 struct smbd_server_connection *sconn = req->sconn;
627 status = parse_spnego_mechanisms(talloc_tos(),
628 blob1, &secblob, &kerb_mech);
629 if (!NT_STATUS_IS_OK(status)) {
630 /* Kill the intermediate vuid */
631 invalidate_vuid(sconn, vuid);
632 reply_nterror(req, nt_status_squash(status));
633 return;
636 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
637 (unsigned long)secblob.length));
639 #ifdef HAVE_KRB5
640 if (kerb_mech && ((lp_security()==SEC_ADS) ||
641 USE_KERBEROS_KEYTAB) ) {
642 bool destroy_vuid = True;
643 reply_spnego_kerberos(req, &secblob, kerb_mech,
644 vuid, &destroy_vuid);
645 data_blob_free(&secblob);
646 if (destroy_vuid) {
647 /* Kill the intermediate vuid */
648 invalidate_vuid(sconn, vuid);
650 TALLOC_FREE(kerb_mech);
651 return;
653 #endif
655 TALLOC_FREE(*auth_ntlmssp_state);
657 if (kerb_mech) {
658 data_blob_free(&secblob);
659 /* The mechtoken is a krb5 ticket, but
660 * we need to fall back to NTLM. */
661 reply_spnego_downgrade_to_ntlmssp(req, vuid);
662 TALLOC_FREE(kerb_mech);
663 return;
666 status = auth_ntlmssp_start(sconn->remote_address,
667 auth_ntlmssp_state);
668 if (!NT_STATUS_IS_OK(status)) {
669 /* Kill the intermediate vuid */
670 invalidate_vuid(sconn, vuid);
671 reply_nterror(req, nt_status_squash(status));
672 return;
675 status = auth_ntlmssp_update(*auth_ntlmssp_state,
676 secblob, &chal);
678 data_blob_free(&secblob);
680 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
681 &chal, status, OID_NTLMSSP, true);
683 data_blob_free(&chal);
685 /* already replied */
686 return;
689 /****************************************************************************
690 Reply to a session setup spnego auth packet.
691 ****************************************************************************/
693 static void reply_spnego_auth(struct smb_request *req,
694 uint16 vuid,
695 DATA_BLOB blob1,
696 struct auth_ntlmssp_state **auth_ntlmssp_state)
698 DATA_BLOB auth = data_blob_null;
699 DATA_BLOB auth_reply = data_blob_null;
700 DATA_BLOB secblob = data_blob_null;
701 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
702 struct smbd_server_connection *sconn = req->sconn;
704 if (!spnego_parse_auth(talloc_tos(), blob1, &auth)) {
705 #if 0
706 file_save("auth.dat", blob1.data, blob1.length);
707 #endif
708 /* Kill the intermediate vuid */
709 invalidate_vuid(sconn, vuid);
711 reply_nterror(req, nt_status_squash(
712 NT_STATUS_LOGON_FAILURE));
713 return;
716 if (auth.data[0] == ASN1_APPLICATION(0)) {
717 /* Might be a second negTokenTarg packet */
718 char *kerb_mech = NULL;
720 status = parse_spnego_mechanisms(talloc_tos(),
721 auth, &secblob, &kerb_mech);
723 if (!NT_STATUS_IS_OK(status)) {
724 /* Kill the intermediate vuid */
725 invalidate_vuid(sconn, vuid);
726 reply_nterror(req, nt_status_squash(status));
727 return;
730 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
731 (unsigned long)secblob.length));
732 #ifdef HAVE_KRB5
733 if (kerb_mech && ((lp_security()==SEC_ADS) ||
734 USE_KERBEROS_KEYTAB)) {
735 bool destroy_vuid = True;
736 reply_spnego_kerberos(req, &secblob, kerb_mech,
737 vuid, &destroy_vuid);
738 data_blob_free(&secblob);
739 data_blob_free(&auth);
740 if (destroy_vuid) {
741 /* Kill the intermediate vuid */
742 invalidate_vuid(sconn, vuid);
744 TALLOC_FREE(kerb_mech);
745 return;
747 #endif
748 /* Can't blunder into NTLMSSP auth if we have
749 * a krb5 ticket. */
751 if (kerb_mech) {
752 /* Kill the intermediate vuid */
753 invalidate_vuid(sconn, vuid);
754 DEBUG(3,("reply_spnego_auth: network "
755 "misconfiguration, client sent us a "
756 "krb5 ticket and kerberos security "
757 "not enabled\n"));
758 reply_nterror(req, nt_status_squash(
759 NT_STATUS_LOGON_FAILURE));
760 TALLOC_FREE(kerb_mech);
764 /* If we get here it wasn't a negTokenTarg auth packet. */
765 data_blob_free(&secblob);
767 if (!*auth_ntlmssp_state) {
768 status = auth_ntlmssp_start(sconn->remote_address,
769 auth_ntlmssp_state);
770 if (!NT_STATUS_IS_OK(status)) {
771 /* Kill the intermediate vuid */
772 invalidate_vuid(sconn, vuid);
773 reply_nterror(req, nt_status_squash(status));
774 return;
778 status = auth_ntlmssp_update(*auth_ntlmssp_state,
779 auth, &auth_reply);
781 data_blob_free(&auth);
783 /* Don't send the mechid as we've already sent this (RFC4178). */
785 reply_spnego_ntlmssp(req, vuid,
786 auth_ntlmssp_state,
787 &auth_reply, status, NULL, true);
789 data_blob_free(&auth_reply);
791 /* and tell smbd that we have already replied to this packet */
792 return;
795 /****************************************************************************
796 Delete an entry on the list.
797 ****************************************************************************/
799 static void delete_partial_auth(struct smbd_server_connection *sconn,
800 struct pending_auth_data *pad)
802 if (!pad) {
803 return;
805 DLIST_REMOVE(sconn->smb1.pd_list, pad);
806 data_blob_free(&pad->partial_data);
807 SAFE_FREE(pad);
810 /****************************************************************************
811 Search for a partial SPNEGO auth fragment matching an smbpid.
812 ****************************************************************************/
814 static struct pending_auth_data *get_pending_auth_data(
815 struct smbd_server_connection *sconn,
816 uint16_t smbpid)
818 struct pending_auth_data *pad;
820 * NOTE: using the smbpid here is completely wrong...
821 * see [MS-SMB]
822 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
824 for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
825 if (pad->smbpid == smbpid) {
826 break;
829 return pad;
832 /****************************************************************************
833 Check the size of an SPNEGO blob. If we need more return
834 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
835 the blob to be more than 64k.
836 ****************************************************************************/
838 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
839 uint16 smbpid, uint16 vuid,
840 DATA_BLOB *pblob)
842 struct pending_auth_data *pad = NULL;
843 ASN1_DATA *data;
844 size_t needed_len = 0;
846 pad = get_pending_auth_data(sconn, smbpid);
848 /* Ensure we have some data. */
849 if (pblob->length == 0) {
850 /* Caller can cope. */
851 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
852 delete_partial_auth(sconn, pad);
853 return NT_STATUS_OK;
856 /* Were we waiting for more data ? */
857 if (pad) {
858 DATA_BLOB tmp_blob;
859 size_t copy_len = MIN(65536, pblob->length);
861 /* Integer wrap paranoia.... */
863 if (pad->partial_data.length + copy_len <
864 pad->partial_data.length ||
865 pad->partial_data.length + copy_len < copy_len) {
867 DEBUG(2,("check_spnego_blob_complete: integer wrap "
868 "pad->partial_data.length = %u, "
869 "copy_len = %u\n",
870 (unsigned int)pad->partial_data.length,
871 (unsigned int)copy_len ));
873 delete_partial_auth(sconn, pad);
874 return NT_STATUS_INVALID_PARAMETER;
877 DEBUG(10,("check_spnego_blob_complete: "
878 "pad->partial_data.length = %u, "
879 "pad->needed_len = %u, "
880 "copy_len = %u, "
881 "pblob->length = %u,\n",
882 (unsigned int)pad->partial_data.length,
883 (unsigned int)pad->needed_len,
884 (unsigned int)copy_len,
885 (unsigned int)pblob->length ));
887 tmp_blob = data_blob(NULL,
888 pad->partial_data.length + copy_len);
890 /* Concatenate the two (up to copy_len) bytes. */
891 memcpy(tmp_blob.data,
892 pad->partial_data.data,
893 pad->partial_data.length);
894 memcpy(tmp_blob.data + pad->partial_data.length,
895 pblob->data,
896 copy_len);
898 /* Replace the partial data. */
899 data_blob_free(&pad->partial_data);
900 pad->partial_data = tmp_blob;
901 ZERO_STRUCT(tmp_blob);
903 /* Are we done ? */
904 if (pblob->length >= pad->needed_len) {
905 /* Yes, replace pblob. */
906 data_blob_free(pblob);
907 *pblob = pad->partial_data;
908 ZERO_STRUCT(pad->partial_data);
909 delete_partial_auth(sconn, pad);
910 return NT_STATUS_OK;
913 /* Still need more data. */
914 pad->needed_len -= copy_len;
915 return NT_STATUS_MORE_PROCESSING_REQUIRED;
918 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
919 (pblob->data[0] != ASN1_CONTEXT(1))) {
920 /* Not something we can determine the
921 * length of.
923 return NT_STATUS_OK;
926 /* This is a new SPNEGO sessionsetup - see if
927 * the data given in this blob is enough.
930 data = asn1_init(NULL);
931 if (data == NULL) {
932 return NT_STATUS_NO_MEMORY;
935 asn1_load(data, *pblob);
936 if (asn1_start_tag(data, pblob->data[0])) {
937 /* asn1_start_tag checks if the given
938 length of the blob is enough to complete
939 the tag. If it returns true we know
940 there is nothing to do - the blob is
941 complete. */
942 asn1_free(data);
943 return NT_STATUS_OK;
946 if (data->nesting == NULL) {
947 /* Incorrect tag, allocation failed,
948 or reading the tag length failed.
949 Let the caller catch. */
950 asn1_free(data);
951 return NT_STATUS_OK;
954 /* Here we know asn1_start_tag() has set data->has_error to true.
955 asn1_tag_remaining() will have failed due to the given blob
956 being too short. We need to work out how short. */
958 /* Integer wrap paranoia.... */
960 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
961 data->nesting->taglen + data->nesting->start < data->nesting->start) {
963 DEBUG(2,("check_spnego_blob_complete: integer wrap "
964 "data.nesting->taglen = %u, "
965 "data.nesting->start = %u\n",
966 (unsigned int)data->nesting->taglen,
967 (unsigned int)data->nesting->start ));
969 asn1_free(data);
970 return NT_STATUS_INVALID_PARAMETER;
973 /* Total length of the needed asn1 is the tag length
974 * plus the current offset. */
976 needed_len = data->nesting->taglen + data->nesting->start;
977 asn1_free(data);
979 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
980 "pblob->length = %u\n",
981 (unsigned int)needed_len,
982 (unsigned int)pblob->length ));
984 if (needed_len <= pblob->length) {
985 /* Nothing to do - blob is complete. */
986 /* THIS SHOULD NOT HAPPEN - asn1_start_tag()
987 above should have caught this !!! */
988 DEBUG(0,("check_spnego_blob_complete: logic "
989 "error (needed_len = %u, "
990 "pblob->length = %u).\n",
991 (unsigned int)needed_len,
992 (unsigned int)pblob->length ));
993 return NT_STATUS_OK;
996 /* Refuse the blob if it's bigger than 64k. */
997 if (needed_len > 65536) {
998 DEBUG(2,("check_spnego_blob_complete: needed_len "
999 "too large (%u)\n",
1000 (unsigned int)needed_len ));
1001 return NT_STATUS_INVALID_PARAMETER;
1004 /* We must store this blob until complete. */
1005 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1006 return NT_STATUS_NO_MEMORY;
1008 pad->needed_len = needed_len - pblob->length;
1009 pad->partial_data = data_blob(pblob->data, pblob->length);
1010 if (pad->partial_data.data == NULL) {
1011 SAFE_FREE(pad);
1012 return NT_STATUS_NO_MEMORY;
1014 pad->smbpid = smbpid;
1015 pad->vuid = vuid;
1016 DLIST_ADD(sconn->smb1.pd_list, pad);
1018 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1021 /****************************************************************************
1022 Reply to a session setup command.
1023 conn POINTER CAN BE NULL HERE !
1024 ****************************************************************************/
1026 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1028 const uint8 *p;
1029 DATA_BLOB blob1;
1030 size_t bufrem;
1031 char *tmp;
1032 const char *native_os;
1033 const char *native_lanman;
1034 const char *primary_domain;
1035 const char *p2;
1036 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1037 enum remote_arch_types ra_type = get_remote_arch();
1038 int vuid = req->vuid;
1039 user_struct *vuser = NULL;
1040 NTSTATUS status = NT_STATUS_OK;
1041 uint16 smbpid = req->smbpid;
1042 struct smbd_server_connection *sconn = req->sconn;
1044 DEBUG(3,("Doing spnego session setup\n"));
1046 if (global_client_caps == 0) {
1047 global_client_caps = IVAL(req->vwv+10, 0);
1049 if (!(global_client_caps & CAP_STATUS32)) {
1050 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1055 p = req->buf;
1057 if (data_blob_len == 0) {
1058 /* an invalid request */
1059 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1060 return;
1063 bufrem = smbreq_bufrem(req, p);
1064 /* pull the spnego blob */
1065 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1067 #if 0
1068 file_save("negotiate.dat", blob1.data, blob1.length);
1069 #endif
1071 p2 = (const char *)req->buf + blob1.length;
1073 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1074 STR_TERMINATE);
1075 native_os = tmp ? tmp : "";
1077 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1078 STR_TERMINATE);
1079 native_lanman = tmp ? tmp : "";
1081 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1082 STR_TERMINATE);
1083 primary_domain = tmp ? tmp : "";
1085 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1086 native_os, native_lanman, primary_domain));
1088 if ( ra_type == RA_WIN2K ) {
1089 /* Vista sets neither the OS or lanman strings */
1091 if ( !strlen(native_os) && !strlen(native_lanman) )
1092 set_remote_arch(RA_VISTA);
1094 /* Windows 2003 doesn't set the native lanman string,
1095 but does set primary domain which is a bug I think */
1097 if ( !strlen(native_lanman) ) {
1098 ra_lanman_string( primary_domain );
1099 } else {
1100 ra_lanman_string( native_lanman );
1102 } else if ( ra_type == RA_VISTA ) {
1103 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
1104 set_remote_arch(RA_OSX);
1108 /* Did we get a valid vuid ? */
1109 if (!is_partial_auth_vuid(sconn, vuid)) {
1110 /* No, then try and see if this is an intermediate sessionsetup
1111 * for a large SPNEGO packet. */
1112 struct pending_auth_data *pad;
1113 pad = get_pending_auth_data(sconn, smbpid);
1114 if (pad) {
1115 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1116 "pending vuid %u\n",
1117 (unsigned int)pad->vuid ));
1118 vuid = pad->vuid;
1122 /* Do we have a valid vuid now ? */
1123 if (!is_partial_auth_vuid(sconn, vuid)) {
1124 /* No, start a new authentication setup. */
1125 vuid = register_initial_vuid(sconn);
1126 if (vuid == UID_FIELD_INVALID) {
1127 data_blob_free(&blob1);
1128 reply_nterror(req, nt_status_squash(
1129 NT_STATUS_INVALID_PARAMETER));
1130 return;
1134 vuser = get_partial_auth_user_struct(sconn, vuid);
1135 /* This MUST be valid. */
1136 if (!vuser) {
1137 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1140 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1141 * sessionsetup requests as the Windows limit on the security blob
1142 * field is 4k. Bug #4400. JRA.
1145 status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1146 if (!NT_STATUS_IS_OK(status)) {
1147 if (!NT_STATUS_EQUAL(status,
1148 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1149 /* Real error - kill the intermediate vuid */
1150 invalidate_vuid(sconn, vuid);
1152 data_blob_free(&blob1);
1153 reply_nterror(req, nt_status_squash(status));
1154 return;
1157 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1159 /* its a negTokenTarg packet */
1161 reply_spnego_negotiate(req, vuid, blob1,
1162 &vuser->auth_ntlmssp_state);
1163 data_blob_free(&blob1);
1164 return;
1167 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1169 /* its a auth packet */
1171 reply_spnego_auth(req, vuid, blob1,
1172 &vuser->auth_ntlmssp_state);
1173 data_blob_free(&blob1);
1174 return;
1177 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1178 DATA_BLOB chal;
1180 if (!vuser->auth_ntlmssp_state) {
1181 status = auth_ntlmssp_start(sconn->remote_address,
1182 &vuser->auth_ntlmssp_state);
1183 if (!NT_STATUS_IS_OK(status)) {
1184 /* Kill the intermediate vuid */
1185 invalidate_vuid(sconn, vuid);
1186 data_blob_free(&blob1);
1187 reply_nterror(req, nt_status_squash(status));
1188 return;
1192 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1193 blob1, &chal);
1195 data_blob_free(&blob1);
1197 reply_spnego_ntlmssp(req, vuid,
1198 &vuser->auth_ntlmssp_state,
1199 &chal, status, OID_NTLMSSP, false);
1200 data_blob_free(&chal);
1201 return;
1204 /* what sort of packet is this? */
1205 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1207 data_blob_free(&blob1);
1209 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1212 /****************************************************************************
1213 On new VC == 0, shutdown *all* old connections and users.
1214 It seems that only NT4.x does this. At W2K and above (XP etc.).
1215 a new session setup with VC==0 is ignored.
1216 ****************************************************************************/
1218 struct shutdown_state {
1219 const char *ip;
1220 struct messaging_context *msg_ctx;
1223 static int shutdown_other_smbds(const struct connections_key *key,
1224 const struct connections_data *crec,
1225 void *private_data)
1227 struct shutdown_state *state = (struct shutdown_state *)private_data;
1229 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
1230 server_id_str(talloc_tos(), &crec->pid), crec->addr));
1232 if (!process_exists(crec->pid)) {
1233 DEBUG(10, ("process does not exist\n"));
1234 return 0;
1237 if (procid_is_me(&crec->pid)) {
1238 DEBUG(10, ("It's me\n"));
1239 return 0;
1242 if (strcmp(state->ip, crec->addr) != 0) {
1243 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
1244 return 0;
1247 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
1248 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
1249 state->ip));
1251 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
1252 &data_blob_null);
1253 return 0;
1256 static void setup_new_vc_session(struct smbd_server_connection *sconn)
1258 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1259 "compatible we would close all old resources.\n"));
1260 #if 0
1261 conn_close_all();
1262 invalidate_all_vuids();
1263 #endif
1264 if (lp_reset_on_zero_vc()) {
1265 char *addr;
1266 struct shutdown_state state;
1268 addr = tsocket_address_inet_addr_string(
1269 sconn->remote_address, talloc_tos());
1270 if (addr == NULL) {
1271 return;
1273 state.ip = addr;
1274 state.msg_ctx = sconn->msg_ctx;
1275 connections_forall_read(shutdown_other_smbds, &state);
1276 TALLOC_FREE(addr);
1280 /****************************************************************************
1281 Reply to a session setup command.
1282 ****************************************************************************/
1284 void reply_sesssetup_and_X(struct smb_request *req)
1286 int sess_vuid;
1287 int smb_bufsize;
1288 DATA_BLOB lm_resp;
1289 DATA_BLOB nt_resp;
1290 DATA_BLOB plaintext_password;
1291 char *tmp;
1292 const char *user;
1293 fstring sub_user; /* Sanitised username for substituion */
1294 const char *domain;
1295 const char *native_os;
1296 const char *native_lanman;
1297 const char *primary_domain;
1298 struct auth_usersupplied_info *user_info = NULL;
1299 struct auth_serversupplied_info *server_info = NULL;
1300 struct auth_serversupplied_info *session_info = NULL;
1301 uint16 smb_flag2 = req->flags2;
1303 NTSTATUS nt_status;
1304 struct smbd_server_connection *sconn = req->sconn;
1306 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1308 START_PROFILE(SMBsesssetupX);
1310 ZERO_STRUCT(lm_resp);
1311 ZERO_STRUCT(nt_resp);
1312 ZERO_STRUCT(plaintext_password);
1314 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1316 /* a SPNEGO session setup has 12 command words, whereas a normal
1317 NT1 session setup has 13. See the cifs spec. */
1318 if (req->wct == 12 &&
1319 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1321 if (!sconn->smb1.negprot.spnego) {
1322 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1323 "at SPNEGO session setup when it was not "
1324 "negotiated.\n"));
1325 reply_nterror(req, nt_status_squash(
1326 NT_STATUS_LOGON_FAILURE));
1327 END_PROFILE(SMBsesssetupX);
1328 return;
1331 if (SVAL(req->vwv+4, 0) == 0) {
1332 setup_new_vc_session(req->sconn);
1335 reply_sesssetup_and_X_spnego(req);
1336 END_PROFILE(SMBsesssetupX);
1337 return;
1340 smb_bufsize = SVAL(req->vwv+2, 0);
1342 if (get_Protocol() < PROTOCOL_NT1) {
1343 uint16 passlen1 = SVAL(req->vwv+7, 0);
1345 /* Never do NT status codes with protocols before NT1 as we
1346 * don't get client caps. */
1347 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1349 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1350 reply_nterror(req, nt_status_squash(
1351 NT_STATUS_INVALID_PARAMETER));
1352 END_PROFILE(SMBsesssetupX);
1353 return;
1356 if (doencrypt) {
1357 lm_resp = data_blob(req->buf, passlen1);
1358 } else {
1359 plaintext_password = data_blob(req->buf, passlen1+1);
1360 /* Ensure null termination */
1361 plaintext_password.data[passlen1] = 0;
1364 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1365 req->buf + passlen1, STR_TERMINATE);
1366 user = tmp ? tmp : "";
1368 domain = "";
1370 } else {
1371 uint16 passlen1 = SVAL(req->vwv+7, 0);
1372 uint16 passlen2 = SVAL(req->vwv+8, 0);
1373 enum remote_arch_types ra_type = get_remote_arch();
1374 const uint8_t *p = req->buf;
1375 const uint8_t *save_p = req->buf;
1376 uint16 byte_count;
1379 if(global_client_caps == 0) {
1380 global_client_caps = IVAL(req->vwv+11, 0);
1382 if (!(global_client_caps & CAP_STATUS32)) {
1383 remove_from_common_flags2(
1384 FLAGS2_32_BIT_ERROR_CODES);
1387 /* client_caps is used as final determination if
1388 * client is NT or Win95. This is needed to return
1389 * the correct error codes in some circumstances.
1392 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1393 ra_type == RA_WIN95) {
1394 if(!(global_client_caps & (CAP_NT_SMBS|
1395 CAP_STATUS32))) {
1396 set_remote_arch( RA_WIN95);
1401 if (!doencrypt) {
1402 /* both Win95 and WinNT stuff up the password
1403 * lengths for non-encrypting systems. Uggh.
1405 if passlen1==24 its a win95 system, and its setting
1406 the password length incorrectly. Luckily it still
1407 works with the default code because Win95 will null
1408 terminate the password anyway
1410 if passlen1>0 and passlen2>0 then maybe its a NT box
1411 and its setting passlen2 to some random value which
1412 really stuffs things up. we need to fix that one. */
1414 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1415 passlen2 != 1) {
1416 passlen2 = 0;
1420 /* check for nasty tricks */
1421 if (passlen1 > MAX_PASS_LEN
1422 || passlen1 > smbreq_bufrem(req, p)) {
1423 reply_nterror(req, nt_status_squash(
1424 NT_STATUS_INVALID_PARAMETER));
1425 END_PROFILE(SMBsesssetupX);
1426 return;
1429 if (passlen2 > MAX_PASS_LEN
1430 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1431 reply_nterror(req, nt_status_squash(
1432 NT_STATUS_INVALID_PARAMETER));
1433 END_PROFILE(SMBsesssetupX);
1434 return;
1437 /* Save the lanman2 password and the NT md4 password. */
1439 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1440 doencrypt = False;
1443 if (doencrypt) {
1444 lm_resp = data_blob(p, passlen1);
1445 nt_resp = data_blob(p+passlen1, passlen2);
1446 } else if (lp_security() != SEC_SHARE) {
1448 * In share level we should ignore any passwords, so
1449 * only read them if we're not.
1451 char *pass = NULL;
1452 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1454 if (unic && (passlen2 == 0) && passlen1) {
1455 /* Only a ascii plaintext password was sent. */
1456 (void)srvstr_pull_talloc(talloc_tos(),
1457 req->inbuf,
1458 req->flags2,
1459 &pass,
1460 req->buf,
1461 passlen1,
1462 STR_TERMINATE|STR_ASCII);
1463 } else {
1464 (void)srvstr_pull_talloc(talloc_tos(),
1465 req->inbuf,
1466 req->flags2,
1467 &pass,
1468 req->buf,
1469 unic ? passlen2 : passlen1,
1470 STR_TERMINATE);
1472 if (!pass) {
1473 reply_nterror(req, nt_status_squash(
1474 NT_STATUS_INVALID_PARAMETER));
1475 END_PROFILE(SMBsesssetupX);
1476 return;
1478 plaintext_password = data_blob(pass, strlen(pass)+1);
1481 p += passlen1 + passlen2;
1483 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1484 STR_TERMINATE);
1485 user = tmp ? tmp : "";
1487 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1488 STR_TERMINATE);
1489 domain = tmp ? tmp : "";
1491 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1492 STR_TERMINATE);
1493 native_os = tmp ? tmp : "";
1495 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1496 STR_TERMINATE);
1497 native_lanman = tmp ? tmp : "";
1499 /* not documented or decoded by Ethereal but there is one more
1500 * string in the extra bytes which is the same as the
1501 * PrimaryDomain when using extended security. Windows NT 4
1502 * and 2003 use this string to store the native lanman string.
1503 * Windows 9x does not include a string here at all so we have
1504 * to check if we have any extra bytes left */
1506 byte_count = SVAL(req->vwv+13, 0);
1507 if ( PTR_DIFF(p, save_p) < byte_count) {
1508 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1509 STR_TERMINATE);
1510 primary_domain = tmp ? tmp : "";
1511 } else {
1512 primary_domain = talloc_strdup(talloc_tos(), "null");
1515 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1516 "PrimaryDomain=[%s]\n",
1517 domain, native_os, native_lanman, primary_domain));
1519 if ( ra_type == RA_WIN2K ) {
1520 if ( strlen(native_lanman) == 0 )
1521 ra_lanman_string( primary_domain );
1522 else
1523 ra_lanman_string( native_lanman );
1528 if (SVAL(req->vwv+4, 0) == 0) {
1529 setup_new_vc_session(req->sconn);
1532 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1533 domain, user, get_remote_machine_name()));
1535 if (*user) {
1536 if (sconn->smb1.negprot.spnego) {
1538 /* This has to be here, because this is a perfectly
1539 * valid behaviour for guest logons :-( */
1541 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1542 "at 'normal' session setup after "
1543 "negotiating spnego.\n"));
1544 reply_nterror(req, nt_status_squash(
1545 NT_STATUS_LOGON_FAILURE));
1546 END_PROFILE(SMBsesssetupX);
1547 return;
1549 fstrcpy(sub_user, user);
1550 } else {
1551 fstrcpy(sub_user, lp_guestaccount());
1554 sub_set_smb_name(sub_user);
1556 reload_services(sconn->msg_ctx, sconn->sock, True);
1558 if (lp_security() == SEC_SHARE) {
1559 char *sub_user_mapped = NULL;
1560 /* In share level we should ignore any passwords */
1562 data_blob_free(&lm_resp);
1563 data_blob_free(&nt_resp);
1564 data_blob_clear_free(&plaintext_password);
1566 (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
1567 if (!sub_user_mapped) {
1568 reply_nterror(req, NT_STATUS_NO_MEMORY);
1569 END_PROFILE(SMBsesssetupX);
1570 return;
1572 fstrcpy(sub_user, sub_user_mapped);
1573 add_session_user(sconn, sub_user);
1574 add_session_workgroup(sconn, domain);
1575 /* Then force it to null for the benfit of the code below */
1576 user = "";
1579 if (!*user) {
1581 nt_status = check_guest_password(sconn->remote_address, &server_info);
1583 } else if (doencrypt) {
1584 struct auth_context *negprot_auth_context = NULL;
1585 negprot_auth_context = sconn->smb1.negprot.auth_context;
1586 if (!negprot_auth_context) {
1587 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1588 "session setup without negprot denied!\n"));
1589 reply_nterror(req, nt_status_squash(
1590 NT_STATUS_LOGON_FAILURE));
1591 END_PROFILE(SMBsesssetupX);
1592 return;
1594 nt_status = make_user_info_for_reply_enc(&user_info, user,
1595 domain,
1596 sconn->remote_address,
1597 lm_resp, nt_resp);
1598 if (NT_STATUS_IS_OK(nt_status)) {
1599 nt_status = negprot_auth_context->check_ntlm_password(
1600 negprot_auth_context,
1601 user_info,
1602 &server_info);
1604 } else {
1605 struct auth_context *plaintext_auth_context = NULL;
1607 nt_status = make_auth_context_subsystem(
1608 talloc_tos(), &plaintext_auth_context);
1610 if (NT_STATUS_IS_OK(nt_status)) {
1611 uint8_t chal[8];
1613 plaintext_auth_context->get_ntlm_challenge(
1614 plaintext_auth_context, chal);
1616 if (!make_user_info_for_reply(&user_info,
1617 user, domain,
1618 sconn->remote_address,
1619 chal,
1620 plaintext_password)) {
1621 nt_status = NT_STATUS_NO_MEMORY;
1624 if (NT_STATUS_IS_OK(nt_status)) {
1625 nt_status = plaintext_auth_context->check_ntlm_password(
1626 plaintext_auth_context,
1627 user_info,
1628 &server_info);
1630 TALLOC_FREE(plaintext_auth_context);
1635 free_user_info(&user_info);
1637 if (!NT_STATUS_IS_OK(nt_status)) {
1638 nt_status = do_map_to_guest(nt_status, &server_info,
1639 user, domain);
1642 if (!NT_STATUS_IS_OK(nt_status)) {
1643 data_blob_free(&nt_resp);
1644 data_blob_free(&lm_resp);
1645 data_blob_clear_free(&plaintext_password);
1646 reply_nterror(req, nt_status_squash(nt_status));
1647 END_PROFILE(SMBsesssetupX);
1648 return;
1651 nt_status = create_local_token(req, server_info, NULL, &session_info);
1652 TALLOC_FREE(server_info);
1654 if (!NT_STATUS_IS_OK(nt_status)) {
1655 DEBUG(10, ("create_local_token failed: %s\n",
1656 nt_errstr(nt_status)));
1657 data_blob_free(&nt_resp);
1658 data_blob_free(&lm_resp);
1659 data_blob_clear_free(&plaintext_password);
1660 reply_nterror(req, nt_status_squash(nt_status));
1661 END_PROFILE(SMBsesssetupX);
1662 return;
1665 data_blob_clear_free(&plaintext_password);
1667 /* it's ok - setup a reply */
1668 reply_outbuf(req, 3, 0);
1669 if (get_Protocol() >= PROTOCOL_NT1) {
1670 push_signature(&req->outbuf);
1671 /* perhaps grab OS version here?? */
1674 if (session_info->guest) {
1675 SSVAL(req->outbuf,smb_vwv2,1);
1678 /* register the name and uid as being validated, so further connections
1679 to a uid can get through without a password, on the same VC */
1681 if (lp_security() == SEC_SHARE) {
1682 sess_vuid = UID_FIELD_INVALID;
1683 TALLOC_FREE(session_info);
1684 } else {
1685 /* Ignore the initial vuid. */
1686 sess_vuid = register_initial_vuid(sconn);
1687 if (sess_vuid == UID_FIELD_INVALID) {
1688 data_blob_free(&nt_resp);
1689 data_blob_free(&lm_resp);
1690 reply_nterror(req, nt_status_squash(
1691 NT_STATUS_LOGON_FAILURE));
1692 END_PROFILE(SMBsesssetupX);
1693 return;
1695 /* register_existing_vuid keeps the session_info */
1696 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1697 session_info,
1698 nt_resp.data ? nt_resp : lm_resp,
1699 sub_user);
1700 if (sess_vuid == UID_FIELD_INVALID) {
1701 data_blob_free(&nt_resp);
1702 data_blob_free(&lm_resp);
1703 reply_nterror(req, nt_status_squash(
1704 NT_STATUS_LOGON_FAILURE));
1705 END_PROFILE(SMBsesssetupX);
1706 return;
1709 /* current_user_info is changed on new vuid */
1710 reload_services(sconn->msg_ctx, sconn->sock, True);
1713 data_blob_free(&nt_resp);
1714 data_blob_free(&lm_resp);
1716 SSVAL(req->outbuf,smb_uid,sess_vuid);
1717 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1718 req->vuid = sess_vuid;
1720 if (!sconn->smb1.sessions.done_sesssetup) {
1721 sconn->smb1.sessions.max_send =
1722 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1724 sconn->smb1.sessions.done_sesssetup = true;
1726 END_PROFILE(SMBsesssetupX);
1727 chain_reply(req);
1728 return;