Fix one more warning introduced by changing the size of UNIX_USER_TOKEN->ngroups...
[Samba.git] / source3 / smbd / sesssetup.c
blob3cb07bea740b49ce00b8fcd6564b958cab53040c
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 "smbd/globals.h"
27 #include "../libcli/auth/spnego.h"
28 #include "../libcli/auth/ntlmssp.h"
29 #include "ntlmssp_wrap.h"
30 #include "librpc/gen_ndr/messaging.h"
31 #include "../librpc/gen_ndr/krb5pac.h"
32 #include "libads/kerberos_proto.h"
34 /* For split krb5 SPNEGO blobs. */
35 struct pending_auth_data {
36 struct pending_auth_data *prev, *next;
37 uint16 vuid; /* Tag for this entry. */
38 uint16 smbpid; /* Alternate tag for this entry. */
39 size_t needed_len;
40 DATA_BLOB partial_data;
44 on a logon error possibly map the error to success if "map to guest"
45 is set approriately
47 NTSTATUS do_map_to_guest(NTSTATUS status,
48 struct auth_serversupplied_info **server_info,
49 const char *user, const char *domain)
51 user = user ? user : "";
52 domain = domain ? domain : "";
54 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
55 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
56 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
57 DEBUG(3,("No such user %s [%s] - using guest account\n",
58 user, domain));
59 status = make_server_info_guest(NULL, server_info);
63 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
64 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
65 DEBUG(3,("Registered username %s for guest access\n",
66 user));
67 status = make_server_info_guest(NULL, server_info);
71 return status;
74 /****************************************************************************
75 Add the standard 'Samba' signature to the end of the session setup.
76 ****************************************************************************/
78 static int push_signature(uint8 **outbuf)
80 char *lanman;
81 int result, tmp;
83 result = 0;
85 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
87 if (tmp == -1) return -1;
88 result += tmp;
90 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
91 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
92 SAFE_FREE(lanman);
94 else {
95 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
98 if (tmp == -1) return -1;
99 result += tmp;
101 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
103 if (tmp == -1) return -1;
104 result += tmp;
106 return result;
109 /****************************************************************************
110 Send a security blob via a session setup reply.
111 ****************************************************************************/
113 static void reply_sesssetup_blob(struct smb_request *req,
114 DATA_BLOB blob,
115 NTSTATUS nt_status)
117 if (!NT_STATUS_IS_OK(nt_status) &&
118 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
119 reply_nterror(req, nt_status_squash(nt_status));
120 return;
123 nt_status = nt_status_squash(nt_status);
124 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
125 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
126 SSVAL(req->outbuf, smb_vwv3, blob.length);
128 if ((message_push_blob(&req->outbuf, blob) == -1)
129 || (push_signature(&req->outbuf) == -1)) {
130 reply_nterror(req, NT_STATUS_NO_MEMORY);
134 /****************************************************************************
135 Do a 'guest' logon, getting back the
136 ****************************************************************************/
138 static NTSTATUS check_guest_password(struct auth_serversupplied_info **server_info)
140 struct auth_context *auth_context;
141 struct auth_usersupplied_info *user_info = NULL;
143 NTSTATUS nt_status;
144 static unsigned char chal[8] = { 0, };
146 DEBUG(3,("Got anonymous request\n"));
148 nt_status = make_auth_context_fixed(talloc_tos(), &auth_context, chal);
149 if (!NT_STATUS_IS_OK(nt_status)) {
150 return nt_status;
153 if (!make_user_info_guest(&user_info)) {
154 TALLOC_FREE(auth_context);
155 return NT_STATUS_NO_MEMORY;
158 nt_status = auth_context->check_ntlm_password(auth_context,
159 user_info,
160 server_info);
161 TALLOC_FREE(auth_context);
162 free_user_info(&user_info);
163 return nt_status;
167 #ifdef HAVE_KRB5
169 #if 0
170 /* Experiment that failed. See "only happens with a KDC" comment below. */
171 /****************************************************************************
172 Cerate a clock skew error blob for a Windows client.
173 ****************************************************************************/
175 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
177 krb5_context context = NULL;
178 krb5_error_code kerr = 0;
179 krb5_data reply;
180 krb5_principal host_princ = NULL;
181 char *host_princ_s = NULL;
182 bool ret = False;
184 *pblob_out = data_blob_null;
186 initialize_krb5_error_table();
187 kerr = krb5_init_context(&context);
188 if (kerr) {
189 return False;
191 /* Create server principal. */
192 asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
193 if (!host_princ_s) {
194 goto out;
196 strlower_m(host_princ_s);
198 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
199 if (kerr) {
200 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
201 "for name %s: Error %s\n",
202 host_princ_s, error_message(kerr) ));
203 goto out;
206 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
207 host_princ, &reply);
208 if (kerr) {
209 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
210 "failed: Error %s\n",
211 error_message(kerr) ));
212 goto out;
215 *pblob_out = data_blob(reply.data, reply.length);
216 kerberos_free_data_contents(context,&reply);
217 ret = True;
219 out:
221 if (host_princ_s) {
222 SAFE_FREE(host_princ_s);
224 if (host_princ) {
225 krb5_free_principal(context, host_princ);
227 krb5_free_context(context);
228 return ret;
230 #endif
232 /****************************************************************************
233 Reply to a session setup spnego negotiate packet for kerberos.
234 ****************************************************************************/
236 static void reply_spnego_kerberos(struct smb_request *req,
237 DATA_BLOB *secblob,
238 const char *mechOID,
239 uint16 vuid,
240 bool *p_invalidate_vuid)
242 TALLOC_CTX *mem_ctx;
243 DATA_BLOB ticket;
244 struct passwd *pw;
245 int sess_vuid = req->vuid;
246 NTSTATUS ret = NT_STATUS_OK;
247 DATA_BLOB ap_rep, ap_rep_wrapped, response;
248 struct auth_serversupplied_info *server_info = NULL;
249 DATA_BLOB session_key = data_blob_null;
250 uint8 tok_id[2];
251 DATA_BLOB nullblob = data_blob_null;
252 bool map_domainuser_to_guest = False;
253 bool username_was_mapped;
254 struct PAC_LOGON_INFO *logon_info = NULL;
255 struct smbd_server_connection *sconn = req->sconn;
256 char *principal;
257 char *user;
258 char *domain;
259 char *real_username;
261 ZERO_STRUCT(ticket);
262 ZERO_STRUCT(ap_rep);
263 ZERO_STRUCT(ap_rep_wrapped);
264 ZERO_STRUCT(response);
266 /* Normally we will always invalidate the intermediate vuid. */
267 *p_invalidate_vuid = True;
269 mem_ctx = talloc_init("reply_spnego_kerberos");
270 if (mem_ctx == NULL) {
271 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
272 return;
275 if (!spnego_parse_krb5_wrap(mem_ctx, *secblob, &ticket, tok_id)) {
276 talloc_destroy(mem_ctx);
277 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
278 return;
281 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
282 &principal, &logon_info, &ap_rep,
283 &session_key, True);
285 data_blob_free(&ticket);
287 if (!NT_STATUS_IS_OK(ret)) {
288 #if 0
289 /* Experiment that failed.
290 * See "only happens with a KDC" comment below. */
292 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
295 * Windows in this case returns
296 * NT_STATUS_MORE_PROCESSING_REQUIRED
297 * with a negTokenTarg blob containing an krb5_error
298 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
299 * The client then fixes its clock and continues rather
300 * than giving an error. JRA.
301 * -- Looks like this only happens with a KDC. JRA.
304 bool ok = make_krb5_skew_error(&ap_rep);
305 if (!ok) {
306 talloc_destroy(mem_ctx);
307 return ERROR_NT(nt_status_squash(
308 NT_STATUS_LOGON_FAILURE));
310 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
311 TOK_ID_KRB_ERROR);
312 response = spnego_gen_auth_response(&ap_rep_wrapped,
313 ret, OID_KERBEROS5_OLD);
314 reply_sesssetup_blob(conn, inbuf, outbuf, response,
315 NT_STATUS_MORE_PROCESSING_REQUIRED);
318 * In this one case we don't invalidate the
319 * intermediate vuid as we're expecting the client
320 * to re-use it for the next sessionsetupX packet. JRA.
323 *p_invalidate_vuid = False;
325 data_blob_free(&ap_rep);
326 data_blob_free(&ap_rep_wrapped);
327 data_blob_free(&response);
328 talloc_destroy(mem_ctx);
329 return -1; /* already replied */
331 #else
332 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
333 ret = NT_STATUS_LOGON_FAILURE;
335 #endif
336 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
337 nt_errstr(ret)));
338 talloc_destroy(mem_ctx);
339 reply_nterror(req, nt_status_squash(ret));
340 return;
343 ret = get_user_from_kerberos_info(talloc_tos(),
344 sconn->client_id.name,
345 principal, logon_info,
346 &username_was_mapped,
347 &map_domainuser_to_guest,
348 &user, &domain,
349 &real_username, &pw);
350 if (!NT_STATUS_IS_OK(ret)) {
351 data_blob_free(&ap_rep);
352 data_blob_free(&session_key);
353 talloc_destroy(mem_ctx);
354 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
355 return;
358 /* save the PAC data if we have it */
359 if (logon_info) {
360 netsamlogon_cache_store(user, &logon_info->info3);
363 /* setup the string used by %U */
364 sub_set_smb_name(real_username);
366 /* reload services so that the new %U is taken into account */
367 reload_services(sconn->msg_ctx, sconn->sock, True);
369 ret = make_server_info_krb5(mem_ctx,
370 user, domain, real_username, pw,
371 logon_info, map_domainuser_to_guest,
372 &server_info);
373 if (!NT_STATUS_IS_OK(ret)) {
374 DEBUG(1, ("make_server_info_krb5 failed!\n"));
375 data_blob_free(&ap_rep);
376 data_blob_free(&session_key);
377 TALLOC_FREE(mem_ctx);
378 reply_nterror(req, nt_status_squash(ret));
379 return;
382 server_info->nss_token |= username_was_mapped;
384 /* we need to build the token for the user. make_server_info_guest()
385 already does this */
387 if ( !server_info->security_token ) {
388 ret = create_local_token( server_info );
389 if ( !NT_STATUS_IS_OK(ret) ) {
390 DEBUG(10,("failed to create local token: %s\n",
391 nt_errstr(ret)));
392 data_blob_free(&ap_rep);
393 data_blob_free(&session_key);
394 TALLOC_FREE( mem_ctx );
395 TALLOC_FREE( server_info );
396 reply_nterror(req, nt_status_squash(ret));
397 return;
401 if (!is_partial_auth_vuid(sconn, sess_vuid)) {
402 sess_vuid = register_initial_vuid(sconn);
405 data_blob_free(&server_info->user_session_key);
406 /* Set the kerberos-derived session key onto the server_info */
407 server_info->user_session_key = session_key;
408 talloc_steal(server_info, session_key.data);
410 session_key = data_blob_null;
412 /* register_existing_vuid keeps the server info */
413 /* register_existing_vuid takes ownership of session_key on success,
414 * no need to free after this on success. A better interface would copy
415 * it.... */
417 sess_vuid = register_existing_vuid(sconn, sess_vuid,
418 server_info, nullblob, user);
420 reply_outbuf(req, 4, 0);
421 SSVAL(req->outbuf,smb_uid,sess_vuid);
423 if (sess_vuid == UID_FIELD_INVALID ) {
424 ret = NT_STATUS_LOGON_FAILURE;
425 } else {
426 /* current_user_info is changed on new vuid */
427 reload_services(sconn->msg_ctx, sconn->sock, True);
429 SSVAL(req->outbuf, smb_vwv3, 0);
431 if (server_info->guest) {
432 SSVAL(req->outbuf,smb_vwv2,1);
435 SSVAL(req->outbuf, smb_uid, sess_vuid);
437 /* Successful logon. Keep this vuid. */
438 *p_invalidate_vuid = False;
441 /* wrap that up in a nice GSS-API wrapping */
442 if (NT_STATUS_IS_OK(ret)) {
443 ap_rep_wrapped = spnego_gen_krb5_wrap(talloc_tos(), ap_rep,
444 TOK_ID_KRB_AP_REP);
445 } else {
446 ap_rep_wrapped = data_blob_null;
448 response = spnego_gen_auth_response(talloc_tos(), &ap_rep_wrapped, ret,
449 mechOID);
450 reply_sesssetup_blob(req, response, ret);
452 data_blob_free(&ap_rep);
453 data_blob_free(&ap_rep_wrapped);
454 data_blob_free(&response);
455 TALLOC_FREE(mem_ctx);
458 #endif
460 /****************************************************************************
461 Send a session setup reply, wrapped in SPNEGO.
462 Get vuid and check first.
463 End the NTLMSSP exchange context if we are OK/complete fail
464 This should be split into two functions, one to handle each
465 leg of the NTLM auth steps.
466 ***************************************************************************/
468 static void reply_spnego_ntlmssp(struct smb_request *req,
469 uint16 vuid,
470 struct auth_ntlmssp_state **auth_ntlmssp_state,
471 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
472 const char *OID,
473 bool wrap)
475 bool do_invalidate = true;
476 DATA_BLOB response;
477 struct auth_serversupplied_info *session_info = NULL;
478 struct smbd_server_connection *sconn = req->sconn;
480 if (NT_STATUS_IS_OK(nt_status)) {
481 nt_status = auth_ntlmssp_steal_session_info(talloc_tos(),
482 (*auth_ntlmssp_state), &session_info);
483 } else {
484 /* Note that this session_info won't have a session
485 * key. But for map to guest, that's exactly the right
486 * thing - we can't reasonably guess the key the
487 * client wants, as the password was wrong */
488 nt_status = do_map_to_guest(nt_status,
489 &session_info,
490 auth_ntlmssp_get_username(*auth_ntlmssp_state),
491 auth_ntlmssp_get_domain(*auth_ntlmssp_state));
494 reply_outbuf(req, 4, 0);
496 SSVAL(req->outbuf, smb_uid, vuid);
498 if (NT_STATUS_IS_OK(nt_status)) {
499 DATA_BLOB nullblob = data_blob_null;
501 if (!is_partial_auth_vuid(sconn, vuid)) {
502 nt_status = NT_STATUS_LOGON_FAILURE;
503 goto out;
506 /* register_existing_vuid keeps the server info */
507 if (register_existing_vuid(sconn, vuid,
508 session_info, nullblob,
509 auth_ntlmssp_get_username(*auth_ntlmssp_state)) !=
510 vuid) {
511 /* The problem is, *auth_ntlmssp_state points
512 * into the vuser this will have
513 * talloc_free()'ed in
514 * register_existing_vuid() */
515 do_invalidate = false;
516 nt_status = NT_STATUS_LOGON_FAILURE;
517 goto out;
520 /* current_user_info is changed on new vuid */
521 reload_services(sconn->msg_ctx, sconn->sock, True);
523 SSVAL(req->outbuf, smb_vwv3, 0);
525 if (session_info->guest) {
526 SSVAL(req->outbuf,smb_vwv2,1);
530 out:
532 if (wrap) {
533 response = spnego_gen_auth_response(talloc_tos(),
534 ntlmssp_blob,
535 nt_status, OID);
536 } else {
537 response = *ntlmssp_blob;
540 reply_sesssetup_blob(req, response, nt_status);
541 if (wrap) {
542 data_blob_free(&response);
545 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
546 and the other end, that we are not finished yet. */
548 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
549 /* NB. This is *NOT* an error case. JRA */
550 if (do_invalidate) {
551 TALLOC_FREE(*auth_ntlmssp_state);
552 if (!NT_STATUS_IS_OK(nt_status)) {
553 /* Kill the intermediate vuid */
554 invalidate_vuid(sconn, vuid);
560 /****************************************************************************
561 Is this a krb5 mechanism ?
562 ****************************************************************************/
564 NTSTATUS parse_spnego_mechanisms(TALLOC_CTX *ctx,
565 DATA_BLOB blob_in,
566 DATA_BLOB *pblob_out,
567 char **kerb_mechOID)
569 char *OIDs[ASN1_MAX_OIDS];
570 int i;
571 NTSTATUS ret = NT_STATUS_OK;
573 *kerb_mechOID = NULL;
575 /* parse out the OIDs and the first sec blob */
576 if (!spnego_parse_negTokenInit(ctx, blob_in, OIDs, NULL, pblob_out) ||
577 (OIDs[0] == NULL)) {
578 return NT_STATUS_LOGON_FAILURE;
581 /* only look at the first OID for determining the mechToken --
582 according to RFC2478, we should choose the one we want
583 and renegotiate, but i smell a client bug here..
585 Problem observed when connecting to a member (samba box)
586 of an AD domain as a user in a Samba domain. Samba member
587 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
588 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
589 NTLMSSP mechtoken. --jerry */
591 #ifdef HAVE_KRB5
592 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
593 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
594 *kerb_mechOID = talloc_strdup(ctx, OIDs[0]);
595 if (*kerb_mechOID == NULL) {
596 ret = NT_STATUS_NO_MEMORY;
599 #endif
601 for (i=0;OIDs[i];i++) {
602 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
603 talloc_free(OIDs[i]);
605 return ret;
608 /****************************************************************************
609 Fall back from krb5 to NTLMSSP.
610 ****************************************************************************/
612 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
613 uint16 vuid)
615 DATA_BLOB response;
617 reply_outbuf(req, 4, 0);
618 SSVAL(req->outbuf,smb_uid,vuid);
620 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
621 "but set to downgrade to NTLMSSP\n"));
623 response = spnego_gen_auth_response(talloc_tos(), NULL,
624 NT_STATUS_MORE_PROCESSING_REQUIRED,
625 OID_NTLMSSP);
626 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
627 data_blob_free(&response);
630 /****************************************************************************
631 Reply to a session setup spnego negotiate packet.
632 ****************************************************************************/
634 static void reply_spnego_negotiate(struct smb_request *req,
635 uint16 vuid,
636 DATA_BLOB blob1,
637 struct auth_ntlmssp_state **auth_ntlmssp_state)
639 DATA_BLOB secblob;
640 DATA_BLOB chal;
641 char *kerb_mech = NULL;
642 NTSTATUS status;
643 struct smbd_server_connection *sconn = req->sconn;
645 status = parse_spnego_mechanisms(talloc_tos(),
646 blob1, &secblob, &kerb_mech);
647 if (!NT_STATUS_IS_OK(status)) {
648 /* Kill the intermediate vuid */
649 invalidate_vuid(sconn, vuid);
650 reply_nterror(req, nt_status_squash(status));
651 return;
654 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
655 (unsigned long)secblob.length));
657 #ifdef HAVE_KRB5
658 if (kerb_mech && ((lp_security()==SEC_ADS) ||
659 USE_KERBEROS_KEYTAB) ) {
660 bool destroy_vuid = True;
661 reply_spnego_kerberos(req, &secblob, kerb_mech,
662 vuid, &destroy_vuid);
663 data_blob_free(&secblob);
664 if (destroy_vuid) {
665 /* Kill the intermediate vuid */
666 invalidate_vuid(sconn, vuid);
668 TALLOC_FREE(kerb_mech);
669 return;
671 #endif
673 if (*auth_ntlmssp_state) {
674 TALLOC_FREE(*auth_ntlmssp_state);
677 if (kerb_mech) {
678 data_blob_free(&secblob);
679 /* The mechtoken is a krb5 ticket, but
680 * we need to fall back to NTLM. */
681 reply_spnego_downgrade_to_ntlmssp(req, vuid);
682 TALLOC_FREE(kerb_mech);
683 return;
686 status = auth_ntlmssp_start(auth_ntlmssp_state);
687 if (!NT_STATUS_IS_OK(status)) {
688 /* Kill the intermediate vuid */
689 invalidate_vuid(sconn, vuid);
690 reply_nterror(req, nt_status_squash(status));
691 return;
694 status = auth_ntlmssp_update(*auth_ntlmssp_state,
695 secblob, &chal);
697 data_blob_free(&secblob);
699 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
700 &chal, status, OID_NTLMSSP, true);
702 data_blob_free(&chal);
704 /* already replied */
705 return;
708 /****************************************************************************
709 Reply to a session setup spnego auth packet.
710 ****************************************************************************/
712 static void reply_spnego_auth(struct smb_request *req,
713 uint16 vuid,
714 DATA_BLOB blob1,
715 struct auth_ntlmssp_state **auth_ntlmssp_state)
717 DATA_BLOB auth = data_blob_null;
718 DATA_BLOB auth_reply = data_blob_null;
719 DATA_BLOB secblob = data_blob_null;
720 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
721 struct smbd_server_connection *sconn = req->sconn;
723 if (!spnego_parse_auth(talloc_tos(), blob1, &auth)) {
724 #if 0
725 file_save("auth.dat", blob1.data, blob1.length);
726 #endif
727 /* Kill the intermediate vuid */
728 invalidate_vuid(sconn, vuid);
730 reply_nterror(req, nt_status_squash(
731 NT_STATUS_LOGON_FAILURE));
732 return;
735 if (auth.data[0] == ASN1_APPLICATION(0)) {
736 /* Might be a second negTokenTarg packet */
737 char *kerb_mech = NULL;
739 status = parse_spnego_mechanisms(talloc_tos(),
740 auth, &secblob, &kerb_mech);
742 if (!NT_STATUS_IS_OK(status)) {
743 /* Kill the intermediate vuid */
744 invalidate_vuid(sconn, vuid);
745 reply_nterror(req, nt_status_squash(status));
746 return;
749 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
750 (unsigned long)secblob.length));
751 #ifdef HAVE_KRB5
752 if (kerb_mech && ((lp_security()==SEC_ADS) ||
753 USE_KERBEROS_KEYTAB)) {
754 bool destroy_vuid = True;
755 reply_spnego_kerberos(req, &secblob, kerb_mech,
756 vuid, &destroy_vuid);
757 data_blob_free(&secblob);
758 data_blob_free(&auth);
759 if (destroy_vuid) {
760 /* Kill the intermediate vuid */
761 invalidate_vuid(sconn, vuid);
763 TALLOC_FREE(kerb_mech);
764 return;
766 #endif
767 /* Can't blunder into NTLMSSP auth if we have
768 * a krb5 ticket. */
770 if (kerb_mech) {
771 /* Kill the intermediate vuid */
772 invalidate_vuid(sconn, vuid);
773 DEBUG(3,("reply_spnego_auth: network "
774 "misconfiguration, client sent us a "
775 "krb5 ticket and kerberos security "
776 "not enabled\n"));
777 reply_nterror(req, nt_status_squash(
778 NT_STATUS_LOGON_FAILURE));
779 TALLOC_FREE(kerb_mech);
783 /* If we get here it wasn't a negTokenTarg auth packet. */
784 data_blob_free(&secblob);
786 if (!*auth_ntlmssp_state) {
787 status = auth_ntlmssp_start(auth_ntlmssp_state);
788 if (!NT_STATUS_IS_OK(status)) {
789 /* Kill the intermediate vuid */
790 invalidate_vuid(sconn, vuid);
791 reply_nterror(req, nt_status_squash(status));
792 return;
796 status = auth_ntlmssp_update(*auth_ntlmssp_state,
797 auth, &auth_reply);
799 data_blob_free(&auth);
801 /* Don't send the mechid as we've already sent this (RFC4178). */
803 reply_spnego_ntlmssp(req, vuid,
804 auth_ntlmssp_state,
805 &auth_reply, status, NULL, true);
807 data_blob_free(&auth_reply);
809 /* and tell smbd that we have already replied to this packet */
810 return;
813 /****************************************************************************
814 Delete an entry on the list.
815 ****************************************************************************/
817 static void delete_partial_auth(struct smbd_server_connection *sconn,
818 struct pending_auth_data *pad)
820 if (!pad) {
821 return;
823 DLIST_REMOVE(sconn->smb1.pd_list, pad);
824 data_blob_free(&pad->partial_data);
825 SAFE_FREE(pad);
828 /****************************************************************************
829 Search for a partial SPNEGO auth fragment matching an smbpid.
830 ****************************************************************************/
832 static struct pending_auth_data *get_pending_auth_data(
833 struct smbd_server_connection *sconn,
834 uint16_t smbpid)
836 struct pending_auth_data *pad;
838 * NOTE: using the smbpid here is completely wrong...
839 * see [MS-SMB]
840 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
842 for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
843 if (pad->smbpid == smbpid) {
844 break;
847 return pad;
850 /****************************************************************************
851 Check the size of an SPNEGO blob. If we need more return
852 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
853 the blob to be more than 64k.
854 ****************************************************************************/
856 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
857 uint16 smbpid, uint16 vuid,
858 DATA_BLOB *pblob)
860 struct pending_auth_data *pad = NULL;
861 ASN1_DATA *data;
862 size_t needed_len = 0;
864 pad = get_pending_auth_data(sconn, smbpid);
866 /* Ensure we have some data. */
867 if (pblob->length == 0) {
868 /* Caller can cope. */
869 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
870 delete_partial_auth(sconn, pad);
871 return NT_STATUS_OK;
874 /* Were we waiting for more data ? */
875 if (pad) {
876 DATA_BLOB tmp_blob;
877 size_t copy_len = MIN(65536, pblob->length);
879 /* Integer wrap paranoia.... */
881 if (pad->partial_data.length + copy_len <
882 pad->partial_data.length ||
883 pad->partial_data.length + copy_len < copy_len) {
885 DEBUG(2,("check_spnego_blob_complete: integer wrap "
886 "pad->partial_data.length = %u, "
887 "copy_len = %u\n",
888 (unsigned int)pad->partial_data.length,
889 (unsigned int)copy_len ));
891 delete_partial_auth(sconn, pad);
892 return NT_STATUS_INVALID_PARAMETER;
895 DEBUG(10,("check_spnego_blob_complete: "
896 "pad->partial_data.length = %u, "
897 "pad->needed_len = %u, "
898 "copy_len = %u, "
899 "pblob->length = %u,\n",
900 (unsigned int)pad->partial_data.length,
901 (unsigned int)pad->needed_len,
902 (unsigned int)copy_len,
903 (unsigned int)pblob->length ));
905 tmp_blob = data_blob(NULL,
906 pad->partial_data.length + copy_len);
908 /* Concatenate the two (up to copy_len) bytes. */
909 memcpy(tmp_blob.data,
910 pad->partial_data.data,
911 pad->partial_data.length);
912 memcpy(tmp_blob.data + pad->partial_data.length,
913 pblob->data,
914 copy_len);
916 /* Replace the partial data. */
917 data_blob_free(&pad->partial_data);
918 pad->partial_data = tmp_blob;
919 ZERO_STRUCT(tmp_blob);
921 /* Are we done ? */
922 if (pblob->length >= pad->needed_len) {
923 /* Yes, replace pblob. */
924 data_blob_free(pblob);
925 *pblob = pad->partial_data;
926 ZERO_STRUCT(pad->partial_data);
927 delete_partial_auth(sconn, pad);
928 return NT_STATUS_OK;
931 /* Still need more data. */
932 pad->needed_len -= copy_len;
933 return NT_STATUS_MORE_PROCESSING_REQUIRED;
936 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
937 (pblob->data[0] != ASN1_CONTEXT(1))) {
938 /* Not something we can determine the
939 * length of.
941 return NT_STATUS_OK;
944 /* This is a new SPNEGO sessionsetup - see if
945 * the data given in this blob is enough.
948 data = asn1_init(NULL);
949 if (data == NULL) {
950 return NT_STATUS_NO_MEMORY;
953 asn1_load(data, *pblob);
954 asn1_start_tag(data, pblob->data[0]);
955 if (data->has_error || data->nesting == NULL) {
956 asn1_free(data);
957 /* Let caller catch. */
958 return NT_STATUS_OK;
961 /* Integer wrap paranoia.... */
963 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
964 data->nesting->taglen + data->nesting->start < data->nesting->start) {
966 DEBUG(2,("check_spnego_blob_complete: integer wrap "
967 "data.nesting->taglen = %u, "
968 "data.nesting->start = %u\n",
969 (unsigned int)data->nesting->taglen,
970 (unsigned int)data->nesting->start ));
972 asn1_free(data);
973 return NT_STATUS_INVALID_PARAMETER;
976 /* Total length of the needed asn1 is the tag length
977 * plus the current offset. */
979 needed_len = data->nesting->taglen + data->nesting->start;
980 asn1_free(data);
982 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
983 "pblob->length = %u\n",
984 (unsigned int)needed_len,
985 (unsigned int)pblob->length ));
987 if (needed_len <= pblob->length) {
988 /* Nothing to do - blob is complete. */
989 return NT_STATUS_OK;
992 /* Refuse the blob if it's bigger than 64k. */
993 if (needed_len > 65536) {
994 DEBUG(2,("check_spnego_blob_complete: needed_len "
995 "too large (%u)\n",
996 (unsigned int)needed_len ));
997 return NT_STATUS_INVALID_PARAMETER;
1000 /* We must store this blob until complete. */
1001 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1002 return NT_STATUS_NO_MEMORY;
1004 pad->needed_len = needed_len - pblob->length;
1005 pad->partial_data = data_blob(pblob->data, pblob->length);
1006 if (pad->partial_data.data == NULL) {
1007 SAFE_FREE(pad);
1008 return NT_STATUS_NO_MEMORY;
1010 pad->smbpid = smbpid;
1011 pad->vuid = vuid;
1012 DLIST_ADD(sconn->smb1.pd_list, pad);
1014 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1017 /****************************************************************************
1018 Reply to a session setup command.
1019 conn POINTER CAN BE NULL HERE !
1020 ****************************************************************************/
1022 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1024 const uint8 *p;
1025 DATA_BLOB blob1;
1026 size_t bufrem;
1027 char *tmp;
1028 const char *native_os;
1029 const char *native_lanman;
1030 const char *primary_domain;
1031 const char *p2;
1032 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1033 enum remote_arch_types ra_type = get_remote_arch();
1034 int vuid = req->vuid;
1035 user_struct *vuser = NULL;
1036 NTSTATUS status = NT_STATUS_OK;
1037 uint16 smbpid = req->smbpid;
1038 struct smbd_server_connection *sconn = req->sconn;
1040 DEBUG(3,("Doing spnego session setup\n"));
1042 if (global_client_caps == 0) {
1043 global_client_caps = IVAL(req->vwv+10, 0);
1045 if (!(global_client_caps & CAP_STATUS32)) {
1046 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1051 p = req->buf;
1053 if (data_blob_len == 0) {
1054 /* an invalid request */
1055 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1056 return;
1059 bufrem = smbreq_bufrem(req, p);
1060 /* pull the spnego blob */
1061 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1063 #if 0
1064 file_save("negotiate.dat", blob1.data, blob1.length);
1065 #endif
1067 p2 = (char *)req->buf + blob1.length;
1069 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1070 STR_TERMINATE);
1071 native_os = tmp ? tmp : "";
1073 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1074 STR_TERMINATE);
1075 native_lanman = tmp ? tmp : "";
1077 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1078 STR_TERMINATE);
1079 primary_domain = tmp ? tmp : "";
1081 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1082 native_os, native_lanman, primary_domain));
1084 if ( ra_type == RA_WIN2K ) {
1085 /* Vista sets neither the OS or lanman strings */
1087 if ( !strlen(native_os) && !strlen(native_lanman) )
1088 set_remote_arch(RA_VISTA);
1090 /* Windows 2003 doesn't set the native lanman string,
1091 but does set primary domain which is a bug I think */
1093 if ( !strlen(native_lanman) ) {
1094 ra_lanman_string( primary_domain );
1095 } else {
1096 ra_lanman_string( native_lanman );
1098 } else if ( ra_type == RA_VISTA ) {
1099 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
1100 set_remote_arch(RA_OSX);
1104 /* Did we get a valid vuid ? */
1105 if (!is_partial_auth_vuid(sconn, vuid)) {
1106 /* No, then try and see if this is an intermediate sessionsetup
1107 * for a large SPNEGO packet. */
1108 struct pending_auth_data *pad;
1109 pad = get_pending_auth_data(sconn, smbpid);
1110 if (pad) {
1111 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1112 "pending vuid %u\n",
1113 (unsigned int)pad->vuid ));
1114 vuid = pad->vuid;
1118 /* Do we have a valid vuid now ? */
1119 if (!is_partial_auth_vuid(sconn, vuid)) {
1120 /* No, start a new authentication setup. */
1121 vuid = register_initial_vuid(sconn);
1122 if (vuid == UID_FIELD_INVALID) {
1123 data_blob_free(&blob1);
1124 reply_nterror(req, nt_status_squash(
1125 NT_STATUS_INVALID_PARAMETER));
1126 return;
1130 vuser = get_partial_auth_user_struct(sconn, vuid);
1131 /* This MUST be valid. */
1132 if (!vuser) {
1133 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1136 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1137 * sessionsetup requests as the Windows limit on the security blob
1138 * field is 4k. Bug #4400. JRA.
1141 status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1142 if (!NT_STATUS_IS_OK(status)) {
1143 if (!NT_STATUS_EQUAL(status,
1144 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1145 /* Real error - kill the intermediate vuid */
1146 invalidate_vuid(sconn, vuid);
1148 data_blob_free(&blob1);
1149 reply_nterror(req, nt_status_squash(status));
1150 return;
1153 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1155 /* its a negTokenTarg packet */
1157 reply_spnego_negotiate(req, vuid, blob1,
1158 &vuser->auth_ntlmssp_state);
1159 data_blob_free(&blob1);
1160 return;
1163 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1165 /* its a auth packet */
1167 reply_spnego_auth(req, vuid, blob1,
1168 &vuser->auth_ntlmssp_state);
1169 data_blob_free(&blob1);
1170 return;
1173 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1174 DATA_BLOB chal;
1176 if (!vuser->auth_ntlmssp_state) {
1177 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1178 if (!NT_STATUS_IS_OK(status)) {
1179 /* Kill the intermediate vuid */
1180 invalidate_vuid(sconn, vuid);
1181 data_blob_free(&blob1);
1182 reply_nterror(req, nt_status_squash(status));
1183 return;
1187 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1188 blob1, &chal);
1190 data_blob_free(&blob1);
1192 reply_spnego_ntlmssp(req, vuid,
1193 &vuser->auth_ntlmssp_state,
1194 &chal, status, OID_NTLMSSP, false);
1195 data_blob_free(&chal);
1196 return;
1199 /* what sort of packet is this? */
1200 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1202 data_blob_free(&blob1);
1204 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1207 /****************************************************************************
1208 On new VC == 0, shutdown *all* old connections and users.
1209 It seems that only NT4.x does this. At W2K and above (XP etc.).
1210 a new session setup with VC==0 is ignored.
1211 ****************************************************************************/
1213 struct shutdown_state {
1214 const char *ip;
1215 struct messaging_context *msg_ctx;
1218 static int shutdown_other_smbds(const struct connections_key *key,
1219 const struct connections_data *crec,
1220 void *private_data)
1222 struct shutdown_state *state = (struct shutdown_state *)private_data;
1224 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
1225 procid_str(talloc_tos(), &crec->pid), crec->addr));
1227 if (!process_exists(crec->pid)) {
1228 DEBUG(10, ("process does not exist\n"));
1229 return 0;
1232 if (procid_is_me(&crec->pid)) {
1233 DEBUG(10, ("It's me\n"));
1234 return 0;
1237 if (strcmp(state->ip, crec->addr) != 0) {
1238 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
1239 return 0;
1242 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
1243 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
1244 state->ip));
1246 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
1247 &data_blob_null);
1248 return 0;
1251 static void setup_new_vc_session(struct smbd_server_connection *sconn)
1253 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1254 "compatible we would close all old resources.\n"));
1255 #if 0
1256 conn_close_all();
1257 invalidate_all_vuids();
1258 #endif
1259 if (lp_reset_on_zero_vc()) {
1260 char *addr;
1261 struct shutdown_state state;
1263 addr = tsocket_address_inet_addr_string(
1264 sconn->remote_address, talloc_tos());
1265 if (addr == NULL) {
1266 return;
1268 state.ip = addr;
1269 state.msg_ctx = sconn->msg_ctx;
1270 connections_forall_read(shutdown_other_smbds, &state);
1271 TALLOC_FREE(addr);
1275 /****************************************************************************
1276 Reply to a session setup command.
1277 ****************************************************************************/
1279 void reply_sesssetup_and_X(struct smb_request *req)
1281 int sess_vuid;
1282 int smb_bufsize;
1283 DATA_BLOB lm_resp;
1284 DATA_BLOB nt_resp;
1285 DATA_BLOB plaintext_password;
1286 char *tmp;
1287 const char *user;
1288 fstring sub_user; /* Sanitised username for substituion */
1289 const char *domain;
1290 const char *native_os;
1291 const char *native_lanman;
1292 const char *primary_domain;
1293 struct auth_usersupplied_info *user_info = NULL;
1294 struct auth_serversupplied_info *server_info = NULL;
1295 uint16 smb_flag2 = req->flags2;
1297 NTSTATUS nt_status;
1298 struct smbd_server_connection *sconn = req->sconn;
1300 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1302 START_PROFILE(SMBsesssetupX);
1304 ZERO_STRUCT(lm_resp);
1305 ZERO_STRUCT(nt_resp);
1306 ZERO_STRUCT(plaintext_password);
1308 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1310 /* a SPNEGO session setup has 12 command words, whereas a normal
1311 NT1 session setup has 13. See the cifs spec. */
1312 if (req->wct == 12 &&
1313 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1315 if (!sconn->smb1.negprot.spnego) {
1316 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1317 "at SPNEGO session setup when it was not "
1318 "negotiated.\n"));
1319 reply_nterror(req, nt_status_squash(
1320 NT_STATUS_LOGON_FAILURE));
1321 END_PROFILE(SMBsesssetupX);
1322 return;
1325 if (SVAL(req->vwv+4, 0) == 0) {
1326 setup_new_vc_session(req->sconn);
1329 reply_sesssetup_and_X_spnego(req);
1330 END_PROFILE(SMBsesssetupX);
1331 return;
1334 smb_bufsize = SVAL(req->vwv+2, 0);
1336 if (get_Protocol() < PROTOCOL_NT1) {
1337 uint16 passlen1 = SVAL(req->vwv+7, 0);
1339 /* Never do NT status codes with protocols before NT1 as we
1340 * don't get client caps. */
1341 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1343 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1344 reply_nterror(req, nt_status_squash(
1345 NT_STATUS_INVALID_PARAMETER));
1346 END_PROFILE(SMBsesssetupX);
1347 return;
1350 if (doencrypt) {
1351 lm_resp = data_blob(req->buf, passlen1);
1352 } else {
1353 plaintext_password = data_blob(req->buf, passlen1+1);
1354 /* Ensure null termination */
1355 plaintext_password.data[passlen1] = 0;
1358 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1359 req->buf + passlen1, STR_TERMINATE);
1360 user = tmp ? tmp : "";
1362 domain = "";
1364 } else {
1365 uint16 passlen1 = SVAL(req->vwv+7, 0);
1366 uint16 passlen2 = SVAL(req->vwv+8, 0);
1367 enum remote_arch_types ra_type = get_remote_arch();
1368 const uint8_t *p = req->buf;
1369 const uint8_t *save_p = req->buf;
1370 uint16 byte_count;
1373 if(global_client_caps == 0) {
1374 global_client_caps = IVAL(req->vwv+11, 0);
1376 if (!(global_client_caps & CAP_STATUS32)) {
1377 remove_from_common_flags2(
1378 FLAGS2_32_BIT_ERROR_CODES);
1381 /* client_caps is used as final determination if
1382 * client is NT or Win95. This is needed to return
1383 * the correct error codes in some circumstances.
1386 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1387 ra_type == RA_WIN95) {
1388 if(!(global_client_caps & (CAP_NT_SMBS|
1389 CAP_STATUS32))) {
1390 set_remote_arch( RA_WIN95);
1395 if (!doencrypt) {
1396 /* both Win95 and WinNT stuff up the password
1397 * lengths for non-encrypting systems. Uggh.
1399 if passlen1==24 its a win95 system, and its setting
1400 the password length incorrectly. Luckily it still
1401 works with the default code because Win95 will null
1402 terminate the password anyway
1404 if passlen1>0 and passlen2>0 then maybe its a NT box
1405 and its setting passlen2 to some random value which
1406 really stuffs things up. we need to fix that one. */
1408 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1409 passlen2 != 1) {
1410 passlen2 = 0;
1414 /* check for nasty tricks */
1415 if (passlen1 > MAX_PASS_LEN
1416 || passlen1 > smbreq_bufrem(req, p)) {
1417 reply_nterror(req, nt_status_squash(
1418 NT_STATUS_INVALID_PARAMETER));
1419 END_PROFILE(SMBsesssetupX);
1420 return;
1423 if (passlen2 > MAX_PASS_LEN
1424 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1425 reply_nterror(req, nt_status_squash(
1426 NT_STATUS_INVALID_PARAMETER));
1427 END_PROFILE(SMBsesssetupX);
1428 return;
1431 /* Save the lanman2 password and the NT md4 password. */
1433 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1434 doencrypt = False;
1437 if (doencrypt) {
1438 lm_resp = data_blob(p, passlen1);
1439 nt_resp = data_blob(p+passlen1, passlen2);
1440 } else if (lp_security() != SEC_SHARE) {
1442 * In share level we should ignore any passwords, so
1443 * only read them if we're not.
1445 char *pass = NULL;
1446 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1448 if (unic && (passlen2 == 0) && passlen1) {
1449 /* Only a ascii plaintext password was sent. */
1450 (void)srvstr_pull_talloc(talloc_tos(),
1451 req->inbuf,
1452 req->flags2,
1453 &pass,
1454 req->buf,
1455 passlen1,
1456 STR_TERMINATE|STR_ASCII);
1457 } else {
1458 (void)srvstr_pull_talloc(talloc_tos(),
1459 req->inbuf,
1460 req->flags2,
1461 &pass,
1462 req->buf,
1463 unic ? passlen2 : passlen1,
1464 STR_TERMINATE);
1466 if (!pass) {
1467 reply_nterror(req, nt_status_squash(
1468 NT_STATUS_INVALID_PARAMETER));
1469 END_PROFILE(SMBsesssetupX);
1470 return;
1472 plaintext_password = data_blob(pass, strlen(pass)+1);
1475 p += passlen1 + passlen2;
1477 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1478 STR_TERMINATE);
1479 user = tmp ? tmp : "";
1481 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1482 STR_TERMINATE);
1483 domain = tmp ? tmp : "";
1485 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1486 STR_TERMINATE);
1487 native_os = tmp ? tmp : "";
1489 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1490 STR_TERMINATE);
1491 native_lanman = tmp ? tmp : "";
1493 /* not documented or decoded by Ethereal but there is one more
1494 * string in the extra bytes which is the same as the
1495 * PrimaryDomain when using extended security. Windows NT 4
1496 * and 2003 use this string to store the native lanman string.
1497 * Windows 9x does not include a string here at all so we have
1498 * to check if we have any extra bytes left */
1500 byte_count = SVAL(req->vwv+13, 0);
1501 if ( PTR_DIFF(p, save_p) < byte_count) {
1502 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1503 STR_TERMINATE);
1504 primary_domain = tmp ? tmp : "";
1505 } else {
1506 primary_domain = talloc_strdup(talloc_tos(), "null");
1509 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1510 "PrimaryDomain=[%s]\n",
1511 domain, native_os, native_lanman, primary_domain));
1513 if ( ra_type == RA_WIN2K ) {
1514 if ( strlen(native_lanman) == 0 )
1515 ra_lanman_string( primary_domain );
1516 else
1517 ra_lanman_string( native_lanman );
1522 if (SVAL(req->vwv+4, 0) == 0) {
1523 setup_new_vc_session(req->sconn);
1526 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1527 domain, user, get_remote_machine_name()));
1529 if (*user) {
1530 if (sconn->smb1.negprot.spnego) {
1532 /* This has to be here, because this is a perfectly
1533 * valid behaviour for guest logons :-( */
1535 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1536 "at 'normal' session setup after "
1537 "negotiating spnego.\n"));
1538 reply_nterror(req, nt_status_squash(
1539 NT_STATUS_LOGON_FAILURE));
1540 END_PROFILE(SMBsesssetupX);
1541 return;
1543 fstrcpy(sub_user, user);
1544 } else {
1545 fstrcpy(sub_user, lp_guestaccount());
1548 sub_set_smb_name(sub_user);
1550 reload_services(sconn->msg_ctx, sconn->sock, True);
1552 if (lp_security() == SEC_SHARE) {
1553 char *sub_user_mapped = NULL;
1554 /* In share level we should ignore any passwords */
1556 data_blob_free(&lm_resp);
1557 data_blob_free(&nt_resp);
1558 data_blob_clear_free(&plaintext_password);
1560 (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
1561 if (!sub_user_mapped) {
1562 reply_nterror(req, NT_STATUS_NO_MEMORY);
1563 END_PROFILE(SMBsesssetupX);
1564 return;
1566 fstrcpy(sub_user, sub_user_mapped);
1567 add_session_user(sconn, sub_user);
1568 add_session_workgroup(sconn, domain);
1569 /* Then force it to null for the benfit of the code below */
1570 user = "";
1573 if (!*user) {
1575 nt_status = check_guest_password(&server_info);
1577 } else if (doencrypt) {
1578 struct auth_context *negprot_auth_context = NULL;
1579 negprot_auth_context = sconn->smb1.negprot.auth_context;
1580 if (!negprot_auth_context) {
1581 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1582 "session setup without negprot denied!\n"));
1583 reply_nterror(req, nt_status_squash(
1584 NT_STATUS_LOGON_FAILURE));
1585 END_PROFILE(SMBsesssetupX);
1586 return;
1588 nt_status = make_user_info_for_reply_enc(&user_info, user,
1589 domain,
1590 lm_resp, nt_resp);
1591 if (NT_STATUS_IS_OK(nt_status)) {
1592 nt_status = negprot_auth_context->check_ntlm_password(
1593 negprot_auth_context,
1594 user_info,
1595 &server_info);
1597 } else {
1598 struct auth_context *plaintext_auth_context = NULL;
1600 nt_status = make_auth_context_subsystem(
1601 talloc_tos(), &plaintext_auth_context);
1603 if (NT_STATUS_IS_OK(nt_status)) {
1604 uint8_t chal[8];
1606 plaintext_auth_context->get_ntlm_challenge(
1607 plaintext_auth_context, chal);
1609 if (!make_user_info_for_reply(&user_info,
1610 user, domain, chal,
1611 plaintext_password)) {
1612 nt_status = NT_STATUS_NO_MEMORY;
1615 if (NT_STATUS_IS_OK(nt_status)) {
1616 nt_status = plaintext_auth_context->check_ntlm_password(
1617 plaintext_auth_context,
1618 user_info,
1619 &server_info);
1621 TALLOC_FREE(plaintext_auth_context);
1626 free_user_info(&user_info);
1628 if (!NT_STATUS_IS_OK(nt_status)) {
1629 nt_status = do_map_to_guest(nt_status, &server_info,
1630 user, domain);
1633 if (!NT_STATUS_IS_OK(nt_status)) {
1634 data_blob_free(&nt_resp);
1635 data_blob_free(&lm_resp);
1636 data_blob_clear_free(&plaintext_password);
1637 reply_nterror(req, nt_status_squash(nt_status));
1638 END_PROFILE(SMBsesssetupX);
1639 return;
1642 /* Ensure we can't possible take a code path leading to a
1643 * null defref. */
1644 if (!server_info) {
1645 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1646 END_PROFILE(SMBsesssetupX);
1647 return;
1650 if (!server_info->security_token) {
1651 nt_status = create_local_token(server_info);
1653 if (!NT_STATUS_IS_OK(nt_status)) {
1654 DEBUG(10, ("create_local_token failed: %s\n",
1655 nt_errstr(nt_status)));
1656 data_blob_free(&nt_resp);
1657 data_blob_free(&lm_resp);
1658 data_blob_clear_free(&plaintext_password);
1659 reply_nterror(req, nt_status_squash(nt_status));
1660 END_PROFILE(SMBsesssetupX);
1661 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 (server_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(server_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 server info */
1696 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1697 server_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(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;