s3: Fix Coverity ID 2304: FORWARD_NULL
[Samba.git] / source3 / smbd / sesssetup.c
blobb9ff4d32dba3542d178967d6e6b70382f8613213
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"
33 #include "../lib/util/asn1.h"
35 /* For split krb5 SPNEGO blobs. */
36 struct pending_auth_data {
37 struct pending_auth_data *prev, *next;
38 uint16 vuid; /* Tag for this entry. */
39 uint16 smbpid; /* Alternate tag for this entry. */
40 size_t needed_len;
41 DATA_BLOB partial_data;
45 on a logon error possibly map the error to success if "map to guest"
46 is set approriately
48 NTSTATUS do_map_to_guest(NTSTATUS status,
49 struct auth_serversupplied_info **server_info,
50 const char *user, const char *domain)
52 user = user ? user : "";
53 domain = domain ? domain : "";
55 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
56 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
57 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
58 DEBUG(3,("No such user %s [%s] - using guest account\n",
59 user, domain));
60 status = make_server_info_guest(NULL, server_info);
64 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
65 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
66 DEBUG(3,("Registered username %s for guest access\n",
67 user));
68 status = make_server_info_guest(NULL, server_info);
72 return status;
75 /****************************************************************************
76 Add the standard 'Samba' signature to the end of the session setup.
77 ****************************************************************************/
79 static int push_signature(uint8 **outbuf)
81 char *lanman;
82 int result, tmp;
84 result = 0;
86 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
88 if (tmp == -1) return -1;
89 result += tmp;
91 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
92 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
93 SAFE_FREE(lanman);
95 else {
96 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
99 if (tmp == -1) return -1;
100 result += tmp;
102 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
104 if (tmp == -1) return -1;
105 result += tmp;
107 return result;
110 /****************************************************************************
111 Send a security blob via a session setup reply.
112 ****************************************************************************/
114 static void reply_sesssetup_blob(struct smb_request *req,
115 DATA_BLOB blob,
116 NTSTATUS nt_status)
118 if (!NT_STATUS_IS_OK(nt_status) &&
119 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
120 reply_nterror(req, nt_status_squash(nt_status));
121 return;
124 nt_status = nt_status_squash(nt_status);
125 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
126 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
127 SSVAL(req->outbuf, smb_vwv3, blob.length);
129 if ((message_push_blob(&req->outbuf, blob) == -1)
130 || (push_signature(&req->outbuf) == -1)) {
131 reply_nterror(req, NT_STATUS_NO_MEMORY);
135 /****************************************************************************
136 Do a 'guest' logon, getting back the
137 ****************************************************************************/
139 static NTSTATUS check_guest_password(struct auth_serversupplied_info **server_info)
141 struct auth_context *auth_context;
142 struct auth_usersupplied_info *user_info = NULL;
144 NTSTATUS nt_status;
145 static unsigned char chal[8] = { 0, };
147 DEBUG(3,("Got anonymous request\n"));
149 nt_status = make_auth_context_fixed(talloc_tos(), &auth_context, chal);
150 if (!NT_STATUS_IS_OK(nt_status)) {
151 return nt_status;
154 if (!make_user_info_guest(&user_info)) {
155 TALLOC_FREE(auth_context);
156 return NT_STATUS_NO_MEMORY;
159 nt_status = auth_context->check_ntlm_password(auth_context,
160 user_info,
161 server_info);
162 TALLOC_FREE(auth_context);
163 free_user_info(&user_info);
164 return nt_status;
168 #ifdef HAVE_KRB5
170 #if 0
171 /* Experiment that failed. See "only happens with a KDC" comment below. */
172 /****************************************************************************
173 Cerate a clock skew error blob for a Windows client.
174 ****************************************************************************/
176 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
178 krb5_context context = NULL;
179 krb5_error_code kerr = 0;
180 krb5_data reply;
181 krb5_principal host_princ = NULL;
182 char *host_princ_s = NULL;
183 bool ret = False;
185 *pblob_out = data_blob_null;
187 initialize_krb5_error_table();
188 kerr = krb5_init_context(&context);
189 if (kerr) {
190 return False;
192 /* Create server principal. */
193 asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
194 if (!host_princ_s) {
195 goto out;
197 strlower_m(host_princ_s);
199 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
200 if (kerr) {
201 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
202 "for name %s: Error %s\n",
203 host_princ_s, error_message(kerr) ));
204 goto out;
207 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
208 host_princ, &reply);
209 if (kerr) {
210 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
211 "failed: Error %s\n",
212 error_message(kerr) ));
213 goto out;
216 *pblob_out = data_blob(reply.data, reply.length);
217 kerberos_free_data_contents(context,&reply);
218 ret = True;
220 out:
222 if (host_princ_s) {
223 SAFE_FREE(host_princ_s);
225 if (host_princ) {
226 krb5_free_principal(context, host_princ);
228 krb5_free_context(context);
229 return ret;
231 #endif
233 /****************************************************************************
234 Reply to a session setup spnego negotiate packet for kerberos.
235 ****************************************************************************/
237 static void reply_spnego_kerberos(struct smb_request *req,
238 DATA_BLOB *secblob,
239 const char *mechOID,
240 uint16 vuid,
241 bool *p_invalidate_vuid)
243 TALLOC_CTX *mem_ctx;
244 DATA_BLOB ticket;
245 struct passwd *pw;
246 int sess_vuid = req->vuid;
247 NTSTATUS ret = NT_STATUS_OK;
248 DATA_BLOB ap_rep, ap_rep_wrapped, response;
249 struct auth_serversupplied_info *server_info = NULL;
250 DATA_BLOB session_key = data_blob_null;
251 uint8 tok_id[2];
252 DATA_BLOB nullblob = data_blob_null;
253 bool map_domainuser_to_guest = False;
254 bool username_was_mapped;
255 struct PAC_LOGON_INFO *logon_info = NULL;
256 struct smbd_server_connection *sconn = req->sconn;
257 char *principal;
258 char *user;
259 char *domain;
260 char *real_username;
262 ZERO_STRUCT(ticket);
263 ZERO_STRUCT(ap_rep);
264 ZERO_STRUCT(ap_rep_wrapped);
265 ZERO_STRUCT(response);
267 /* Normally we will always invalidate the intermediate vuid. */
268 *p_invalidate_vuid = True;
270 mem_ctx = talloc_init("reply_spnego_kerberos");
271 if (mem_ctx == NULL) {
272 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
273 return;
276 if (!spnego_parse_krb5_wrap(mem_ctx, *secblob, &ticket, tok_id)) {
277 talloc_destroy(mem_ctx);
278 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
279 return;
282 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
283 &principal, &logon_info, &ap_rep,
284 &session_key, True);
286 data_blob_free(&ticket);
288 if (!NT_STATUS_IS_OK(ret)) {
289 #if 0
290 /* Experiment that failed.
291 * See "only happens with a KDC" comment below. */
293 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
296 * Windows in this case returns
297 * NT_STATUS_MORE_PROCESSING_REQUIRED
298 * with a negTokenTarg blob containing an krb5_error
299 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
300 * The client then fixes its clock and continues rather
301 * than giving an error. JRA.
302 * -- Looks like this only happens with a KDC. JRA.
305 bool ok = make_krb5_skew_error(&ap_rep);
306 if (!ok) {
307 talloc_destroy(mem_ctx);
308 return ERROR_NT(nt_status_squash(
309 NT_STATUS_LOGON_FAILURE));
311 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
312 TOK_ID_KRB_ERROR);
313 response = spnego_gen_auth_response(&ap_rep_wrapped,
314 ret, OID_KERBEROS5_OLD);
315 reply_sesssetup_blob(conn, inbuf, outbuf, response,
316 NT_STATUS_MORE_PROCESSING_REQUIRED);
319 * In this one case we don't invalidate the
320 * intermediate vuid as we're expecting the client
321 * to re-use it for the next sessionsetupX packet. JRA.
324 *p_invalidate_vuid = False;
326 data_blob_free(&ap_rep);
327 data_blob_free(&ap_rep_wrapped);
328 data_blob_free(&response);
329 talloc_destroy(mem_ctx);
330 return -1; /* already replied */
332 #else
333 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
334 ret = NT_STATUS_LOGON_FAILURE;
336 #endif
337 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
338 nt_errstr(ret)));
339 talloc_destroy(mem_ctx);
340 reply_nterror(req, nt_status_squash(ret));
341 return;
344 ret = get_user_from_kerberos_info(talloc_tos(),
345 sconn->client_id.name,
346 principal, logon_info,
347 &username_was_mapped,
348 &map_domainuser_to_guest,
349 &user, &domain,
350 &real_username, &pw);
351 if (!NT_STATUS_IS_OK(ret)) {
352 data_blob_free(&ap_rep);
353 data_blob_free(&session_key);
354 talloc_destroy(mem_ctx);
355 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
356 return;
359 /* save the PAC data if we have it */
360 if (logon_info) {
361 netsamlogon_cache_store(user, &logon_info->info3);
364 /* setup the string used by %U */
365 sub_set_smb_name(real_username);
367 /* reload services so that the new %U is taken into account */
368 reload_services(sconn->msg_ctx, sconn->sock, True);
370 ret = make_server_info_krb5(mem_ctx,
371 user, domain, real_username, pw,
372 logon_info, map_domainuser_to_guest,
373 &server_info);
374 if (!NT_STATUS_IS_OK(ret)) {
375 DEBUG(1, ("make_server_info_krb5 failed!\n"));
376 data_blob_free(&ap_rep);
377 data_blob_free(&session_key);
378 TALLOC_FREE(mem_ctx);
379 reply_nterror(req, nt_status_squash(ret));
380 return;
383 server_info->nss_token |= username_was_mapped;
385 /* we need to build the token for the user. make_server_info_guest()
386 already does this */
388 if ( !server_info->security_token ) {
389 ret = create_local_token( server_info );
390 if ( !NT_STATUS_IS_OK(ret) ) {
391 DEBUG(10,("failed to create local token: %s\n",
392 nt_errstr(ret)));
393 data_blob_free(&ap_rep);
394 data_blob_free(&session_key);
395 TALLOC_FREE( mem_ctx );
396 TALLOC_FREE( server_info );
397 reply_nterror(req, nt_status_squash(ret));
398 return;
402 if (!is_partial_auth_vuid(sconn, sess_vuid)) {
403 sess_vuid = register_initial_vuid(sconn);
406 data_blob_free(&server_info->user_session_key);
407 /* Set the kerberos-derived session key onto the server_info */
408 server_info->user_session_key = session_key;
409 talloc_steal(server_info, session_key.data);
411 session_key = data_blob_null;
413 /* register_existing_vuid keeps the server info */
414 /* register_existing_vuid takes ownership of session_key on success,
415 * no need to free after this on success. A better interface would copy
416 * it.... */
418 sess_vuid = register_existing_vuid(sconn, sess_vuid,
419 server_info, nullblob, user);
421 reply_outbuf(req, 4, 0);
422 SSVAL(req->outbuf,smb_uid,sess_vuid);
424 if (sess_vuid == UID_FIELD_INVALID ) {
425 ret = NT_STATUS_LOGON_FAILURE;
426 } else {
427 /* current_user_info is changed on new vuid */
428 reload_services(sconn->msg_ctx, sconn->sock, True);
430 SSVAL(req->outbuf, smb_vwv3, 0);
432 if (server_info->guest) {
433 SSVAL(req->outbuf,smb_vwv2,1);
436 SSVAL(req->outbuf, smb_uid, sess_vuid);
438 /* Successful logon. Keep this vuid. */
439 *p_invalidate_vuid = False;
442 /* wrap that up in a nice GSS-API wrapping */
443 if (NT_STATUS_IS_OK(ret)) {
444 ap_rep_wrapped = spnego_gen_krb5_wrap(talloc_tos(), ap_rep,
445 TOK_ID_KRB_AP_REP);
446 } else {
447 ap_rep_wrapped = data_blob_null;
449 response = spnego_gen_auth_response(talloc_tos(), &ap_rep_wrapped, ret,
450 mechOID);
451 reply_sesssetup_blob(req, response, ret);
453 data_blob_free(&ap_rep);
454 data_blob_free(&ap_rep_wrapped);
455 data_blob_free(&response);
456 TALLOC_FREE(mem_ctx);
459 #endif
461 /****************************************************************************
462 Send a session setup reply, wrapped in SPNEGO.
463 Get vuid and check first.
464 End the NTLMSSP exchange context if we are OK/complete fail
465 This should be split into two functions, one to handle each
466 leg of the NTLM auth steps.
467 ***************************************************************************/
469 static void reply_spnego_ntlmssp(struct smb_request *req,
470 uint16 vuid,
471 struct auth_ntlmssp_state **auth_ntlmssp_state,
472 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
473 const char *OID,
474 bool wrap)
476 bool do_invalidate = true;
477 DATA_BLOB response;
478 struct auth_serversupplied_info *session_info = NULL;
479 struct smbd_server_connection *sconn = req->sconn;
481 if (NT_STATUS_IS_OK(nt_status)) {
482 nt_status = auth_ntlmssp_steal_session_info(talloc_tos(),
483 (*auth_ntlmssp_state), &session_info);
484 } else {
485 /* Note that this session_info won't have a session
486 * key. But for map to guest, that's exactly the right
487 * thing - we can't reasonably guess the key the
488 * client wants, as the password was wrong */
489 nt_status = do_map_to_guest(nt_status,
490 &session_info,
491 auth_ntlmssp_get_username(*auth_ntlmssp_state),
492 auth_ntlmssp_get_domain(*auth_ntlmssp_state));
495 reply_outbuf(req, 4, 0);
497 SSVAL(req->outbuf, smb_uid, vuid);
499 if (NT_STATUS_IS_OK(nt_status)) {
500 DATA_BLOB nullblob = data_blob_null;
502 if (!is_partial_auth_vuid(sconn, vuid)) {
503 nt_status = NT_STATUS_LOGON_FAILURE;
504 goto out;
507 /* register_existing_vuid keeps the server info */
508 if (register_existing_vuid(sconn, vuid,
509 session_info, nullblob,
510 auth_ntlmssp_get_username(*auth_ntlmssp_state)) !=
511 vuid) {
512 /* The problem is, *auth_ntlmssp_state points
513 * into the vuser this will have
514 * talloc_free()'ed in
515 * register_existing_vuid() */
516 do_invalidate = false;
517 nt_status = NT_STATUS_LOGON_FAILURE;
518 goto out;
521 /* current_user_info is changed on new vuid */
522 reload_services(sconn->msg_ctx, sconn->sock, True);
524 SSVAL(req->outbuf, smb_vwv3, 0);
526 if (session_info->guest) {
527 SSVAL(req->outbuf,smb_vwv2,1);
531 out:
533 if (wrap) {
534 response = spnego_gen_auth_response(talloc_tos(),
535 ntlmssp_blob,
536 nt_status, OID);
537 } else {
538 response = *ntlmssp_blob;
541 reply_sesssetup_blob(req, response, nt_status);
542 if (wrap) {
543 data_blob_free(&response);
546 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
547 and the other end, that we are not finished yet. */
549 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
550 /* NB. This is *NOT* an error case. JRA */
551 if (do_invalidate) {
552 TALLOC_FREE(*auth_ntlmssp_state);
553 if (!NT_STATUS_IS_OK(nt_status)) {
554 /* Kill the intermediate vuid */
555 invalidate_vuid(sconn, vuid);
561 /****************************************************************************
562 Is this a krb5 mechanism ?
563 ****************************************************************************/
565 NTSTATUS parse_spnego_mechanisms(TALLOC_CTX *ctx,
566 DATA_BLOB blob_in,
567 DATA_BLOB *pblob_out,
568 char **kerb_mechOID)
570 char *OIDs[ASN1_MAX_OIDS];
571 int i;
572 NTSTATUS ret = NT_STATUS_OK;
574 *kerb_mechOID = NULL;
576 /* parse out the OIDs and the first sec blob */
577 if (!spnego_parse_negTokenInit(ctx, blob_in, OIDs, NULL, pblob_out) ||
578 (OIDs[0] == NULL)) {
579 return NT_STATUS_LOGON_FAILURE;
582 /* only look at the first OID for determining the mechToken --
583 according to RFC2478, we should choose the one we want
584 and renegotiate, but i smell a client bug here..
586 Problem observed when connecting to a member (samba box)
587 of an AD domain as a user in a Samba domain. Samba member
588 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
589 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
590 NTLMSSP mechtoken. --jerry */
592 #ifdef HAVE_KRB5
593 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
594 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
595 *kerb_mechOID = talloc_strdup(ctx, OIDs[0]);
596 if (*kerb_mechOID == NULL) {
597 ret = NT_STATUS_NO_MEMORY;
600 #endif
602 for (i=0;OIDs[i];i++) {
603 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
604 talloc_free(OIDs[i]);
606 return ret;
609 /****************************************************************************
610 Fall back from krb5 to NTLMSSP.
611 ****************************************************************************/
613 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
614 uint16 vuid)
616 DATA_BLOB response;
618 reply_outbuf(req, 4, 0);
619 SSVAL(req->outbuf,smb_uid,vuid);
621 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
622 "but set to downgrade to NTLMSSP\n"));
624 response = spnego_gen_auth_response(talloc_tos(), NULL,
625 NT_STATUS_MORE_PROCESSING_REQUIRED,
626 OID_NTLMSSP);
627 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
628 data_blob_free(&response);
631 /****************************************************************************
632 Reply to a session setup spnego negotiate packet.
633 ****************************************************************************/
635 static void reply_spnego_negotiate(struct smb_request *req,
636 uint16 vuid,
637 DATA_BLOB blob1,
638 struct auth_ntlmssp_state **auth_ntlmssp_state)
640 DATA_BLOB secblob;
641 DATA_BLOB chal;
642 char *kerb_mech = NULL;
643 NTSTATUS status;
644 struct smbd_server_connection *sconn = req->sconn;
646 status = parse_spnego_mechanisms(talloc_tos(),
647 blob1, &secblob, &kerb_mech);
648 if (!NT_STATUS_IS_OK(status)) {
649 /* Kill the intermediate vuid */
650 invalidate_vuid(sconn, vuid);
651 reply_nterror(req, nt_status_squash(status));
652 return;
655 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
656 (unsigned long)secblob.length));
658 #ifdef HAVE_KRB5
659 if (kerb_mech && ((lp_security()==SEC_ADS) ||
660 USE_KERBEROS_KEYTAB) ) {
661 bool destroy_vuid = True;
662 reply_spnego_kerberos(req, &secblob, kerb_mech,
663 vuid, &destroy_vuid);
664 data_blob_free(&secblob);
665 if (destroy_vuid) {
666 /* Kill the intermediate vuid */
667 invalidate_vuid(sconn, vuid);
669 TALLOC_FREE(kerb_mech);
670 return;
672 #endif
674 TALLOC_FREE(*auth_ntlmssp_state);
676 if (kerb_mech) {
677 data_blob_free(&secblob);
678 /* The mechtoken is a krb5 ticket, but
679 * we need to fall back to NTLM. */
680 reply_spnego_downgrade_to_ntlmssp(req, vuid);
681 TALLOC_FREE(kerb_mech);
682 return;
685 status = auth_ntlmssp_start(auth_ntlmssp_state);
686 if (!NT_STATUS_IS_OK(status)) {
687 /* Kill the intermediate vuid */
688 invalidate_vuid(sconn, vuid);
689 reply_nterror(req, nt_status_squash(status));
690 return;
693 status = auth_ntlmssp_update(*auth_ntlmssp_state,
694 secblob, &chal);
696 data_blob_free(&secblob);
698 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
699 &chal, status, OID_NTLMSSP, true);
701 data_blob_free(&chal);
703 /* already replied */
704 return;
707 /****************************************************************************
708 Reply to a session setup spnego auth packet.
709 ****************************************************************************/
711 static void reply_spnego_auth(struct smb_request *req,
712 uint16 vuid,
713 DATA_BLOB blob1,
714 struct auth_ntlmssp_state **auth_ntlmssp_state)
716 DATA_BLOB auth = data_blob_null;
717 DATA_BLOB auth_reply = data_blob_null;
718 DATA_BLOB secblob = data_blob_null;
719 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
720 struct smbd_server_connection *sconn = req->sconn;
722 if (!spnego_parse_auth(talloc_tos(), blob1, &auth)) {
723 #if 0
724 file_save("auth.dat", blob1.data, blob1.length);
725 #endif
726 /* Kill the intermediate vuid */
727 invalidate_vuid(sconn, vuid);
729 reply_nterror(req, nt_status_squash(
730 NT_STATUS_LOGON_FAILURE));
731 return;
734 if (auth.data[0] == ASN1_APPLICATION(0)) {
735 /* Might be a second negTokenTarg packet */
736 char *kerb_mech = NULL;
738 status = parse_spnego_mechanisms(talloc_tos(),
739 auth, &secblob, &kerb_mech);
741 if (!NT_STATUS_IS_OK(status)) {
742 /* Kill the intermediate vuid */
743 invalidate_vuid(sconn, vuid);
744 reply_nterror(req, nt_status_squash(status));
745 return;
748 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
749 (unsigned long)secblob.length));
750 #ifdef HAVE_KRB5
751 if (kerb_mech && ((lp_security()==SEC_ADS) ||
752 USE_KERBEROS_KEYTAB)) {
753 bool destroy_vuid = True;
754 reply_spnego_kerberos(req, &secblob, kerb_mech,
755 vuid, &destroy_vuid);
756 data_blob_free(&secblob);
757 data_blob_free(&auth);
758 if (destroy_vuid) {
759 /* Kill the intermediate vuid */
760 invalidate_vuid(sconn, vuid);
762 TALLOC_FREE(kerb_mech);
763 return;
765 #endif
766 /* Can't blunder into NTLMSSP auth if we have
767 * a krb5 ticket. */
769 if (kerb_mech) {
770 /* Kill the intermediate vuid */
771 invalidate_vuid(sconn, vuid);
772 DEBUG(3,("reply_spnego_auth: network "
773 "misconfiguration, client sent us a "
774 "krb5 ticket and kerberos security "
775 "not enabled\n"));
776 reply_nterror(req, nt_status_squash(
777 NT_STATUS_LOGON_FAILURE));
778 TALLOC_FREE(kerb_mech);
782 /* If we get here it wasn't a negTokenTarg auth packet. */
783 data_blob_free(&secblob);
785 if (!*auth_ntlmssp_state) {
786 status = auth_ntlmssp_start(auth_ntlmssp_state);
787 if (!NT_STATUS_IS_OK(status)) {
788 /* Kill the intermediate vuid */
789 invalidate_vuid(sconn, vuid);
790 reply_nterror(req, nt_status_squash(status));
791 return;
795 status = auth_ntlmssp_update(*auth_ntlmssp_state,
796 auth, &auth_reply);
798 data_blob_free(&auth);
800 /* Don't send the mechid as we've already sent this (RFC4178). */
802 reply_spnego_ntlmssp(req, vuid,
803 auth_ntlmssp_state,
804 &auth_reply, status, NULL, true);
806 data_blob_free(&auth_reply);
808 /* and tell smbd that we have already replied to this packet */
809 return;
812 /****************************************************************************
813 Delete an entry on the list.
814 ****************************************************************************/
816 static void delete_partial_auth(struct smbd_server_connection *sconn,
817 struct pending_auth_data *pad)
819 if (!pad) {
820 return;
822 DLIST_REMOVE(sconn->smb1.pd_list, pad);
823 data_blob_free(&pad->partial_data);
824 SAFE_FREE(pad);
827 /****************************************************************************
828 Search for a partial SPNEGO auth fragment matching an smbpid.
829 ****************************************************************************/
831 static struct pending_auth_data *get_pending_auth_data(
832 struct smbd_server_connection *sconn,
833 uint16_t smbpid)
835 struct pending_auth_data *pad;
837 * NOTE: using the smbpid here is completely wrong...
838 * see [MS-SMB]
839 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
841 for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
842 if (pad->smbpid == smbpid) {
843 break;
846 return pad;
849 /****************************************************************************
850 Check the size of an SPNEGO blob. If we need more return
851 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
852 the blob to be more than 64k.
853 ****************************************************************************/
855 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
856 uint16 smbpid, uint16 vuid,
857 DATA_BLOB *pblob)
859 struct pending_auth_data *pad = NULL;
860 ASN1_DATA *data;
861 size_t needed_len = 0;
863 pad = get_pending_auth_data(sconn, smbpid);
865 /* Ensure we have some data. */
866 if (pblob->length == 0) {
867 /* Caller can cope. */
868 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
869 delete_partial_auth(sconn, pad);
870 return NT_STATUS_OK;
873 /* Were we waiting for more data ? */
874 if (pad) {
875 DATA_BLOB tmp_blob;
876 size_t copy_len = MIN(65536, pblob->length);
878 /* Integer wrap paranoia.... */
880 if (pad->partial_data.length + copy_len <
881 pad->partial_data.length ||
882 pad->partial_data.length + copy_len < copy_len) {
884 DEBUG(2,("check_spnego_blob_complete: integer wrap "
885 "pad->partial_data.length = %u, "
886 "copy_len = %u\n",
887 (unsigned int)pad->partial_data.length,
888 (unsigned int)copy_len ));
890 delete_partial_auth(sconn, pad);
891 return NT_STATUS_INVALID_PARAMETER;
894 DEBUG(10,("check_spnego_blob_complete: "
895 "pad->partial_data.length = %u, "
896 "pad->needed_len = %u, "
897 "copy_len = %u, "
898 "pblob->length = %u,\n",
899 (unsigned int)pad->partial_data.length,
900 (unsigned int)pad->needed_len,
901 (unsigned int)copy_len,
902 (unsigned int)pblob->length ));
904 tmp_blob = data_blob(NULL,
905 pad->partial_data.length + copy_len);
907 /* Concatenate the two (up to copy_len) bytes. */
908 memcpy(tmp_blob.data,
909 pad->partial_data.data,
910 pad->partial_data.length);
911 memcpy(tmp_blob.data + pad->partial_data.length,
912 pblob->data,
913 copy_len);
915 /* Replace the partial data. */
916 data_blob_free(&pad->partial_data);
917 pad->partial_data = tmp_blob;
918 ZERO_STRUCT(tmp_blob);
920 /* Are we done ? */
921 if (pblob->length >= pad->needed_len) {
922 /* Yes, replace pblob. */
923 data_blob_free(pblob);
924 *pblob = pad->partial_data;
925 ZERO_STRUCT(pad->partial_data);
926 delete_partial_auth(sconn, pad);
927 return NT_STATUS_OK;
930 /* Still need more data. */
931 pad->needed_len -= copy_len;
932 return NT_STATUS_MORE_PROCESSING_REQUIRED;
935 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
936 (pblob->data[0] != ASN1_CONTEXT(1))) {
937 /* Not something we can determine the
938 * length of.
940 return NT_STATUS_OK;
943 /* This is a new SPNEGO sessionsetup - see if
944 * the data given in this blob is enough.
947 data = asn1_init(NULL);
948 if (data == NULL) {
949 return NT_STATUS_NO_MEMORY;
952 asn1_load(data, *pblob);
953 asn1_start_tag(data, pblob->data[0]);
954 if (data->has_error || data->nesting == NULL) {
955 asn1_free(data);
956 /* Let caller catch. */
957 return NT_STATUS_OK;
960 /* Integer wrap paranoia.... */
962 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
963 data->nesting->taglen + data->nesting->start < data->nesting->start) {
965 DEBUG(2,("check_spnego_blob_complete: integer wrap "
966 "data.nesting->taglen = %u, "
967 "data.nesting->start = %u\n",
968 (unsigned int)data->nesting->taglen,
969 (unsigned int)data->nesting->start ));
971 asn1_free(data);
972 return NT_STATUS_INVALID_PARAMETER;
975 /* Total length of the needed asn1 is the tag length
976 * plus the current offset. */
978 needed_len = data->nesting->taglen + data->nesting->start;
979 asn1_free(data);
981 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
982 "pblob->length = %u\n",
983 (unsigned int)needed_len,
984 (unsigned int)pblob->length ));
986 if (needed_len <= pblob->length) {
987 /* Nothing to do - blob is complete. */
988 return NT_STATUS_OK;
991 /* Refuse the blob if it's bigger than 64k. */
992 if (needed_len > 65536) {
993 DEBUG(2,("check_spnego_blob_complete: needed_len "
994 "too large (%u)\n",
995 (unsigned int)needed_len ));
996 return NT_STATUS_INVALID_PARAMETER;
999 /* We must store this blob until complete. */
1000 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1001 return NT_STATUS_NO_MEMORY;
1003 pad->needed_len = needed_len - pblob->length;
1004 pad->partial_data = data_blob(pblob->data, pblob->length);
1005 if (pad->partial_data.data == NULL) {
1006 SAFE_FREE(pad);
1007 return NT_STATUS_NO_MEMORY;
1009 pad->smbpid = smbpid;
1010 pad->vuid = vuid;
1011 DLIST_ADD(sconn->smb1.pd_list, pad);
1013 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1016 /****************************************************************************
1017 Reply to a session setup command.
1018 conn POINTER CAN BE NULL HERE !
1019 ****************************************************************************/
1021 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1023 const uint8 *p;
1024 DATA_BLOB blob1;
1025 size_t bufrem;
1026 char *tmp;
1027 const char *native_os;
1028 const char *native_lanman;
1029 const char *primary_domain;
1030 const char *p2;
1031 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1032 enum remote_arch_types ra_type = get_remote_arch();
1033 int vuid = req->vuid;
1034 user_struct *vuser = NULL;
1035 NTSTATUS status = NT_STATUS_OK;
1036 uint16 smbpid = req->smbpid;
1037 struct smbd_server_connection *sconn = req->sconn;
1039 DEBUG(3,("Doing spnego session setup\n"));
1041 if (global_client_caps == 0) {
1042 global_client_caps = IVAL(req->vwv+10, 0);
1044 if (!(global_client_caps & CAP_STATUS32)) {
1045 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1050 p = req->buf;
1052 if (data_blob_len == 0) {
1053 /* an invalid request */
1054 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1055 return;
1058 bufrem = smbreq_bufrem(req, p);
1059 /* pull the spnego blob */
1060 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1062 #if 0
1063 file_save("negotiate.dat", blob1.data, blob1.length);
1064 #endif
1066 p2 = (char *)req->buf + blob1.length;
1068 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1069 STR_TERMINATE);
1070 native_os = tmp ? tmp : "";
1072 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1073 STR_TERMINATE);
1074 native_lanman = tmp ? tmp : "";
1076 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1077 STR_TERMINATE);
1078 primary_domain = tmp ? tmp : "";
1080 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1081 native_os, native_lanman, primary_domain));
1083 if ( ra_type == RA_WIN2K ) {
1084 /* Vista sets neither the OS or lanman strings */
1086 if ( !strlen(native_os) && !strlen(native_lanman) )
1087 set_remote_arch(RA_VISTA);
1089 /* Windows 2003 doesn't set the native lanman string,
1090 but does set primary domain which is a bug I think */
1092 if ( !strlen(native_lanman) ) {
1093 ra_lanman_string( primary_domain );
1094 } else {
1095 ra_lanman_string( native_lanman );
1097 } else if ( ra_type == RA_VISTA ) {
1098 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
1099 set_remote_arch(RA_OSX);
1103 /* Did we get a valid vuid ? */
1104 if (!is_partial_auth_vuid(sconn, vuid)) {
1105 /* No, then try and see if this is an intermediate sessionsetup
1106 * for a large SPNEGO packet. */
1107 struct pending_auth_data *pad;
1108 pad = get_pending_auth_data(sconn, smbpid);
1109 if (pad) {
1110 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1111 "pending vuid %u\n",
1112 (unsigned int)pad->vuid ));
1113 vuid = pad->vuid;
1117 /* Do we have a valid vuid now ? */
1118 if (!is_partial_auth_vuid(sconn, vuid)) {
1119 /* No, start a new authentication setup. */
1120 vuid = register_initial_vuid(sconn);
1121 if (vuid == UID_FIELD_INVALID) {
1122 data_blob_free(&blob1);
1123 reply_nterror(req, nt_status_squash(
1124 NT_STATUS_INVALID_PARAMETER));
1125 return;
1129 vuser = get_partial_auth_user_struct(sconn, vuid);
1130 /* This MUST be valid. */
1131 if (!vuser) {
1132 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1135 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1136 * sessionsetup requests as the Windows limit on the security blob
1137 * field is 4k. Bug #4400. JRA.
1140 status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1141 if (!NT_STATUS_IS_OK(status)) {
1142 if (!NT_STATUS_EQUAL(status,
1143 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1144 /* Real error - kill the intermediate vuid */
1145 invalidate_vuid(sconn, vuid);
1147 data_blob_free(&blob1);
1148 reply_nterror(req, nt_status_squash(status));
1149 return;
1152 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1154 /* its a negTokenTarg packet */
1156 reply_spnego_negotiate(req, vuid, blob1,
1157 &vuser->auth_ntlmssp_state);
1158 data_blob_free(&blob1);
1159 return;
1162 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1164 /* its a auth packet */
1166 reply_spnego_auth(req, vuid, blob1,
1167 &vuser->auth_ntlmssp_state);
1168 data_blob_free(&blob1);
1169 return;
1172 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1173 DATA_BLOB chal;
1175 if (!vuser->auth_ntlmssp_state) {
1176 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1177 if (!NT_STATUS_IS_OK(status)) {
1178 /* Kill the intermediate vuid */
1179 invalidate_vuid(sconn, vuid);
1180 data_blob_free(&blob1);
1181 reply_nterror(req, nt_status_squash(status));
1182 return;
1186 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1187 blob1, &chal);
1189 data_blob_free(&blob1);
1191 reply_spnego_ntlmssp(req, vuid,
1192 &vuser->auth_ntlmssp_state,
1193 &chal, status, OID_NTLMSSP, false);
1194 data_blob_free(&chal);
1195 return;
1198 /* what sort of packet is this? */
1199 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1201 data_blob_free(&blob1);
1203 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1206 /****************************************************************************
1207 On new VC == 0, shutdown *all* old connections and users.
1208 It seems that only NT4.x does this. At W2K and above (XP etc.).
1209 a new session setup with VC==0 is ignored.
1210 ****************************************************************************/
1212 struct shutdown_state {
1213 const char *ip;
1214 struct messaging_context *msg_ctx;
1217 static int shutdown_other_smbds(const struct connections_key *key,
1218 const struct connections_data *crec,
1219 void *private_data)
1221 struct shutdown_state *state = (struct shutdown_state *)private_data;
1223 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
1224 procid_str(talloc_tos(), &crec->pid), crec->addr));
1226 if (!process_exists(crec->pid)) {
1227 DEBUG(10, ("process does not exist\n"));
1228 return 0;
1231 if (procid_is_me(&crec->pid)) {
1232 DEBUG(10, ("It's me\n"));
1233 return 0;
1236 if (strcmp(state->ip, crec->addr) != 0) {
1237 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
1238 return 0;
1241 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
1242 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
1243 state->ip));
1245 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
1246 &data_blob_null);
1247 return 0;
1250 static void setup_new_vc_session(struct smbd_server_connection *sconn)
1252 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1253 "compatible we would close all old resources.\n"));
1254 #if 0
1255 conn_close_all();
1256 invalidate_all_vuids();
1257 #endif
1258 if (lp_reset_on_zero_vc()) {
1259 char *addr;
1260 struct shutdown_state state;
1262 addr = tsocket_address_inet_addr_string(
1263 sconn->remote_address, talloc_tos());
1264 if (addr == NULL) {
1265 return;
1267 state.ip = addr;
1268 state.msg_ctx = sconn->msg_ctx;
1269 connections_forall_read(shutdown_other_smbds, &state);
1270 TALLOC_FREE(addr);
1274 /****************************************************************************
1275 Reply to a session setup command.
1276 ****************************************************************************/
1278 void reply_sesssetup_and_X(struct smb_request *req)
1280 int sess_vuid;
1281 int smb_bufsize;
1282 DATA_BLOB lm_resp;
1283 DATA_BLOB nt_resp;
1284 DATA_BLOB plaintext_password;
1285 char *tmp;
1286 const char *user;
1287 fstring sub_user; /* Sanitised username for substituion */
1288 const char *domain;
1289 const char *native_os;
1290 const char *native_lanman;
1291 const char *primary_domain;
1292 struct auth_usersupplied_info *user_info = NULL;
1293 struct auth_serversupplied_info *server_info = NULL;
1294 uint16 smb_flag2 = req->flags2;
1296 NTSTATUS nt_status;
1297 struct smbd_server_connection *sconn = req->sconn;
1299 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1301 START_PROFILE(SMBsesssetupX);
1303 ZERO_STRUCT(lm_resp);
1304 ZERO_STRUCT(nt_resp);
1305 ZERO_STRUCT(plaintext_password);
1307 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1309 /* a SPNEGO session setup has 12 command words, whereas a normal
1310 NT1 session setup has 13. See the cifs spec. */
1311 if (req->wct == 12 &&
1312 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1314 if (!sconn->smb1.negprot.spnego) {
1315 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1316 "at SPNEGO session setup when it was not "
1317 "negotiated.\n"));
1318 reply_nterror(req, nt_status_squash(
1319 NT_STATUS_LOGON_FAILURE));
1320 END_PROFILE(SMBsesssetupX);
1321 return;
1324 if (SVAL(req->vwv+4, 0) == 0) {
1325 setup_new_vc_session(req->sconn);
1328 reply_sesssetup_and_X_spnego(req);
1329 END_PROFILE(SMBsesssetupX);
1330 return;
1333 smb_bufsize = SVAL(req->vwv+2, 0);
1335 if (get_Protocol() < PROTOCOL_NT1) {
1336 uint16 passlen1 = SVAL(req->vwv+7, 0);
1338 /* Never do NT status codes with protocols before NT1 as we
1339 * don't get client caps. */
1340 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1342 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1343 reply_nterror(req, nt_status_squash(
1344 NT_STATUS_INVALID_PARAMETER));
1345 END_PROFILE(SMBsesssetupX);
1346 return;
1349 if (doencrypt) {
1350 lm_resp = data_blob(req->buf, passlen1);
1351 } else {
1352 plaintext_password = data_blob(req->buf, passlen1+1);
1353 /* Ensure null termination */
1354 plaintext_password.data[passlen1] = 0;
1357 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1358 req->buf + passlen1, STR_TERMINATE);
1359 user = tmp ? tmp : "";
1361 domain = "";
1363 } else {
1364 uint16 passlen1 = SVAL(req->vwv+7, 0);
1365 uint16 passlen2 = SVAL(req->vwv+8, 0);
1366 enum remote_arch_types ra_type = get_remote_arch();
1367 const uint8_t *p = req->buf;
1368 const uint8_t *save_p = req->buf;
1369 uint16 byte_count;
1372 if(global_client_caps == 0) {
1373 global_client_caps = IVAL(req->vwv+11, 0);
1375 if (!(global_client_caps & CAP_STATUS32)) {
1376 remove_from_common_flags2(
1377 FLAGS2_32_BIT_ERROR_CODES);
1380 /* client_caps is used as final determination if
1381 * client is NT or Win95. This is needed to return
1382 * the correct error codes in some circumstances.
1385 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1386 ra_type == RA_WIN95) {
1387 if(!(global_client_caps & (CAP_NT_SMBS|
1388 CAP_STATUS32))) {
1389 set_remote_arch( RA_WIN95);
1394 if (!doencrypt) {
1395 /* both Win95 and WinNT stuff up the password
1396 * lengths for non-encrypting systems. Uggh.
1398 if passlen1==24 its a win95 system, and its setting
1399 the password length incorrectly. Luckily it still
1400 works with the default code because Win95 will null
1401 terminate the password anyway
1403 if passlen1>0 and passlen2>0 then maybe its a NT box
1404 and its setting passlen2 to some random value which
1405 really stuffs things up. we need to fix that one. */
1407 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1408 passlen2 != 1) {
1409 passlen2 = 0;
1413 /* check for nasty tricks */
1414 if (passlen1 > MAX_PASS_LEN
1415 || passlen1 > smbreq_bufrem(req, p)) {
1416 reply_nterror(req, nt_status_squash(
1417 NT_STATUS_INVALID_PARAMETER));
1418 END_PROFILE(SMBsesssetupX);
1419 return;
1422 if (passlen2 > MAX_PASS_LEN
1423 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1424 reply_nterror(req, nt_status_squash(
1425 NT_STATUS_INVALID_PARAMETER));
1426 END_PROFILE(SMBsesssetupX);
1427 return;
1430 /* Save the lanman2 password and the NT md4 password. */
1432 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1433 doencrypt = False;
1436 if (doencrypt) {
1437 lm_resp = data_blob(p, passlen1);
1438 nt_resp = data_blob(p+passlen1, passlen2);
1439 } else if (lp_security() != SEC_SHARE) {
1441 * In share level we should ignore any passwords, so
1442 * only read them if we're not.
1444 char *pass = NULL;
1445 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1447 if (unic && (passlen2 == 0) && passlen1) {
1448 /* Only a ascii plaintext password was sent. */
1449 (void)srvstr_pull_talloc(talloc_tos(),
1450 req->inbuf,
1451 req->flags2,
1452 &pass,
1453 req->buf,
1454 passlen1,
1455 STR_TERMINATE|STR_ASCII);
1456 } else {
1457 (void)srvstr_pull_talloc(talloc_tos(),
1458 req->inbuf,
1459 req->flags2,
1460 &pass,
1461 req->buf,
1462 unic ? passlen2 : passlen1,
1463 STR_TERMINATE);
1465 if (!pass) {
1466 reply_nterror(req, nt_status_squash(
1467 NT_STATUS_INVALID_PARAMETER));
1468 END_PROFILE(SMBsesssetupX);
1469 return;
1471 plaintext_password = data_blob(pass, strlen(pass)+1);
1474 p += passlen1 + passlen2;
1476 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1477 STR_TERMINATE);
1478 user = tmp ? tmp : "";
1480 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1481 STR_TERMINATE);
1482 domain = tmp ? tmp : "";
1484 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1485 STR_TERMINATE);
1486 native_os = tmp ? tmp : "";
1488 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1489 STR_TERMINATE);
1490 native_lanman = tmp ? tmp : "";
1492 /* not documented or decoded by Ethereal but there is one more
1493 * string in the extra bytes which is the same as the
1494 * PrimaryDomain when using extended security. Windows NT 4
1495 * and 2003 use this string to store the native lanman string.
1496 * Windows 9x does not include a string here at all so we have
1497 * to check if we have any extra bytes left */
1499 byte_count = SVAL(req->vwv+13, 0);
1500 if ( PTR_DIFF(p, save_p) < byte_count) {
1501 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1502 STR_TERMINATE);
1503 primary_domain = tmp ? tmp : "";
1504 } else {
1505 primary_domain = talloc_strdup(talloc_tos(), "null");
1508 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1509 "PrimaryDomain=[%s]\n",
1510 domain, native_os, native_lanman, primary_domain));
1512 if ( ra_type == RA_WIN2K ) {
1513 if ( strlen(native_lanman) == 0 )
1514 ra_lanman_string( primary_domain );
1515 else
1516 ra_lanman_string( native_lanman );
1521 if (SVAL(req->vwv+4, 0) == 0) {
1522 setup_new_vc_session(req->sconn);
1525 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1526 domain, user, get_remote_machine_name()));
1528 if (*user) {
1529 if (sconn->smb1.negprot.spnego) {
1531 /* This has to be here, because this is a perfectly
1532 * valid behaviour for guest logons :-( */
1534 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1535 "at 'normal' session setup after "
1536 "negotiating spnego.\n"));
1537 reply_nterror(req, nt_status_squash(
1538 NT_STATUS_LOGON_FAILURE));
1539 END_PROFILE(SMBsesssetupX);
1540 return;
1542 fstrcpy(sub_user, user);
1543 } else {
1544 fstrcpy(sub_user, lp_guestaccount());
1547 sub_set_smb_name(sub_user);
1549 reload_services(sconn->msg_ctx, sconn->sock, True);
1551 if (lp_security() == SEC_SHARE) {
1552 char *sub_user_mapped = NULL;
1553 /* In share level we should ignore any passwords */
1555 data_blob_free(&lm_resp);
1556 data_blob_free(&nt_resp);
1557 data_blob_clear_free(&plaintext_password);
1559 (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
1560 if (!sub_user_mapped) {
1561 reply_nterror(req, NT_STATUS_NO_MEMORY);
1562 END_PROFILE(SMBsesssetupX);
1563 return;
1565 fstrcpy(sub_user, sub_user_mapped);
1566 add_session_user(sconn, sub_user);
1567 add_session_workgroup(sconn, domain);
1568 /* Then force it to null for the benfit of the code below */
1569 user = "";
1572 if (!*user) {
1574 nt_status = check_guest_password(&server_info);
1576 } else if (doencrypt) {
1577 struct auth_context *negprot_auth_context = NULL;
1578 negprot_auth_context = sconn->smb1.negprot.auth_context;
1579 if (!negprot_auth_context) {
1580 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1581 "session setup without negprot denied!\n"));
1582 reply_nterror(req, nt_status_squash(
1583 NT_STATUS_LOGON_FAILURE));
1584 END_PROFILE(SMBsesssetupX);
1585 return;
1587 nt_status = make_user_info_for_reply_enc(&user_info, user,
1588 domain,
1589 lm_resp, nt_resp);
1590 if (NT_STATUS_IS_OK(nt_status)) {
1591 nt_status = negprot_auth_context->check_ntlm_password(
1592 negprot_auth_context,
1593 user_info,
1594 &server_info);
1596 } else {
1597 struct auth_context *plaintext_auth_context = NULL;
1599 nt_status = make_auth_context_subsystem(
1600 talloc_tos(), &plaintext_auth_context);
1602 if (NT_STATUS_IS_OK(nt_status)) {
1603 uint8_t chal[8];
1605 plaintext_auth_context->get_ntlm_challenge(
1606 plaintext_auth_context, chal);
1608 if (!make_user_info_for_reply(&user_info,
1609 user, domain, chal,
1610 plaintext_password)) {
1611 nt_status = NT_STATUS_NO_MEMORY;
1614 if (NT_STATUS_IS_OK(nt_status)) {
1615 nt_status = plaintext_auth_context->check_ntlm_password(
1616 plaintext_auth_context,
1617 user_info,
1618 &server_info);
1620 TALLOC_FREE(plaintext_auth_context);
1625 free_user_info(&user_info);
1627 if (!NT_STATUS_IS_OK(nt_status)) {
1628 nt_status = do_map_to_guest(nt_status, &server_info,
1629 user, domain);
1632 if (!NT_STATUS_IS_OK(nt_status)) {
1633 data_blob_free(&nt_resp);
1634 data_blob_free(&lm_resp);
1635 data_blob_clear_free(&plaintext_password);
1636 reply_nterror(req, nt_status_squash(nt_status));
1637 END_PROFILE(SMBsesssetupX);
1638 return;
1641 /* Ensure we can't possible take a code path leading to a
1642 * null defref. */
1643 if (!server_info) {
1644 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1645 END_PROFILE(SMBsesssetupX);
1646 return;
1649 if (!server_info->security_token) {
1650 nt_status = create_local_token(server_info);
1652 if (!NT_STATUS_IS_OK(nt_status)) {
1653 DEBUG(10, ("create_local_token failed: %s\n",
1654 nt_errstr(nt_status)));
1655 data_blob_free(&nt_resp);
1656 data_blob_free(&lm_resp);
1657 data_blob_clear_free(&plaintext_password);
1658 reply_nterror(req, nt_status_squash(nt_status));
1659 END_PROFILE(SMBsesssetupX);
1660 return;
1664 data_blob_clear_free(&plaintext_password);
1666 /* it's ok - setup a reply */
1667 reply_outbuf(req, 3, 0);
1668 if (get_Protocol() >= PROTOCOL_NT1) {
1669 push_signature(&req->outbuf);
1670 /* perhaps grab OS version here?? */
1673 if (server_info->guest) {
1674 SSVAL(req->outbuf,smb_vwv2,1);
1677 /* register the name and uid as being validated, so further connections
1678 to a uid can get through without a password, on the same VC */
1680 if (lp_security() == SEC_SHARE) {
1681 sess_vuid = UID_FIELD_INVALID;
1682 TALLOC_FREE(server_info);
1683 } else {
1684 /* Ignore the initial vuid. */
1685 sess_vuid = register_initial_vuid(sconn);
1686 if (sess_vuid == UID_FIELD_INVALID) {
1687 data_blob_free(&nt_resp);
1688 data_blob_free(&lm_resp);
1689 reply_nterror(req, nt_status_squash(
1690 NT_STATUS_LOGON_FAILURE));
1691 END_PROFILE(SMBsesssetupX);
1692 return;
1694 /* register_existing_vuid keeps the server info */
1695 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1696 server_info,
1697 nt_resp.data ? nt_resp : lm_resp,
1698 sub_user);
1699 if (sess_vuid == UID_FIELD_INVALID) {
1700 data_blob_free(&nt_resp);
1701 data_blob_free(&lm_resp);
1702 reply_nterror(req, nt_status_squash(
1703 NT_STATUS_LOGON_FAILURE));
1704 END_PROFILE(SMBsesssetupX);
1705 return;
1708 /* current_user_info is changed on new vuid */
1709 reload_services(sconn->msg_ctx, sconn->sock, True);
1712 data_blob_free(&nt_resp);
1713 data_blob_free(&lm_resp);
1715 SSVAL(req->outbuf,smb_uid,sess_vuid);
1716 SSVAL(req->inbuf,smb_uid,sess_vuid);
1717 req->vuid = sess_vuid;
1719 if (!sconn->smb1.sessions.done_sesssetup) {
1720 sconn->smb1.sessions.max_send =
1721 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1723 sconn->smb1.sessions.done_sesssetup = true;
1725 END_PROFILE(SMBsesssetupX);
1726 chain_reply(req);
1727 return;