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;
262 PAC_DATA *pac_data = NULL;
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;
275 ZERO_STRUCT(ap_rep_wrapped);
276 ZERO_STRUCT(response);
278 /* Normally we will always invalidate the intermediate vuid. */
279 *p_invalidate_vuid = True;
281 mem_ctx = talloc_init("reply_spnego_kerberos");
282 if (mem_ctx == NULL) {
283 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
287 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
288 talloc_destroy(mem_ctx);
289 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
293 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
294 &client, &pac_data, &ap_rep,
297 data_blob_free(&ticket);
299 if (!NT_STATUS_IS_OK(ret)) {
301 /* Experiment that failed.
302 * See "only happens with a KDC" comment below. */
304 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
307 * Windows in this case returns
308 * NT_STATUS_MORE_PROCESSING_REQUIRED
309 * with a negTokenTarg blob containing an krb5_error
310 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
311 * The client then fixes its clock and continues rather
312 * than giving an error. JRA.
313 * -- Looks like this only happens with a KDC. JRA.
316 bool ok = make_krb5_skew_error(&ap_rep);
318 talloc_destroy(mem_ctx);
319 return ERROR_NT(nt_status_squash(
320 NT_STATUS_LOGON_FAILURE));
322 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
324 response = spnego_gen_auth_response(&ap_rep_wrapped,
325 ret, OID_KERBEROS5_OLD);
326 reply_sesssetup_blob(conn, inbuf, outbuf, response,
327 NT_STATUS_MORE_PROCESSING_REQUIRED);
330 * In this one case we don't invalidate the
331 * intermediate vuid as we're expecting the client
332 * to re-use it for the next sessionsetupX packet. JRA.
335 *p_invalidate_vuid = False;
337 data_blob_free(&ap_rep);
338 data_blob_free(&ap_rep_wrapped);
339 data_blob_free(&response);
340 talloc_destroy(mem_ctx);
341 return -1; /* already replied */
344 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
345 ret = NT_STATUS_LOGON_FAILURE;
348 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
350 talloc_destroy(mem_ctx);
351 reply_nterror(req, nt_status_squash(ret));
355 DEBUG(3,("Ticket name is [%s]\n", client));
357 p = strchr_m(client, '@');
359 DEBUG(3,("Doesn't look like a valid principal\n"));
360 data_blob_free(&ap_rep);
361 data_blob_free(&session_key);
363 talloc_destroy(mem_ctx);
364 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
370 /* save the PAC data if we have it */
373 logon_info = get_logon_info_from_pac(pac_data);
375 netsamlogon_cache_store( client, &logon_info->info3 );
379 if (!strequal(p+1, lp_realm())) {
380 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
381 if (!lp_allow_trusted_domains()) {
382 data_blob_free(&ap_rep);
383 data_blob_free(&session_key);
385 talloc_destroy(mem_ctx);
386 reply_nterror(req, nt_status_squash(
387 NT_STATUS_LOGON_FAILURE));
392 /* this gives a fully qualified user name (ie. with full realm).
393 that leads to very long usernames, but what else can we do? */
397 if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) {
398 unistr2_to_ascii(netbios_domain_name,
399 &logon_info->info3.uni_logon_dom,
400 sizeof(netbios_domain_name));
401 domain = netbios_domain_name;
402 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
406 /* If we have winbind running, we can (and must) shorten the
407 username by using the short netbios name. Otherwise we will
408 have inconsistent user names. With Kerberos, we get the
409 fully qualified realm, with ntlmssp we get the short
410 name. And even w2k3 does use ntlmssp if you for example
411 connect to an ip address. */
414 struct wbcDomainInfo *info = NULL;
416 DEBUG(10, ("Mapping [%s] to short name\n", domain));
418 wbc_status = wbcDomainInfo(domain, &info);
420 if (WBC_ERROR_IS_OK(wbc_status)) {
422 fstrcpy(netbios_domain_name,
426 domain = netbios_domain_name;
427 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
429 DEBUG(3, ("Could not find short name: %s\n",
430 wbcErrorString(wbc_status)));
434 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
436 /* lookup the passwd struct, create a new user if necessary */
438 username_was_mapped = map_username( user );
440 pw = smb_getpwnam( mem_ctx, user, real_username, True );
443 /* if a real user check pam account restrictions */
444 /* only really perfomed if "obey pam restriction" is true */
445 /* do this before an eventual mappign to guest occurs */
446 ret = smb_pam_accountcheck(pw->pw_name);
447 if ( !NT_STATUS_IS_OK(ret)) {
448 DEBUG(1,("PAM account restriction "
449 "prevents user login\n"));
450 data_blob_free(&ap_rep);
451 data_blob_free(&session_key);
452 TALLOC_FREE(mem_ctx);
453 reply_nterror(req, nt_status_squash(ret));
460 /* this was originally the behavior of Samba 2.2, if a user
461 did not have a local uid but has been authenticated, then
462 map them to a guest account */
464 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
465 map_domainuser_to_guest = True;
466 fstrcpy(user,lp_guestaccount());
467 pw = smb_getpwnam( mem_ctx, user, real_username, True );
470 /* extra sanity check that the guest account is valid */
473 DEBUG(1,("Username %s is invalid on this system\n",
476 data_blob_free(&ap_rep);
477 data_blob_free(&session_key);
478 TALLOC_FREE(mem_ctx);
479 reply_nterror(req, nt_status_squash(
480 NT_STATUS_LOGON_FAILURE));
485 /* setup the string used by %U */
487 sub_set_smb_name( real_username );
488 reload_services(True);
490 if ( map_domainuser_to_guest ) {
491 make_server_info_guest(&server_info);
492 } else if (logon_info) {
493 /* pass the unmapped username here since map_username()
494 will be called again from inside make_server_info_info3() */
496 ret = make_server_info_info3(mem_ctx, client, domain,
497 &server_info, &logon_info->info3);
498 if ( !NT_STATUS_IS_OK(ret) ) {
499 DEBUG(1,("make_server_info_info3 failed: %s!\n",
502 data_blob_free(&ap_rep);
503 data_blob_free(&session_key);
504 TALLOC_FREE(mem_ctx);
505 reply_nterror(req, nt_status_squash(ret));
510 ret = make_server_info_pw(&server_info, real_username, pw);
512 if ( !NT_STATUS_IS_OK(ret) ) {
513 DEBUG(1,("make_server_info_pw failed: %s!\n",
516 data_blob_free(&ap_rep);
517 data_blob_free(&session_key);
518 TALLOC_FREE(mem_ctx);
519 reply_nterror(req, nt_status_squash(ret));
523 /* make_server_info_pw does not set the domain. Without this
524 * we end up with the local netbios name in substitutions for
527 if (server_info->sam_account != NULL) {
528 pdb_set_domain(server_info->sam_account,
533 if (username_was_mapped) {
534 server_info->was_mapped = username_was_mapped;
537 /* we need to build the token for the user. make_server_info_guest()
540 if ( !server_info->ptok ) {
541 ret = create_local_token( server_info );
542 if ( !NT_STATUS_IS_OK(ret) ) {
544 data_blob_free(&ap_rep);
545 data_blob_free(&session_key);
546 TALLOC_FREE( mem_ctx );
547 TALLOC_FREE( server_info );
548 reply_nterror(req, nt_status_squash(ret));
553 /* register_existing_vuid keeps the server info */
554 /* register_existing_vuid takes ownership of session_key on success,
555 * no need to free after this on success. A better interface would copy
558 if (!is_partial_auth_vuid(sess_vuid)) {
559 sess_vuid = register_initial_vuid();
561 sess_vuid = register_existing_vuid(sess_vuid,
569 reply_outbuf(req, 4, 0);
570 SSVAL(req->outbuf,smb_uid,sess_vuid);
572 if (sess_vuid == UID_FIELD_INVALID ) {
573 ret = NT_STATUS_LOGON_FAILURE;
574 data_blob_free(&session_key);
576 /* current_user_info is changed on new vuid */
577 reload_services( True );
579 SSVAL(req->outbuf, smb_vwv3, 0);
581 if (server_info->guest) {
582 SSVAL(req->outbuf,smb_vwv2,1);
585 SSVAL(req->outbuf, smb_uid, sess_vuid);
587 sessionsetup_start_signing_engine(server_info, req->inbuf);
588 /* Successful logon. Keep this vuid. */
589 *p_invalidate_vuid = False;
592 /* wrap that up in a nice GSS-API wrapping */
593 if (NT_STATUS_IS_OK(ret)) {
594 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
597 ap_rep_wrapped = data_blob_null;
599 response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
601 reply_sesssetup_blob(req, response, ret);
603 data_blob_free(&ap_rep);
604 data_blob_free(&ap_rep_wrapped);
605 data_blob_free(&response);
606 TALLOC_FREE(mem_ctx);
611 /****************************************************************************
612 Send a session setup reply, wrapped in SPNEGO.
613 Get vuid and check first.
614 End the NTLMSSP exchange context if we are OK/complete fail
615 This should be split into two functions, one to handle each
616 leg of the NTLM auth steps.
617 ***************************************************************************/
619 static void reply_spnego_ntlmssp(struct smb_request *req,
621 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
622 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
626 struct auth_serversupplied_info *server_info = NULL;
628 if (NT_STATUS_IS_OK(nt_status)) {
629 server_info = (*auth_ntlmssp_state)->server_info;
631 nt_status = do_map_to_guest(nt_status,
633 (*auth_ntlmssp_state)->ntlmssp_state->user,
634 (*auth_ntlmssp_state)->ntlmssp_state->domain);
637 reply_outbuf(req, 4, 0);
639 SSVAL(req->outbuf, smb_uid, vuid);
641 if (NT_STATUS_IS_OK(nt_status)) {
642 DATA_BLOB nullblob = data_blob_null;
643 DATA_BLOB session_key =
645 (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
646 (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
648 if (!is_partial_auth_vuid(vuid)) {
649 data_blob_free(&session_key);
650 nt_status = NT_STATUS_LOGON_FAILURE;
653 /* register_existing_vuid keeps the server info */
654 if (register_existing_vuid(vuid,
656 session_key, nullblob,
657 (*auth_ntlmssp_state)->ntlmssp_state->user) !=
659 data_blob_free(&session_key);
660 nt_status = NT_STATUS_LOGON_FAILURE;
664 (*auth_ntlmssp_state)->server_info = NULL;
666 /* current_user_info is changed on new vuid */
667 reload_services( True );
669 SSVAL(req->outbuf, smb_vwv3, 0);
671 if (server_info->guest) {
672 SSVAL(req->outbuf,smb_vwv2,1);
675 sessionsetup_start_signing_engine(server_info,
676 (uint8 *)req->inbuf);
682 response = spnego_gen_auth_response(ntlmssp_blob,
683 nt_status, OID_NTLMSSP);
685 response = *ntlmssp_blob;
688 reply_sesssetup_blob(req, response, nt_status);
690 data_blob_free(&response);
693 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
694 and the other end, that we are not finished yet. */
696 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
697 /* NB. This is *NOT* an error case. JRA */
698 auth_ntlmssp_end(auth_ntlmssp_state);
699 if (!NT_STATUS_IS_OK(nt_status)) {
700 /* Kill the intermediate vuid */
701 invalidate_vuid(vuid);
706 /****************************************************************************
707 Is this a krb5 mechanism ?
708 ****************************************************************************/
710 NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out,
713 char *OIDs[ASN1_MAX_OIDS];
718 /* parse out the OIDs and the first sec blob */
719 if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
720 return NT_STATUS_LOGON_FAILURE;
723 /* only look at the first OID for determining the mechToken --
724 according to RFC2478, we should choose the one we want
725 and renegotiate, but i smell a client bug here..
727 Problem observed when connecting to a member (samba box)
728 of an AD domain as a user in a Samba domain. Samba member
729 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
730 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
731 NTLMSSP mechtoken. --jerry */
734 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
735 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
740 for (i=0;OIDs[i];i++) {
741 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
747 /****************************************************************************
748 Reply to a session setup spnego negotiate packet.
749 ****************************************************************************/
751 static void reply_spnego_negotiate(struct smb_request *req,
754 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
758 bool got_kerberos_mechanism = False;
761 status = parse_spnego_mechanisms(blob1, &secblob,
762 &got_kerberos_mechanism);
763 if (!NT_STATUS_IS_OK(status)) {
764 /* Kill the intermediate vuid */
765 invalidate_vuid(vuid);
766 reply_nterror(req, nt_status_squash(status));
770 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
771 (unsigned long)secblob.length));
774 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) ||
775 lp_use_kerberos_keytab()) ) {
776 bool destroy_vuid = True;
777 reply_spnego_kerberos(req, &secblob, vuid,
779 data_blob_free(&secblob);
781 /* Kill the intermediate vuid */
782 invalidate_vuid(vuid);
788 if (*auth_ntlmssp_state) {
789 auth_ntlmssp_end(auth_ntlmssp_state);
792 status = auth_ntlmssp_start(auth_ntlmssp_state);
793 if (!NT_STATUS_IS_OK(status)) {
794 /* Kill the intermediate vuid */
795 invalidate_vuid(vuid);
796 reply_nterror(req, nt_status_squash(status));
800 status = auth_ntlmssp_update(*auth_ntlmssp_state,
803 data_blob_free(&secblob);
805 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
806 &chal, status, True);
808 data_blob_free(&chal);
810 /* already replied */
814 /****************************************************************************
815 Reply to a session setup spnego auth packet.
816 ****************************************************************************/
818 static void reply_spnego_auth(struct smb_request *req,
821 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
823 DATA_BLOB auth = data_blob_null;
824 DATA_BLOB auth_reply = data_blob_null;
825 DATA_BLOB secblob = data_blob_null;
826 NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
828 if (!spnego_parse_auth(blob1, &auth)) {
830 file_save("auth.dat", blob1.data, blob1.length);
832 /* Kill the intermediate vuid */
833 invalidate_vuid(vuid);
835 reply_nterror(req, nt_status_squash(
836 NT_STATUS_INVALID_PARAMETER));
840 if (auth.data[0] == ASN1_APPLICATION(0)) {
841 /* Might be a second negTokenTarg packet */
843 bool got_krb5_mechanism = False;
844 status = parse_spnego_mechanisms(auth, &secblob,
845 &got_krb5_mechanism);
846 if (NT_STATUS_IS_OK(status)) {
847 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
848 (unsigned long)secblob.length));
850 if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) ||
851 lp_use_kerberos_keytab()) ) {
852 bool destroy_vuid = True;
853 reply_spnego_kerberos(req, &secblob,
854 vuid, &destroy_vuid);
855 data_blob_free(&secblob);
856 data_blob_free(&auth);
858 /* Kill the intermediate vuid */
859 invalidate_vuid(vuid);
867 /* If we get here it wasn't a negTokenTarg auth packet. */
868 data_blob_free(&secblob);
870 if (!*auth_ntlmssp_state) {
871 /* Kill the intermediate vuid */
872 invalidate_vuid(vuid);
874 /* auth before negotiatiate? */
875 reply_nterror(req, nt_status_squash(
876 NT_STATUS_INVALID_PARAMETER));
880 status = auth_ntlmssp_update(*auth_ntlmssp_state,
883 data_blob_free(&auth);
885 reply_spnego_ntlmssp(req, vuid,
887 &auth_reply, status, True);
889 data_blob_free(&auth_reply);
891 /* and tell smbd that we have already replied to this packet */
895 /****************************************************************************
896 List to store partial SPNEGO auth fragments.
897 ****************************************************************************/
899 static struct pending_auth_data *pd_list;
901 /****************************************************************************
902 Delete an entry on the list.
903 ****************************************************************************/
905 static void delete_partial_auth(struct pending_auth_data *pad)
910 DLIST_REMOVE(pd_list, pad);
911 data_blob_free(&pad->partial_data);
915 /****************************************************************************
916 Search for a partial SPNEGO auth fragment matching an smbpid.
917 ****************************************************************************/
919 static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
921 struct pending_auth_data *pad;
923 for (pad = pd_list; pad; pad = pad->next) {
924 if (pad->smbpid == smbpid) {
931 /****************************************************************************
932 Check the size of an SPNEGO blob. If we need more return
933 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
934 the blob to be more than 64k.
935 ****************************************************************************/
937 static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid,
940 struct pending_auth_data *pad = NULL;
942 size_t needed_len = 0;
944 pad = get_pending_auth_data(smbpid);
946 /* Ensure we have some data. */
947 if (pblob->length == 0) {
948 /* Caller can cope. */
949 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
950 delete_partial_auth(pad);
954 /* Were we waiting for more data ? */
957 size_t copy_len = MIN(65536, pblob->length);
959 /* Integer wrap paranoia.... */
961 if (pad->partial_data.length + copy_len <
962 pad->partial_data.length ||
963 pad->partial_data.length + copy_len < copy_len) {
965 DEBUG(2,("check_spnego_blob_complete: integer wrap "
966 "pad->partial_data.length = %u, "
968 (unsigned int)pad->partial_data.length,
969 (unsigned int)copy_len ));
971 delete_partial_auth(pad);
972 return NT_STATUS_INVALID_PARAMETER;
975 DEBUG(10,("check_spnego_blob_complete: "
976 "pad->partial_data.length = %u, "
977 "pad->needed_len = %u, "
979 "pblob->length = %u,\n",
980 (unsigned int)pad->partial_data.length,
981 (unsigned int)pad->needed_len,
982 (unsigned int)copy_len,
983 (unsigned int)pblob->length ));
985 tmp_blob = data_blob(NULL,
986 pad->partial_data.length + copy_len);
988 /* Concatenate the two (up to copy_len) bytes. */
989 memcpy(tmp_blob.data,
990 pad->partial_data.data,
991 pad->partial_data.length);
992 memcpy(tmp_blob.data + pad->partial_data.length,
996 /* Replace the partial data. */
997 data_blob_free(&pad->partial_data);
998 pad->partial_data = tmp_blob;
999 ZERO_STRUCT(tmp_blob);
1002 if (pblob->length >= pad->needed_len) {
1003 /* Yes, replace pblob. */
1004 data_blob_free(pblob);
1005 *pblob = pad->partial_data;
1006 ZERO_STRUCT(pad->partial_data);
1007 delete_partial_auth(pad);
1008 return NT_STATUS_OK;
1011 /* Still need more data. */
1012 pad->needed_len -= copy_len;
1013 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1016 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
1017 (pblob->data[0] != ASN1_CONTEXT(1))) {
1018 /* Not something we can determine the
1021 return NT_STATUS_OK;
1024 /* This is a new SPNEGO sessionsetup - see if
1025 * the data given in this blob is enough.
1028 asn1_load(&data, *pblob);
1029 asn1_start_tag(&data, pblob->data[0]);
1030 if (data.has_error || data.nesting == NULL) {
1032 /* Let caller catch. */
1033 return NT_STATUS_OK;
1036 /* Integer wrap paranoia.... */
1038 if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
1039 data.nesting->taglen + data.nesting->start < data.nesting->start) {
1041 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1042 "data.nesting->taglen = %u, "
1043 "data.nesting->start = %u\n",
1044 (unsigned int)data.nesting->taglen,
1045 (unsigned int)data.nesting->start ));
1048 return NT_STATUS_INVALID_PARAMETER;
1051 /* Total length of the needed asn1 is the tag length
1052 * plus the current offset. */
1054 needed_len = data.nesting->taglen + data.nesting->start;
1057 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1058 "pblob->length = %u\n",
1059 (unsigned int)needed_len,
1060 (unsigned int)pblob->length ));
1062 if (needed_len <= pblob->length) {
1063 /* Nothing to do - blob is complete. */
1064 return NT_STATUS_OK;
1067 /* Refuse the blob if it's bigger than 64k. */
1068 if (needed_len > 65536) {
1069 DEBUG(2,("check_spnego_blob_complete: needed_len "
1071 (unsigned int)needed_len ));
1072 return NT_STATUS_INVALID_PARAMETER;
1075 /* We must store this blob until complete. */
1076 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1077 return NT_STATUS_NO_MEMORY;
1079 pad->needed_len = needed_len - pblob->length;
1080 pad->partial_data = data_blob(pblob->data, pblob->length);
1081 if (pad->partial_data.data == NULL) {
1083 return NT_STATUS_NO_MEMORY;
1085 pad->smbpid = smbpid;
1087 DLIST_ADD(pd_list, pad);
1089 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1092 /****************************************************************************
1093 Reply to a session setup command.
1094 conn POINTER CAN BE NULL HERE !
1095 ****************************************************************************/
1097 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1102 fstring native_os, native_lanman, primary_domain;
1104 uint16 data_blob_len = SVAL(req->inbuf, smb_vwv7);
1105 enum remote_arch_types ra_type = get_remote_arch();
1106 int vuid = SVAL(req->inbuf,smb_uid);
1107 user_struct *vuser = NULL;
1108 NTSTATUS status = NT_STATUS_OK;
1109 uint16 smbpid = req->smbpid;
1110 uint16 smb_flag2 = req->flags2;
1112 DEBUG(3,("Doing spnego session setup\n"));
1114 if (global_client_caps == 0) {
1115 global_client_caps = IVAL(req->inbuf,smb_vwv10);
1117 if (!(global_client_caps & CAP_STATUS32)) {
1118 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1123 p = (uint8 *)smb_buf(req->inbuf);
1125 if (data_blob_len == 0) {
1126 /* an invalid request */
1127 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1131 bufrem = smb_bufrem(req->inbuf, p);
1132 /* pull the spnego blob */
1133 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1136 file_save("negotiate.dat", blob1.data, blob1.length);
1139 p2 = (char *)req->inbuf + smb_vwv13 + data_blob_len;
1140 p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_os, p2,
1141 sizeof(native_os), STR_TERMINATE);
1142 p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_lanman, p2,
1143 sizeof(native_lanman), STR_TERMINATE);
1144 p2 += srvstr_pull_buf(req->inbuf, smb_flag2, primary_domain, p2,
1145 sizeof(primary_domain), STR_TERMINATE);
1146 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1147 native_os, native_lanman, primary_domain));
1149 if ( ra_type == RA_WIN2K ) {
1150 /* Vista sets neither the OS or lanman strings */
1152 if ( !strlen(native_os) && !strlen(native_lanman) )
1153 set_remote_arch(RA_VISTA);
1155 /* Windows 2003 doesn't set the native lanman string,
1156 but does set primary domain which is a bug I think */
1158 if ( !strlen(native_lanman) ) {
1159 ra_lanman_string( primary_domain );
1161 ra_lanman_string( native_lanman );
1165 /* Did we get a valid vuid ? */
1166 if (!is_partial_auth_vuid(vuid)) {
1167 /* No, then try and see if this is an intermediate sessionsetup
1168 * for a large SPNEGO packet. */
1169 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
1171 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1172 "pending vuid %u\n",
1173 (unsigned int)pad->vuid ));
1178 /* Do we have a valid vuid now ? */
1179 if (!is_partial_auth_vuid(vuid)) {
1180 /* No, start a new authentication setup. */
1181 vuid = register_initial_vuid();
1182 if (vuid == UID_FIELD_INVALID) {
1183 data_blob_free(&blob1);
1184 reply_nterror(req, nt_status_squash(
1185 NT_STATUS_INVALID_PARAMETER));
1190 vuser = get_partial_auth_user_struct(vuid);
1191 /* This MUST be valid. */
1193 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1196 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1197 * sessionsetup requests as the Windows limit on the security blob
1198 * field is 4k. Bug #4400. JRA.
1201 status = check_spnego_blob_complete(smbpid, vuid, &blob1);
1202 if (!NT_STATUS_IS_OK(status)) {
1203 if (!NT_STATUS_EQUAL(status,
1204 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1205 /* Real error - kill the intermediate vuid */
1206 invalidate_vuid(vuid);
1208 data_blob_free(&blob1);
1209 reply_nterror(req, nt_status_squash(status));
1213 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1215 /* its a negTokenTarg packet */
1217 reply_spnego_negotiate(req, vuid, blob1,
1218 &vuser->auth_ntlmssp_state);
1219 data_blob_free(&blob1);
1223 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1225 /* its a auth packet */
1227 reply_spnego_auth(req, vuid, blob1,
1228 &vuser->auth_ntlmssp_state);
1229 data_blob_free(&blob1);
1233 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1236 if (!vuser->auth_ntlmssp_state) {
1237 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1238 if (!NT_STATUS_IS_OK(status)) {
1239 /* Kill the intermediate vuid */
1240 invalidate_vuid(vuid);
1241 data_blob_free(&blob1);
1242 reply_nterror(req, nt_status_squash(status));
1247 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1250 data_blob_free(&blob1);
1252 reply_spnego_ntlmssp(req, vuid,
1253 &vuser->auth_ntlmssp_state,
1254 &chal, status, False);
1255 data_blob_free(&chal);
1259 /* what sort of packet is this? */
1260 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1262 data_blob_free(&blob1);
1264 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1267 /****************************************************************************
1268 On new VC == 0, shutdown *all* old connections and users.
1269 It seems that only NT4.x does this. At W2K and above (XP etc.).
1270 a new session setup with VC==0 is ignored.
1271 ****************************************************************************/
1273 static int shutdown_other_smbds(struct db_record *rec,
1274 const struct connections_key *key,
1275 const struct connections_data *crec,
1278 const char *ip = (const char *)private_data;
1280 if (!process_exists(crec->pid)) {
1284 if (procid_is_me(&crec->pid)) {
1288 if (strcmp(ip, crec->addr) != 0) {
1292 messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1297 static void setup_new_vc_session(void)
1299 char addr[INET6_ADDRSTRLEN];
1301 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1302 "compatible we would close all old resources.\n"));
1305 invalidate_all_vuids();
1307 if (lp_reset_on_zero_vc()) {
1308 connections_forall(shutdown_other_smbds,
1309 CONST_DISCARD(void *,
1310 client_addr(get_client_fd(),addr,sizeof(addr))));
1314 /****************************************************************************
1315 Reply to a session setup command.
1316 ****************************************************************************/
1318 void reply_sesssetup_and_X(struct smb_request *req)
1324 DATA_BLOB plaintext_password;
1326 fstring sub_user; /* Sainitised username for substituion */
1329 fstring native_lanman;
1330 fstring primary_domain;
1331 static bool done_sesssetup = False;
1332 auth_usersupplied_info *user_info = NULL;
1333 auth_serversupplied_info *server_info = NULL;
1334 uint16 smb_flag2 = req->flags2;
1338 bool doencrypt = global_encrypted_passwords_negotiated;
1340 DATA_BLOB session_key;
1342 START_PROFILE(SMBsesssetupX);
1344 ZERO_STRUCT(lm_resp);
1345 ZERO_STRUCT(nt_resp);
1346 ZERO_STRUCT(plaintext_password);
1348 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1350 /* a SPNEGO session setup has 12 command words, whereas a normal
1351 NT1 session setup has 13. See the cifs spec. */
1352 if (req->wct == 12 &&
1353 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1355 if (!global_spnego_negotiated) {
1356 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1357 "at SPNEGO session setup when it was not "
1359 reply_nterror(req, nt_status_squash(
1360 NT_STATUS_LOGON_FAILURE));
1361 END_PROFILE(SMBsesssetupX);
1365 if (SVAL(req->inbuf,smb_vwv4) == 0) {
1366 setup_new_vc_session();
1369 reply_sesssetup_and_X_spnego(req);
1370 END_PROFILE(SMBsesssetupX);
1374 smb_bufsize = SVAL(req->inbuf,smb_vwv2);
1376 if (Protocol < PROTOCOL_NT1) {
1377 uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
1379 /* Never do NT status codes with protocols before NT1 as we
1380 * don't get client caps. */
1381 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1383 if ((passlen1 > MAX_PASS_LEN)
1384 || (passlen1 > smb_bufrem(req->inbuf,
1385 smb_buf(req->inbuf)))) {
1386 reply_nterror(req, nt_status_squash(
1387 NT_STATUS_INVALID_PARAMETER));
1388 END_PROFILE(SMBsesssetupX);
1393 lm_resp = data_blob(smb_buf(req->inbuf), passlen1);
1395 plaintext_password = data_blob(smb_buf(req->inbuf),
1397 /* Ensure null termination */
1398 plaintext_password.data[passlen1] = 0;
1401 srvstr_pull_buf(req->inbuf, req->flags2, user,
1402 smb_buf(req->inbuf)+passlen1, sizeof(user),
1407 uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
1408 uint16 passlen2 = SVAL(req->inbuf,smb_vwv8);
1409 enum remote_arch_types ra_type = get_remote_arch();
1410 char *p = smb_buf(req->inbuf);
1411 char *save_p = smb_buf(req->inbuf);
1415 if(global_client_caps == 0) {
1416 global_client_caps = IVAL(req->inbuf,smb_vwv11);
1418 if (!(global_client_caps & CAP_STATUS32)) {
1419 remove_from_common_flags2(
1420 FLAGS2_32_BIT_ERROR_CODES);
1423 /* client_caps is used as final determination if
1424 * client is NT or Win95. This is needed to return
1425 * the correct error codes in some circumstances.
1428 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1429 ra_type == RA_WIN95) {
1430 if(!(global_client_caps & (CAP_NT_SMBS|
1432 set_remote_arch( RA_WIN95);
1438 /* both Win95 and WinNT stuff up the password
1439 * lengths for non-encrypting systems. Uggh.
1441 if passlen1==24 its a win95 system, and its setting
1442 the password length incorrectly. Luckily it still
1443 works with the default code because Win95 will null
1444 terminate the password anyway
1446 if passlen1>0 and passlen2>0 then maybe its a NT box
1447 and its setting passlen2 to some random value which
1448 really stuffs things up. we need to fix that one. */
1450 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1456 /* check for nasty tricks */
1457 if (passlen1 > MAX_PASS_LEN
1458 || passlen1 > smb_bufrem(req->inbuf, p)) {
1459 reply_nterror(req, nt_status_squash(
1460 NT_STATUS_INVALID_PARAMETER));
1461 END_PROFILE(SMBsesssetupX);
1465 if (passlen2 > MAX_PASS_LEN
1466 || passlen2 > smb_bufrem(req->inbuf, p+passlen1)) {
1467 reply_nterror(req, nt_status_squash(
1468 NT_STATUS_INVALID_PARAMETER));
1469 END_PROFILE(SMBsesssetupX);
1473 /* Save the lanman2 password and the NT md4 password. */
1475 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1480 lm_resp = data_blob(p, passlen1);
1481 nt_resp = data_blob(p+passlen1, passlen2);
1484 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1486 if (unic && (passlen2 == 0) && passlen1) {
1487 /* Only a ascii plaintext password was sent. */
1488 (void)srvstr_pull_talloc(talloc_tos(),
1492 smb_buf(req->inbuf),
1494 STR_TERMINATE|STR_ASCII);
1496 (void)srvstr_pull_talloc(talloc_tos(),
1500 smb_buf(req->inbuf),
1501 unic ? passlen2 : passlen1,
1505 reply_nterror(req, nt_status_squash(
1506 NT_STATUS_INVALID_PARAMETER));
1507 END_PROFILE(SMBsesssetupX);
1510 plaintext_password = data_blob(pass, strlen(pass)+1);
1513 p += passlen1 + passlen2;
1514 p += srvstr_pull_buf(req->inbuf, req->flags2, user, p,
1515 sizeof(user), STR_TERMINATE);
1516 p += srvstr_pull_buf(req->inbuf, req->flags2, domain, p,
1517 sizeof(domain), STR_TERMINATE);
1518 p += srvstr_pull_buf(req->inbuf, req->flags2, native_os,
1519 p, sizeof(native_os), STR_TERMINATE);
1520 p += srvstr_pull_buf(req->inbuf, req->flags2,
1521 native_lanman, p, sizeof(native_lanman),
1524 /* not documented or decoded by Ethereal but there is one more
1525 * string in the extra bytes which is the same as the
1526 * PrimaryDomain when using extended security. Windows NT 4
1527 * and 2003 use this string to store the native lanman string.
1528 * Windows 9x does not include a string here at all so we have
1529 * to check if we have any extra bytes left */
1531 byte_count = SVAL(req->inbuf, smb_vwv13);
1532 if ( PTR_DIFF(p, save_p) < byte_count) {
1533 p += srvstr_pull_buf(req->inbuf, req->flags2,
1535 sizeof(primary_domain),
1538 fstrcpy( primary_domain, "null" );
1541 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1542 "PrimaryDomain=[%s]\n",
1543 domain, native_os, native_lanman, primary_domain));
1545 if ( ra_type == RA_WIN2K ) {
1546 if ( strlen(native_lanman) == 0 )
1547 ra_lanman_string( primary_domain );
1549 ra_lanman_string( native_lanman );
1554 if (SVAL(req->inbuf,smb_vwv4) == 0) {
1555 setup_new_vc_session();
1558 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1559 domain, user, get_remote_machine_name()));
1562 if (global_spnego_negotiated) {
1564 /* This has to be here, because this is a perfectly
1565 * valid behaviour for guest logons :-( */
1567 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1568 "at 'normal' session setup after "
1569 "negotiating spnego.\n"));
1570 reply_nterror(req, nt_status_squash(
1571 NT_STATUS_LOGON_FAILURE));
1572 END_PROFILE(SMBsesssetupX);
1575 fstrcpy(sub_user, user);
1577 fstrcpy(sub_user, lp_guestaccount());
1580 sub_set_smb_name(sub_user);
1582 reload_services(True);
1584 if (lp_security() == SEC_SHARE) {
1585 /* in share level we should ignore any passwords */
1587 data_blob_free(&lm_resp);
1588 data_blob_free(&nt_resp);
1589 data_blob_clear_free(&plaintext_password);
1591 map_username(sub_user);
1592 add_session_user(sub_user);
1593 add_session_workgroup(domain);
1594 /* Then force it to null for the benfit of the code below */
1600 nt_status = check_guest_password(&server_info);
1602 } else if (doencrypt) {
1603 if (!negprot_global_auth_context) {
1604 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1605 "session setup without negprot denied!\n"));
1606 reply_nterror(req, nt_status_squash(
1607 NT_STATUS_LOGON_FAILURE));
1608 END_PROFILE(SMBsesssetupX);
1611 nt_status = make_user_info_for_reply_enc(&user_info, user,
1614 if (NT_STATUS_IS_OK(nt_status)) {
1615 nt_status = negprot_global_auth_context->check_ntlm_password(
1616 negprot_global_auth_context,
1621 struct auth_context *plaintext_auth_context = NULL;
1624 nt_status = make_auth_context_subsystem(
1625 &plaintext_auth_context);
1627 if (NT_STATUS_IS_OK(nt_status)) {
1628 chal = plaintext_auth_context->get_ntlm_challenge(
1629 plaintext_auth_context);
1631 if (!make_user_info_for_reply(&user_info,
1633 plaintext_password)) {
1634 nt_status = NT_STATUS_NO_MEMORY;
1637 if (NT_STATUS_IS_OK(nt_status)) {
1638 nt_status = plaintext_auth_context->check_ntlm_password(
1639 plaintext_auth_context,
1643 (plaintext_auth_context->free)(
1644 &plaintext_auth_context);
1649 free_user_info(&user_info);
1651 if (!NT_STATUS_IS_OK(nt_status)) {
1652 nt_status = do_map_to_guest(nt_status, &server_info,
1656 if (!NT_STATUS_IS_OK(nt_status)) {
1657 data_blob_free(&nt_resp);
1658 data_blob_free(&lm_resp);
1659 data_blob_clear_free(&plaintext_password);
1660 reply_nterror(req, nt_status_squash(nt_status));
1661 END_PROFILE(SMBsesssetupX);
1665 /* Ensure we can't possible take a code path leading to a
1668 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1669 END_PROFILE(SMBsesssetupX);
1673 nt_status = create_local_token(server_info);
1674 if (!NT_STATUS_IS_OK(nt_status)) {
1675 DEBUG(10, ("create_local_token failed: %s\n",
1676 nt_errstr(nt_status)));
1677 data_blob_free(&nt_resp);
1678 data_blob_free(&lm_resp);
1679 data_blob_clear_free(&plaintext_password);
1680 reply_nterror(req, nt_status_squash(nt_status));
1681 END_PROFILE(SMBsesssetupX);
1685 if (server_info->user_session_key.data) {
1686 session_key = data_blob(server_info->user_session_key.data,
1687 server_info->user_session_key.length);
1689 session_key = data_blob_null;
1692 data_blob_clear_free(&plaintext_password);
1694 /* it's ok - setup a reply */
1695 reply_outbuf(req, 3, 0);
1696 if (Protocol >= PROTOCOL_NT1) {
1697 push_signature(&req->outbuf);
1698 /* perhaps grab OS version here?? */
1701 if (server_info->guest) {
1702 SSVAL(req->outbuf,smb_vwv2,1);
1705 /* register the name and uid as being validated, so further connections
1706 to a uid can get through without a password, on the same VC */
1708 if (lp_security() == SEC_SHARE) {
1709 sess_vuid = UID_FIELD_INVALID;
1710 data_blob_free(&session_key);
1711 TALLOC_FREE(server_info);
1713 /* Ignore the initial vuid. */
1714 sess_vuid = register_initial_vuid();
1715 if (sess_vuid == UID_FIELD_INVALID) {
1716 data_blob_free(&nt_resp);
1717 data_blob_free(&lm_resp);
1718 data_blob_free(&session_key);
1719 reply_nterror(req, nt_status_squash(
1720 NT_STATUS_LOGON_FAILURE));
1721 END_PROFILE(SMBsesssetupX);
1724 /* register_existing_vuid keeps the server info */
1725 sess_vuid = register_existing_vuid(sess_vuid,
1728 nt_resp.data ? nt_resp : lm_resp,
1730 if (sess_vuid == UID_FIELD_INVALID) {
1731 data_blob_free(&nt_resp);
1732 data_blob_free(&lm_resp);
1733 data_blob_free(&session_key);
1734 reply_nterror(req, nt_status_squash(
1735 NT_STATUS_LOGON_FAILURE));
1736 END_PROFILE(SMBsesssetupX);
1740 /* current_user_info is changed on new vuid */
1741 reload_services( True );
1743 sessionsetup_start_signing_engine(server_info, req->inbuf);
1746 data_blob_free(&nt_resp);
1747 data_blob_free(&lm_resp);
1749 SSVAL(req->outbuf,smb_uid,sess_vuid);
1750 SSVAL(req->inbuf,smb_uid,sess_vuid);
1752 if (!done_sesssetup)
1753 max_send = MIN(max_send,smb_bufsize);
1755 done_sesssetup = True;
1757 END_PROFILE(SMBsesssetupX);