2 Unix SMB/CIFS implementation.
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/>.
27 extern struct auth_context *negprot_global_auth_context;
28 extern bool global_encrypted_passwords_negotiated;
29 extern bool global_spnego_negotiated;
30 extern enum protocol_types Protocol;
33 uint32 global_client_caps = 0;
36 on a logon error possibly map the error to success if "map to guest"
39 static NTSTATUS do_map_to_guest(NTSTATUS status,
40 auth_serversupplied_info **server_info,
41 const char *user, const char *domain)
43 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
44 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
45 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
46 DEBUG(3,("No such user %s [%s] - using guest account\n",
48 status = make_server_info_guest(server_info);
52 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
53 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
54 DEBUG(3,("Registered username %s for guest access\n",
56 status = make_server_info_guest(server_info);
63 /****************************************************************************
64 Add the standard 'Samba' signature to the end of the session setup.
65 ****************************************************************************/
67 static int push_signature(uint8 **outbuf)
74 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
76 if (tmp == -1) return -1;
79 if (asprintf(&lanman, "Samba %s", SAMBA_VERSION_STRING) != -1) {
80 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
84 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
87 if (tmp == -1) return -1;
90 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
92 if (tmp == -1) return -1;
98 /****************************************************************************
99 Start the signing engine if needed. Don't fail signing here.
100 ****************************************************************************/
102 static void sessionsetup_start_signing_engine(
103 const auth_serversupplied_info *server_info,
106 if (!server_info->guest && !srv_signing_started()) {
107 /* We need to start the signing engine
108 * here but a W2K client sends the old
109 * "BSRSPYL " signature instead of the
110 * correct one. Subsequent packets will
113 srv_check_sign_mac((char *)inbuf, False);
117 /****************************************************************************
118 Send a security blob via a session setup reply.
119 ****************************************************************************/
121 static void reply_sesssetup_blob(struct smb_request *req,
125 if (!NT_STATUS_IS_OK(nt_status) &&
126 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
127 reply_nterror(req, nt_status_squash(nt_status));
129 nt_status = nt_status_squash(nt_status);
130 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
131 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
132 SSVAL(req->outbuf, smb_vwv3, blob.length);
134 if ((message_push_blob(&req->outbuf, blob) == -1)
135 || (push_signature(&req->outbuf) == -1)) {
136 reply_nterror(req, NT_STATUS_NO_MEMORY);
140 show_msg((char *)req->outbuf);
141 srv_send_smb(smbd_server_fd(),(char *)req->outbuf,req->encrypted);
142 TALLOC_FREE(req->outbuf);
145 /****************************************************************************
146 Do a 'guest' logon, getting back the
147 ****************************************************************************/
149 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
151 struct auth_context *auth_context;
152 auth_usersupplied_info *user_info = NULL;
155 unsigned char chal[8];
159 DEBUG(3,("Got anonymous request\n"));
161 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context,
166 if (!make_user_info_guest(&user_info)) {
167 (auth_context->free)(&auth_context);
168 return NT_STATUS_NO_MEMORY;
171 nt_status = auth_context->check_ntlm_password(auth_context,
174 (auth_context->free)(&auth_context);
175 free_user_info(&user_info);
183 /* Experiment that failed. See "only happens with a KDC" comment below. */
184 /****************************************************************************
185 Cerate a clock skew error blob for a Windows client.
186 ****************************************************************************/
188 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
190 krb5_context context = NULL;
191 krb5_error_code kerr = 0;
193 krb5_principal host_princ = NULL;
194 char *host_princ_s = NULL;
197 *pblob_out = data_blob_null;
199 initialize_krb5_error_table();
200 kerr = krb5_init_context(&context);
204 /* Create server principal. */
205 asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
209 strlower_m(host_princ_s);
211 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
213 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
214 "for name %s: Error %s\n",
215 host_princ_s, error_message(kerr) ));
219 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
222 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
223 "failed: Error %s\n",
224 error_message(kerr) ));
228 *pblob_out = data_blob(reply.data, reply.length);
229 kerberos_free_data_contents(context,&reply);
235 SAFE_FREE(host_princ_s);
238 krb5_free_principal(context, host_princ);
240 krb5_free_context(context);
245 /****************************************************************************
246 Reply to a session setup spnego negotiate packet for kerberos.
247 ****************************************************************************/
249 static void reply_spnego_kerberos(struct smb_request *req,
252 bool *p_invalidate_vuid)
256 char *client, *p, *domain;
257 fstring netbios_domain_name;
260 int sess_vuid = req->vuid;
261 NTSTATUS ret = NT_STATUS_OK;
263 DATA_BLOB ap_rep, ap_rep_wrapped, response;
264 auth_serversupplied_info *server_info = NULL;
265 DATA_BLOB session_key = data_blob_null;
267 DATA_BLOB nullblob = data_blob_null;
268 fstring real_username;
269 bool map_domainuser_to_guest = False;
270 bool username_was_mapped;
271 PAC_LOGON_INFO *logon_info = NULL;
274 ZERO_STRUCT(pac_data);
276 ZERO_STRUCT(ap_rep_wrapped);
277 ZERO_STRUCT(response);
279 /* Normally we will always invalidate the intermediate vuid. */
280 *p_invalidate_vuid = True;
282 mem_ctx = talloc_init("reply_spnego_kerberos");
283 if (mem_ctx == NULL) {
284 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
288 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
289 talloc_destroy(mem_ctx);
290 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
294 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
295 &client, &pac_data, &ap_rep,
298 data_blob_free(&ticket);
300 if (!NT_STATUS_IS_OK(ret)) {
302 /* Experiment that failed.
303 * See "only happens with a KDC" comment below. */
305 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
308 * Windows in this case returns
309 * NT_STATUS_MORE_PROCESSING_REQUIRED
310 * with a negTokenTarg blob containing an krb5_error
311 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
312 * The client then fixes its clock and continues rather
313 * than giving an error. JRA.
314 * -- Looks like this only happens with a KDC. JRA.
317 bool ok = make_krb5_skew_error(&ap_rep);
319 talloc_destroy(mem_ctx);
320 return ERROR_NT(nt_status_squash(
321 NT_STATUS_LOGON_FAILURE));
323 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
325 response = spnego_gen_auth_response(&ap_rep_wrapped,
326 ret, OID_KERBEROS5_OLD);
327 reply_sesssetup_blob(conn, inbuf, outbuf, response,
328 NT_STATUS_MORE_PROCESSING_REQUIRED);
331 * In this one case we don't invalidate the
332 * intermediate vuid as we're expecting the client
333 * to re-use it for the next sessionsetupX packet. JRA.
336 *p_invalidate_vuid = False;
338 data_blob_free(&ap_rep);
339 data_blob_free(&ap_rep_wrapped);
340 data_blob_free(&response);
341 talloc_destroy(mem_ctx);
342 return -1; /* already replied */
345 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
346 ret = NT_STATUS_LOGON_FAILURE;
349 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
351 talloc_destroy(mem_ctx);
352 reply_nterror(req, nt_status_squash(ret));
356 DEBUG(3,("Ticket name is [%s]\n", client));
358 p = strchr_m(client, '@');
360 DEBUG(3,("Doesn't look like a valid principal\n"));
361 data_blob_free(&ap_rep);
362 data_blob_free(&session_key);
364 talloc_destroy(mem_ctx);
365 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
371 /* save the PAC data if we have it */
374 logon_info = get_logon_info_from_pac(pac_data);
376 netsamlogon_cache_store( client, &logon_info->info3 );
380 if (!strequal(p+1, lp_realm())) {
381 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
382 if (!lp_allow_trusted_domains()) {
383 data_blob_free(&ap_rep);
384 data_blob_free(&session_key);
386 talloc_destroy(mem_ctx);
387 reply_nterror(req, nt_status_squash(
388 NT_STATUS_LOGON_FAILURE));
393 /* this gives a fully qualified user name (ie. with full realm).
394 that leads to very long usernames, but what else can we do? */
398 if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) {
399 unistr2_to_ascii(netbios_domain_name,
400 &logon_info->info3.uni_logon_dom,
401 sizeof(netbios_domain_name));
402 domain = netbios_domain_name;
403 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
407 /* If we have winbind running, we can (and must) shorten the
408 username by using the short netbios name. Otherwise we will
409 have inconsistent user names. With Kerberos, we get the
410 fully qualified realm, with ntlmssp we get the short
411 name. And even w2k3 does use ntlmssp if you for example
412 connect to an ip address. */
414 struct winbindd_request wb_request;
415 struct winbindd_response wb_response;
416 NSS_STATUS wb_result;
418 ZERO_STRUCT(wb_request);
419 ZERO_STRUCT(wb_response);
421 DEBUG(10, ("Mapping [%s] to short name\n", domain));
423 fstrcpy(wb_request.domain_name, domain);
425 wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
426 &wb_request, &wb_response);
428 if (wb_result == NSS_STATUS_SUCCESS) {
430 fstrcpy(netbios_domain_name,
431 wb_response.data.domain_info.name);
432 domain = netbios_domain_name;
434 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
436 DEBUG(3, ("Could not find short name -- winbind "
441 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
443 /* lookup the passwd struct, create a new user if necessary */
445 username_was_mapped = map_username( user );
447 pw = smb_getpwnam( mem_ctx, user, real_username, True );
450 /* if a real user check pam account restrictions */
451 /* only really perfomed if "obey pam restriction" is true */
452 /* do this before an eventual mappign to guest occurs */
453 ret = smb_pam_accountcheck(pw->pw_name);
454 if ( !NT_STATUS_IS_OK(ret)) {
455 DEBUG(1,("PAM account restriction "
456 "prevents user login\n"));
457 data_blob_free(&ap_rep);
458 data_blob_free(&session_key);
459 TALLOC_FREE(mem_ctx);
460 reply_nterror(req, nt_status_squash(ret));
467 /* this was originally the behavior of Samba 2.2, if a user
468 did not have a local uid but has been authenticated, then
469 map them to a guest account */
471 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
472 map_domainuser_to_guest = True;
473 fstrcpy(user,lp_guestaccount());
474 pw = smb_getpwnam( mem_ctx, user, real_username, True );
477 /* extra sanity check that the guest account is valid */
480 DEBUG(1,("Username %s is invalid on this system\n",
483 data_blob_free(&ap_rep);
484 data_blob_free(&session_key);
485 TALLOC_FREE(mem_ctx);
486 reply_nterror(req, nt_status_squash(
487 NT_STATUS_LOGON_FAILURE));
492 /* setup the string used by %U */
494 sub_set_smb_name( real_username );
495 reload_services(True);
497 if ( map_domainuser_to_guest ) {
498 make_server_info_guest(&server_info);
499 } else if (logon_info) {
500 /* pass the unmapped username here since map_username()
501 will be called again from inside make_server_info_info3() */
503 ret = make_server_info_info3(mem_ctx, client, domain,
504 &server_info, &logon_info->info3);
505 if ( !NT_STATUS_IS_OK(ret) ) {
506 DEBUG(1,("make_server_info_info3 failed: %s!\n",
509 data_blob_free(&ap_rep);
510 data_blob_free(&session_key);
511 TALLOC_FREE(mem_ctx);
512 reply_nterror(req, nt_status_squash(ret));
517 ret = make_server_info_pw(&server_info, real_username, pw);
519 if ( !NT_STATUS_IS_OK(ret) ) {
520 DEBUG(1,("make_server_info_pw failed: %s!\n",
523 data_blob_free(&ap_rep);
524 data_blob_free(&session_key);
525 TALLOC_FREE(mem_ctx);
526 reply_nterror(req, nt_status_squash(ret));
530 /* make_server_info_pw does not set the domain. Without this
531 * we end up with the local netbios name in substitutions for
534 if (server_info->sam_account != NULL) {
535 pdb_set_domain(server_info->sam_account,
540 server_info->was_mapped |= username_was_mapped;
542 /* we need to build the token for the user. make_server_info_guest()
545 if ( !server_info->ptok ) {
546 ret = create_local_token( server_info );
547 if ( !NT_STATUS_IS_OK(ret) ) {
549 data_blob_free(&ap_rep);
550 data_blob_free(&session_key);
551 TALLOC_FREE( mem_ctx );
552 TALLOC_FREE( server_info );
553 reply_nterror(req, nt_status_squash(ret));
558 /* register_existing_vuid keeps the server info */
559 /* register_existing_vuid takes ownership of session_key on success,
560 * no need to free after this on success. A better interface would copy
563 if (!is_partial_auth_vuid(sess_vuid)) {
564 sess_vuid = register_initial_vuid();
566 sess_vuid = register_existing_vuid(sess_vuid,
574 reply_outbuf(req, 4, 0);
575 SSVAL(req->outbuf,smb_uid,sess_vuid);
577 if (sess_vuid == UID_FIELD_INVALID ) {
578 ret = NT_STATUS_LOGON_FAILURE;
579 data_blob_free(&session_key);
581 /* current_user_info is changed on new vuid */
582 reload_services( True );
584 SSVAL(req->outbuf, smb_vwv3, 0);
586 if (server_info->guest) {
587 SSVAL(req->outbuf,smb_vwv2,1);
590 SSVAL(req->outbuf, smb_uid, sess_vuid);
592 sessionsetup_start_signing_engine(server_info, req->inbuf);
593 /* Successful logon. Keep this vuid. */
594 *p_invalidate_vuid = False;
597 /* wrap that up in a nice GSS-API wrapping */
598 if (NT_STATUS_IS_OK(ret)) {
599 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
602 ap_rep_wrapped = data_blob_null;
604 response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
606 reply_sesssetup_blob(req, response, ret);
608 data_blob_free(&ap_rep);
609 data_blob_free(&ap_rep_wrapped);
610 data_blob_free(&response);
611 TALLOC_FREE(mem_ctx);
616 /****************************************************************************
617 Send a session setup reply, wrapped in SPNEGO.
618 Get vuid and check first.
619 End the NTLMSSP exchange context if we are OK/complete fail
620 This should be split into two functions, one to handle each
621 leg of the NTLM auth steps.
622 ***************************************************************************/
624 static void reply_spnego_ntlmssp(struct smb_request *req,
626 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
627 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
631 struct auth_serversupplied_info *server_info = NULL;
633 if (NT_STATUS_IS_OK(nt_status)) {
634 server_info = (*auth_ntlmssp_state)->server_info;
636 nt_status = do_map_to_guest(nt_status,
638 (*auth_ntlmssp_state)->ntlmssp_state->user,
639 (*auth_ntlmssp_state)->ntlmssp_state->domain);
642 reply_outbuf(req, 4, 0);
644 SSVAL(req->outbuf, smb_uid, vuid);
646 if (NT_STATUS_IS_OK(nt_status)) {
647 DATA_BLOB nullblob = data_blob_null;
648 DATA_BLOB session_key =
650 (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
651 (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
653 if (!is_partial_auth_vuid(vuid)) {
654 data_blob_free(&session_key);
655 nt_status = NT_STATUS_LOGON_FAILURE;
658 /* register_existing_vuid keeps the server info */
659 if (register_existing_vuid(vuid,
661 session_key, nullblob,
662 (*auth_ntlmssp_state)->ntlmssp_state->user) !=
664 data_blob_free(&session_key);
665 nt_status = NT_STATUS_LOGON_FAILURE;
669 (*auth_ntlmssp_state)->server_info = NULL;
671 /* current_user_info is changed on new vuid */
672 reload_services( True );
674 SSVAL(req->outbuf, smb_vwv3, 0);
676 if (server_info->guest) {
677 SSVAL(req->outbuf,smb_vwv2,1);
680 sessionsetup_start_signing_engine(server_info,
681 (uint8 *)req->inbuf);
687 response = spnego_gen_auth_response(ntlmssp_blob,
688 nt_status, OID_NTLMSSP);
690 response = *ntlmssp_blob;
693 reply_sesssetup_blob(req, response, nt_status);
695 data_blob_free(&response);
698 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
699 and the other end, that we are not finished yet. */
701 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
702 /* NB. This is *NOT* an error case. JRA */
703 auth_ntlmssp_end(auth_ntlmssp_state);
704 if (!NT_STATUS_IS_OK(nt_status)) {
705 /* Kill the intermediate vuid */
706 invalidate_vuid(vuid);
711 /****************************************************************************
712 Is this a krb5 mechanism ?
713 ****************************************************************************/
715 NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out,
718 char *OIDs[ASN1_MAX_OIDS];
723 /* parse out the OIDs and the first sec blob */
724 if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
725 return NT_STATUS_LOGON_FAILURE;
728 /* only look at the first OID for determining the mechToken --
729 according to RFC2478, we should choose the one we want
730 and renegotiate, but i smell a client bug here..
732 Problem observed when connecting to a member (samba box)
733 of an AD domain as a user in a Samba domain. Samba member
734 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
735 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
736 NTLMSSP mechtoken. --jerry */
739 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
740 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
745 for (i=0;OIDs[i];i++) {
746 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
752 /****************************************************************************
753 Reply to a session setup spnego negotiate packet.
754 ****************************************************************************/
756 static void reply_spnego_negotiate(struct smb_request *req,
759 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
763 bool got_kerberos_mechanism = False;
766 status = parse_spnego_mechanisms(blob1, &secblob,
767 &got_kerberos_mechanism);
768 if (!NT_STATUS_IS_OK(status)) {
769 /* Kill the intermediate vuid */
770 invalidate_vuid(vuid);
771 reply_nterror(req, nt_status_squash(status));
775 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
776 (unsigned long)secblob.length));
779 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) ||
780 lp_use_kerberos_keytab()) ) {
781 bool destroy_vuid = True;
782 reply_spnego_kerberos(req, &secblob, vuid,
784 data_blob_free(&secblob);
786 /* Kill the intermediate vuid */
787 invalidate_vuid(vuid);
793 if (*auth_ntlmssp_state) {
794 auth_ntlmssp_end(auth_ntlmssp_state);
797 status = auth_ntlmssp_start(auth_ntlmssp_state);
798 if (!NT_STATUS_IS_OK(status)) {
799 /* Kill the intermediate vuid */
800 invalidate_vuid(vuid);
801 reply_nterror(req, nt_status_squash(status));
805 status = auth_ntlmssp_update(*auth_ntlmssp_state,
808 data_blob_free(&secblob);
810 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
811 &chal, status, True);
813 data_blob_free(&chal);
815 /* already replied */
819 /****************************************************************************
820 Reply to a session setup spnego auth packet.
821 ****************************************************************************/
823 static void reply_spnego_auth(struct smb_request *req,
826 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
828 DATA_BLOB auth = data_blob_null;
829 DATA_BLOB auth_reply = data_blob_null;
830 DATA_BLOB secblob = data_blob_null;
831 NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
833 if (!spnego_parse_auth(blob1, &auth)) {
835 file_save("auth.dat", blob1.data, blob1.length);
837 /* Kill the intermediate vuid */
838 invalidate_vuid(vuid);
840 reply_nterror(req, nt_status_squash(
841 NT_STATUS_INVALID_PARAMETER));
845 if (auth.data[0] == ASN1_APPLICATION(0)) {
846 /* Might be a second negTokenTarg packet */
848 bool got_krb5_mechanism = False;
849 status = parse_spnego_mechanisms(auth, &secblob,
850 &got_krb5_mechanism);
851 if (NT_STATUS_IS_OK(status)) {
852 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
853 (unsigned long)secblob.length));
855 if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) ||
856 lp_use_kerberos_keytab()) ) {
857 bool destroy_vuid = True;
858 reply_spnego_kerberos(req, &secblob,
859 vuid, &destroy_vuid);
860 data_blob_free(&secblob);
861 data_blob_free(&auth);
863 /* Kill the intermediate vuid */
864 invalidate_vuid(vuid);
872 /* If we get here it wasn't a negTokenTarg auth packet. */
873 data_blob_free(&secblob);
875 if (!*auth_ntlmssp_state) {
876 /* Kill the intermediate vuid */
877 invalidate_vuid(vuid);
879 /* auth before negotiatiate? */
880 reply_nterror(req, nt_status_squash(
881 NT_STATUS_INVALID_PARAMETER));
885 status = auth_ntlmssp_update(*auth_ntlmssp_state,
888 data_blob_free(&auth);
890 reply_spnego_ntlmssp(req, vuid,
892 &auth_reply, status, True);
894 data_blob_free(&auth_reply);
896 /* and tell smbd that we have already replied to this packet */
900 /****************************************************************************
901 List to store partial SPNEGO auth fragments.
902 ****************************************************************************/
904 static struct pending_auth_data *pd_list;
906 /****************************************************************************
907 Delete an entry on the list.
908 ****************************************************************************/
910 static void delete_partial_auth(struct pending_auth_data *pad)
915 DLIST_REMOVE(pd_list, pad);
916 data_blob_free(&pad->partial_data);
920 /****************************************************************************
921 Search for a partial SPNEGO auth fragment matching an smbpid.
922 ****************************************************************************/
924 static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
926 struct pending_auth_data *pad;
928 for (pad = pd_list; pad; pad = pad->next) {
929 if (pad->smbpid == smbpid) {
936 /****************************************************************************
937 Check the size of an SPNEGO blob. If we need more return
938 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
939 the blob to be more than 64k.
940 ****************************************************************************/
942 static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid,
945 struct pending_auth_data *pad = NULL;
947 size_t needed_len = 0;
949 pad = get_pending_auth_data(smbpid);
951 /* Ensure we have some data. */
952 if (pblob->length == 0) {
953 /* Caller can cope. */
954 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
955 delete_partial_auth(pad);
959 /* Were we waiting for more data ? */
962 size_t copy_len = MIN(65536, pblob->length);
964 /* Integer wrap paranoia.... */
966 if (pad->partial_data.length + copy_len <
967 pad->partial_data.length ||
968 pad->partial_data.length + copy_len < copy_len) {
970 DEBUG(2,("check_spnego_blob_complete: integer wrap "
971 "pad->partial_data.length = %u, "
973 (unsigned int)pad->partial_data.length,
974 (unsigned int)copy_len ));
976 delete_partial_auth(pad);
977 return NT_STATUS_INVALID_PARAMETER;
980 DEBUG(10,("check_spnego_blob_complete: "
981 "pad->partial_data.length = %u, "
982 "pad->needed_len = %u, "
984 "pblob->length = %u,\n",
985 (unsigned int)pad->partial_data.length,
986 (unsigned int)pad->needed_len,
987 (unsigned int)copy_len,
988 (unsigned int)pblob->length ));
990 tmp_blob = data_blob(NULL,
991 pad->partial_data.length + copy_len);
993 /* Concatenate the two (up to copy_len) bytes. */
994 memcpy(tmp_blob.data,
995 pad->partial_data.data,
996 pad->partial_data.length);
997 memcpy(tmp_blob.data + pad->partial_data.length,
1001 /* Replace the partial data. */
1002 data_blob_free(&pad->partial_data);
1003 pad->partial_data = tmp_blob;
1004 ZERO_STRUCT(tmp_blob);
1007 if (pblob->length >= pad->needed_len) {
1008 /* Yes, replace pblob. */
1009 data_blob_free(pblob);
1010 *pblob = pad->partial_data;
1011 ZERO_STRUCT(pad->partial_data);
1012 delete_partial_auth(pad);
1013 return NT_STATUS_OK;
1016 /* Still need more data. */
1017 pad->needed_len -= copy_len;
1018 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1021 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
1022 (pblob->data[0] != ASN1_CONTEXT(1))) {
1023 /* Not something we can determine the
1026 return NT_STATUS_OK;
1029 /* This is a new SPNEGO sessionsetup - see if
1030 * the data given in this blob is enough.
1033 asn1_load(&data, *pblob);
1034 asn1_start_tag(&data, pblob->data[0]);
1035 if (data.has_error || data.nesting == NULL) {
1037 /* Let caller catch. */
1038 return NT_STATUS_OK;
1041 /* Integer wrap paranoia.... */
1043 if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
1044 data.nesting->taglen + data.nesting->start < data.nesting->start) {
1046 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1047 "data.nesting->taglen = %u, "
1048 "data.nesting->start = %u\n",
1049 (unsigned int)data.nesting->taglen,
1050 (unsigned int)data.nesting->start ));
1053 return NT_STATUS_INVALID_PARAMETER;
1056 /* Total length of the needed asn1 is the tag length
1057 * plus the current offset. */
1059 needed_len = data.nesting->taglen + data.nesting->start;
1062 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1063 "pblob->length = %u\n",
1064 (unsigned int)needed_len,
1065 (unsigned int)pblob->length ));
1067 if (needed_len <= pblob->length) {
1068 /* Nothing to do - blob is complete. */
1069 return NT_STATUS_OK;
1072 /* Refuse the blob if it's bigger than 64k. */
1073 if (needed_len > 65536) {
1074 DEBUG(2,("check_spnego_blob_complete: needed_len "
1076 (unsigned int)needed_len ));
1077 return NT_STATUS_INVALID_PARAMETER;
1080 /* We must store this blob until complete. */
1081 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1082 return NT_STATUS_NO_MEMORY;
1084 pad->needed_len = needed_len - pblob->length;
1085 pad->partial_data = data_blob(pblob->data, pblob->length);
1086 if (pad->partial_data.data == NULL) {
1088 return NT_STATUS_NO_MEMORY;
1090 pad->smbpid = smbpid;
1092 DLIST_ADD(pd_list, pad);
1094 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1097 /****************************************************************************
1098 Reply to a session setup command.
1099 conn POINTER CAN BE NULL HERE !
1100 ****************************************************************************/
1102 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1107 fstring native_os, native_lanman, primary_domain;
1109 uint16 data_blob_len = SVAL(req->inbuf, smb_vwv7);
1110 enum remote_arch_types ra_type = get_remote_arch();
1111 int vuid = SVAL(req->inbuf,smb_uid);
1112 user_struct *vuser = NULL;
1113 NTSTATUS status = NT_STATUS_OK;
1114 uint16 smbpid = req->smbpid;
1115 uint16 smb_flag2 = req->flags2;
1117 DEBUG(3,("Doing spnego session setup\n"));
1119 if (global_client_caps == 0) {
1120 global_client_caps = IVAL(req->inbuf,smb_vwv10);
1122 if (!(global_client_caps & CAP_STATUS32)) {
1123 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1128 p = (uint8 *)smb_buf(req->inbuf);
1130 if (data_blob_len == 0) {
1131 /* an invalid request */
1132 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1136 bufrem = smb_bufrem(req->inbuf, p);
1137 /* pull the spnego blob */
1138 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1141 file_save("negotiate.dat", blob1.data, blob1.length);
1144 p2 = (char *)req->inbuf + smb_vwv13 + data_blob_len;
1145 p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_os, p2,
1146 sizeof(native_os), STR_TERMINATE);
1147 p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_lanman, p2,
1148 sizeof(native_lanman), STR_TERMINATE);
1149 p2 += srvstr_pull_buf(req->inbuf, smb_flag2, primary_domain, p2,
1150 sizeof(primary_domain), STR_TERMINATE);
1151 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1152 native_os, native_lanman, primary_domain));
1154 if ( ra_type == RA_WIN2K ) {
1155 /* Vista sets neither the OS or lanman strings */
1157 if ( !strlen(native_os) && !strlen(native_lanman) )
1158 set_remote_arch(RA_VISTA);
1160 /* Windows 2003 doesn't set the native lanman string,
1161 but does set primary domain which is a bug I think */
1163 if ( !strlen(native_lanman) ) {
1164 ra_lanman_string( primary_domain );
1166 ra_lanman_string( native_lanman );
1170 /* Did we get a valid vuid ? */
1171 if (!is_partial_auth_vuid(vuid)) {
1172 /* No, then try and see if this is an intermediate sessionsetup
1173 * for a large SPNEGO packet. */
1174 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
1176 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1177 "pending vuid %u\n",
1178 (unsigned int)pad->vuid ));
1183 /* Do we have a valid vuid now ? */
1184 if (!is_partial_auth_vuid(vuid)) {
1185 /* No, start a new authentication setup. */
1186 vuid = register_initial_vuid();
1187 if (vuid == UID_FIELD_INVALID) {
1188 data_blob_free(&blob1);
1189 reply_nterror(req, nt_status_squash(
1190 NT_STATUS_INVALID_PARAMETER));
1195 vuser = get_partial_auth_user_struct(vuid);
1196 /* This MUST be valid. */
1198 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1201 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1202 * sessionsetup requests as the Windows limit on the security blob
1203 * field is 4k. Bug #4400. JRA.
1206 status = check_spnego_blob_complete(smbpid, vuid, &blob1);
1207 if (!NT_STATUS_IS_OK(status)) {
1208 if (!NT_STATUS_EQUAL(status,
1209 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1210 /* Real error - kill the intermediate vuid */
1211 invalidate_vuid(vuid);
1213 data_blob_free(&blob1);
1214 reply_nterror(req, nt_status_squash(status));
1218 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1220 /* its a negTokenTarg packet */
1222 reply_spnego_negotiate(req, vuid, blob1,
1223 &vuser->auth_ntlmssp_state);
1224 data_blob_free(&blob1);
1228 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1230 /* its a auth packet */
1232 reply_spnego_auth(req, vuid, blob1,
1233 &vuser->auth_ntlmssp_state);
1234 data_blob_free(&blob1);
1238 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1241 if (!vuser->auth_ntlmssp_state) {
1242 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1243 if (!NT_STATUS_IS_OK(status)) {
1244 /* Kill the intermediate vuid */
1245 invalidate_vuid(vuid);
1246 data_blob_free(&blob1);
1247 reply_nterror(req, nt_status_squash(status));
1252 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1255 data_blob_free(&blob1);
1257 reply_spnego_ntlmssp(req, vuid,
1258 &vuser->auth_ntlmssp_state,
1259 &chal, status, False);
1260 data_blob_free(&chal);
1264 /* what sort of packet is this? */
1265 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1267 data_blob_free(&blob1);
1269 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1272 /****************************************************************************
1273 On new VC == 0, shutdown *all* old connections and users.
1274 It seems that only NT4.x does this. At W2K and above (XP etc.).
1275 a new session setup with VC==0 is ignored.
1276 ****************************************************************************/
1278 static int shutdown_other_smbds(struct db_record *rec,
1279 const struct connections_key *key,
1280 const struct connections_data *crec,
1283 const char *ip = (const char *)private_data;
1285 if (!process_exists(crec->pid)) {
1289 if (procid_is_me(&crec->pid)) {
1293 if (strcmp(ip, crec->addr) != 0) {
1297 messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1302 static void setup_new_vc_session(void)
1304 char addr[INET6_ADDRSTRLEN];
1306 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1307 "compatible we would close all old resources.\n"));
1310 invalidate_all_vuids();
1312 if (lp_reset_on_zero_vc()) {
1313 connections_forall(shutdown_other_smbds,
1314 CONST_DISCARD(void *,
1315 client_addr(get_client_fd(),addr,sizeof(addr))));
1319 /****************************************************************************
1320 Reply to a session setup command.
1321 ****************************************************************************/
1323 void reply_sesssetup_and_X(struct smb_request *req)
1329 DATA_BLOB plaintext_password;
1331 fstring sub_user; /* Sainitised username for substituion */
1334 fstring native_lanman;
1335 fstring primary_domain;
1336 static bool done_sesssetup = False;
1337 auth_usersupplied_info *user_info = NULL;
1338 auth_serversupplied_info *server_info = NULL;
1339 uint16 smb_flag2 = req->flags2;
1343 bool doencrypt = global_encrypted_passwords_negotiated;
1345 DATA_BLOB session_key;
1347 START_PROFILE(SMBsesssetupX);
1349 ZERO_STRUCT(lm_resp);
1350 ZERO_STRUCT(nt_resp);
1351 ZERO_STRUCT(plaintext_password);
1353 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1355 /* a SPNEGO session setup has 12 command words, whereas a normal
1356 NT1 session setup has 13. See the cifs spec. */
1357 if (req->wct == 12 &&
1358 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1360 if (!global_spnego_negotiated) {
1361 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1362 "at SPNEGO session setup when it was not "
1364 reply_nterror(req, nt_status_squash(
1365 NT_STATUS_LOGON_FAILURE));
1366 END_PROFILE(SMBsesssetupX);
1370 if (SVAL(req->inbuf,smb_vwv4) == 0) {
1371 setup_new_vc_session();
1374 reply_sesssetup_and_X_spnego(req);
1375 END_PROFILE(SMBsesssetupX);
1379 smb_bufsize = SVAL(req->inbuf,smb_vwv2);
1381 if (Protocol < PROTOCOL_NT1) {
1382 uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
1384 /* Never do NT status codes with protocols before NT1 as we
1385 * don't get client caps. */
1386 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1388 if ((passlen1 > MAX_PASS_LEN)
1389 || (passlen1 > smb_bufrem(req->inbuf,
1390 smb_buf(req->inbuf)))) {
1391 reply_nterror(req, nt_status_squash(
1392 NT_STATUS_INVALID_PARAMETER));
1393 END_PROFILE(SMBsesssetupX);
1398 lm_resp = data_blob(smb_buf(req->inbuf), passlen1);
1400 plaintext_password = data_blob(smb_buf(req->inbuf),
1402 /* Ensure null termination */
1403 plaintext_password.data[passlen1] = 0;
1406 srvstr_pull_buf(req->inbuf, req->flags2, user,
1407 smb_buf(req->inbuf)+passlen1, sizeof(user),
1412 uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
1413 uint16 passlen2 = SVAL(req->inbuf,smb_vwv8);
1414 enum remote_arch_types ra_type = get_remote_arch();
1415 char *p = smb_buf(req->inbuf);
1416 char *save_p = smb_buf(req->inbuf);
1420 if(global_client_caps == 0) {
1421 global_client_caps = IVAL(req->inbuf,smb_vwv11);
1423 if (!(global_client_caps & CAP_STATUS32)) {
1424 remove_from_common_flags2(
1425 FLAGS2_32_BIT_ERROR_CODES);
1428 /* client_caps is used as final determination if
1429 * client is NT or Win95. This is needed to return
1430 * the correct error codes in some circumstances.
1433 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1434 ra_type == RA_WIN95) {
1435 if(!(global_client_caps & (CAP_NT_SMBS|
1437 set_remote_arch( RA_WIN95);
1443 /* both Win95 and WinNT stuff up the password
1444 * lengths for non-encrypting systems. Uggh.
1446 if passlen1==24 its a win95 system, and its setting
1447 the password length incorrectly. Luckily it still
1448 works with the default code because Win95 will null
1449 terminate the password anyway
1451 if passlen1>0 and passlen2>0 then maybe its a NT box
1452 and its setting passlen2 to some random value which
1453 really stuffs things up. we need to fix that one. */
1455 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1461 /* check for nasty tricks */
1462 if (passlen1 > MAX_PASS_LEN
1463 || passlen1 > smb_bufrem(req->inbuf, p)) {
1464 reply_nterror(req, nt_status_squash(
1465 NT_STATUS_INVALID_PARAMETER));
1466 END_PROFILE(SMBsesssetupX);
1470 if (passlen2 > MAX_PASS_LEN
1471 || passlen2 > smb_bufrem(req->inbuf, p+passlen1)) {
1472 reply_nterror(req, nt_status_squash(
1473 NT_STATUS_INVALID_PARAMETER));
1474 END_PROFILE(SMBsesssetupX);
1478 /* Save the lanman2 password and the NT md4 password. */
1480 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1485 lm_resp = data_blob(p, passlen1);
1486 nt_resp = data_blob(p+passlen1, passlen2);
1489 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1491 if (unic && (passlen2 == 0) && passlen1) {
1492 /* Only a ascii plaintext password was sent. */
1493 (void)srvstr_pull_talloc(talloc_tos(),
1497 smb_buf(req->inbuf),
1499 STR_TERMINATE|STR_ASCII);
1501 (void)srvstr_pull_talloc(talloc_tos(),
1505 smb_buf(req->inbuf),
1506 unic ? passlen2 : passlen1,
1510 reply_nterror(req, nt_status_squash(
1511 NT_STATUS_INVALID_PARAMETER));
1512 END_PROFILE(SMBsesssetupX);
1515 plaintext_password = data_blob(pass, strlen(pass)+1);
1518 p += passlen1 + passlen2;
1519 p += srvstr_pull_buf(req->inbuf, req->flags2, user, p,
1520 sizeof(user), STR_TERMINATE);
1521 p += srvstr_pull_buf(req->inbuf, req->flags2, domain, p,
1522 sizeof(domain), STR_TERMINATE);
1523 p += srvstr_pull_buf(req->inbuf, req->flags2, native_os,
1524 p, sizeof(native_os), STR_TERMINATE);
1525 p += srvstr_pull_buf(req->inbuf, req->flags2,
1526 native_lanman, p, sizeof(native_lanman),
1529 /* not documented or decoded by Ethereal but there is one more
1530 * string in the extra bytes which is the same as the
1531 * PrimaryDomain when using extended security. Windows NT 4
1532 * and 2003 use this string to store the native lanman string.
1533 * Windows 9x does not include a string here at all so we have
1534 * to check if we have any extra bytes left */
1536 byte_count = SVAL(req->inbuf, smb_vwv13);
1537 if ( PTR_DIFF(p, save_p) < byte_count) {
1538 p += srvstr_pull_buf(req->inbuf, req->flags2,
1540 sizeof(primary_domain),
1543 fstrcpy( primary_domain, "null" );
1546 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1547 "PrimaryDomain=[%s]\n",
1548 domain, native_os, native_lanman, primary_domain));
1550 if ( ra_type == RA_WIN2K ) {
1551 if ( strlen(native_lanman) == 0 )
1552 ra_lanman_string( primary_domain );
1554 ra_lanman_string( native_lanman );
1559 if (SVAL(req->inbuf,smb_vwv4) == 0) {
1560 setup_new_vc_session();
1563 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1564 domain, user, get_remote_machine_name()));
1567 if (global_spnego_negotiated) {
1569 /* This has to be here, because this is a perfectly
1570 * valid behaviour for guest logons :-( */
1572 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1573 "at 'normal' session setup after "
1574 "negotiating spnego.\n"));
1575 reply_nterror(req, nt_status_squash(
1576 NT_STATUS_LOGON_FAILURE));
1577 END_PROFILE(SMBsesssetupX);
1580 fstrcpy(sub_user, user);
1582 fstrcpy(sub_user, lp_guestaccount());
1585 sub_set_smb_name(sub_user);
1587 reload_services(True);
1589 if (lp_security() == SEC_SHARE) {
1590 /* in share level we should ignore any passwords */
1592 data_blob_free(&lm_resp);
1593 data_blob_free(&nt_resp);
1594 data_blob_clear_free(&plaintext_password);
1596 map_username(sub_user);
1597 add_session_user(sub_user);
1598 add_session_workgroup(domain);
1599 /* Then force it to null for the benfit of the code below */
1605 nt_status = check_guest_password(&server_info);
1607 } else if (doencrypt) {
1608 if (!negprot_global_auth_context) {
1609 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1610 "session setup without negprot denied!\n"));
1611 reply_nterror(req, nt_status_squash(
1612 NT_STATUS_LOGON_FAILURE));
1613 END_PROFILE(SMBsesssetupX);
1616 nt_status = make_user_info_for_reply_enc(&user_info, user,
1619 if (NT_STATUS_IS_OK(nt_status)) {
1620 nt_status = negprot_global_auth_context->check_ntlm_password(
1621 negprot_global_auth_context,
1626 struct auth_context *plaintext_auth_context = NULL;
1629 nt_status = make_auth_context_subsystem(
1630 &plaintext_auth_context);
1632 if (NT_STATUS_IS_OK(nt_status)) {
1633 chal = plaintext_auth_context->get_ntlm_challenge(
1634 plaintext_auth_context);
1636 if (!make_user_info_for_reply(&user_info,
1638 plaintext_password)) {
1639 nt_status = NT_STATUS_NO_MEMORY;
1642 if (NT_STATUS_IS_OK(nt_status)) {
1643 nt_status = plaintext_auth_context->check_ntlm_password(
1644 plaintext_auth_context,
1648 (plaintext_auth_context->free)(
1649 &plaintext_auth_context);
1654 free_user_info(&user_info);
1656 if (!NT_STATUS_IS_OK(nt_status)) {
1657 nt_status = do_map_to_guest(nt_status, &server_info,
1661 if (!NT_STATUS_IS_OK(nt_status)) {
1662 data_blob_free(&nt_resp);
1663 data_blob_free(&lm_resp);
1664 data_blob_clear_free(&plaintext_password);
1665 reply_nterror(req, nt_status_squash(nt_status));
1666 END_PROFILE(SMBsesssetupX);
1670 /* Ensure we can't possible take a code path leading to a
1673 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1674 END_PROFILE(SMBsesssetupX);
1678 nt_status = create_local_token(server_info);
1679 if (!NT_STATUS_IS_OK(nt_status)) {
1680 DEBUG(10, ("create_local_token failed: %s\n",
1681 nt_errstr(nt_status)));
1682 data_blob_free(&nt_resp);
1683 data_blob_free(&lm_resp);
1684 data_blob_clear_free(&plaintext_password);
1685 reply_nterror(req, nt_status_squash(nt_status));
1686 END_PROFILE(SMBsesssetupX);
1690 if (server_info->user_session_key.data) {
1691 session_key = data_blob(server_info->user_session_key.data,
1692 server_info->user_session_key.length);
1694 session_key = data_blob_null;
1697 data_blob_clear_free(&plaintext_password);
1699 /* it's ok - setup a reply */
1700 reply_outbuf(req, 3, 0);
1701 if (Protocol >= PROTOCOL_NT1) {
1702 push_signature(&req->outbuf);
1703 /* perhaps grab OS version here?? */
1706 if (server_info->guest) {
1707 SSVAL(req->outbuf,smb_vwv2,1);
1710 /* register the name and uid as being validated, so further connections
1711 to a uid can get through without a password, on the same VC */
1713 if (lp_security() == SEC_SHARE) {
1714 sess_vuid = UID_FIELD_INVALID;
1715 data_blob_free(&session_key);
1716 TALLOC_FREE(server_info);
1718 /* Ignore the initial vuid. */
1719 sess_vuid = register_initial_vuid();
1720 if (sess_vuid == UID_FIELD_INVALID) {
1721 data_blob_free(&nt_resp);
1722 data_blob_free(&lm_resp);
1723 data_blob_free(&session_key);
1724 reply_nterror(req, nt_status_squash(
1725 NT_STATUS_LOGON_FAILURE));
1726 END_PROFILE(SMBsesssetupX);
1729 /* register_existing_vuid keeps the server info */
1730 sess_vuid = register_existing_vuid(sess_vuid,
1733 nt_resp.data ? nt_resp : lm_resp,
1735 if (sess_vuid == UID_FIELD_INVALID) {
1736 data_blob_free(&nt_resp);
1737 data_blob_free(&lm_resp);
1738 data_blob_free(&session_key);
1739 reply_nterror(req, nt_status_squash(
1740 NT_STATUS_LOGON_FAILURE));
1741 END_PROFILE(SMBsesssetupX);
1745 /* current_user_info is changed on new vuid */
1746 reload_services( True );
1748 sessionsetup_start_signing_engine(server_info, req->inbuf);
1751 data_blob_free(&nt_resp);
1752 data_blob_free(&lm_resp);
1754 SSVAL(req->outbuf,smb_uid,sess_vuid);
1755 SSVAL(req->inbuf,smb_uid,sess_vuid);
1757 if (!done_sesssetup)
1758 max_send = MIN(max_send,smb_bufsize);
1760 done_sesssetup = True;
1762 END_PROFILE(SMBsesssetupX);