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 if (username_was_mapped) {
541 server_info->was_mapped = username_was_mapped;
544 /* we need to build the token for the user. make_server_info_guest()
547 if ( !server_info->ptok ) {
548 ret = create_local_token( server_info );
549 if ( !NT_STATUS_IS_OK(ret) ) {
551 data_blob_free(&ap_rep);
552 data_blob_free(&session_key);
553 TALLOC_FREE( mem_ctx );
554 TALLOC_FREE( server_info );
555 reply_nterror(req, nt_status_squash(ret));
560 /* register_existing_vuid keeps the server info */
561 /* register_existing_vuid takes ownership of session_key on success,
562 * no need to free after this on success. A better interface would copy
565 if (!is_partial_auth_vuid(sess_vuid)) {
566 sess_vuid = register_initial_vuid();
568 sess_vuid = register_existing_vuid(sess_vuid,
576 reply_outbuf(req, 4, 0);
577 SSVAL(req->outbuf,smb_uid,sess_vuid);
579 if (sess_vuid == UID_FIELD_INVALID ) {
580 ret = NT_STATUS_LOGON_FAILURE;
581 data_blob_free(&session_key);
583 /* current_user_info is changed on new vuid */
584 reload_services( True );
586 SSVAL(req->outbuf, smb_vwv3, 0);
588 if (server_info->guest) {
589 SSVAL(req->outbuf,smb_vwv2,1);
592 SSVAL(req->outbuf, smb_uid, sess_vuid);
594 sessionsetup_start_signing_engine(server_info, req->inbuf);
595 /* Successful logon. Keep this vuid. */
596 *p_invalidate_vuid = False;
599 /* wrap that up in a nice GSS-API wrapping */
600 if (NT_STATUS_IS_OK(ret)) {
601 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
604 ap_rep_wrapped = data_blob_null;
606 response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
608 reply_sesssetup_blob(req, response, ret);
610 data_blob_free(&ap_rep);
611 data_blob_free(&ap_rep_wrapped);
612 data_blob_free(&response);
613 TALLOC_FREE(mem_ctx);
618 /****************************************************************************
619 Send a session setup reply, wrapped in SPNEGO.
620 Get vuid and check first.
621 End the NTLMSSP exchange context if we are OK/complete fail
622 This should be split into two functions, one to handle each
623 leg of the NTLM auth steps.
624 ***************************************************************************/
626 static void reply_spnego_ntlmssp(struct smb_request *req,
628 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
629 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
633 struct auth_serversupplied_info *server_info = NULL;
635 if (NT_STATUS_IS_OK(nt_status)) {
636 server_info = (*auth_ntlmssp_state)->server_info;
638 nt_status = do_map_to_guest(nt_status,
640 (*auth_ntlmssp_state)->ntlmssp_state->user,
641 (*auth_ntlmssp_state)->ntlmssp_state->domain);
644 reply_outbuf(req, 4, 0);
646 SSVAL(req->outbuf, smb_uid, vuid);
648 if (NT_STATUS_IS_OK(nt_status)) {
649 DATA_BLOB nullblob = data_blob_null;
650 DATA_BLOB session_key =
652 (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
653 (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
655 if (!is_partial_auth_vuid(vuid)) {
656 data_blob_free(&session_key);
657 nt_status = NT_STATUS_LOGON_FAILURE;
660 /* register_existing_vuid keeps the server info */
661 if (register_existing_vuid(vuid,
663 session_key, nullblob,
664 (*auth_ntlmssp_state)->ntlmssp_state->user) !=
666 data_blob_free(&session_key);
667 nt_status = NT_STATUS_LOGON_FAILURE;
671 (*auth_ntlmssp_state)->server_info = NULL;
673 /* current_user_info is changed on new vuid */
674 reload_services( True );
676 SSVAL(req->outbuf, smb_vwv3, 0);
678 if (server_info->guest) {
679 SSVAL(req->outbuf,smb_vwv2,1);
682 sessionsetup_start_signing_engine(server_info,
683 (uint8 *)req->inbuf);
689 response = spnego_gen_auth_response(ntlmssp_blob,
690 nt_status, OID_NTLMSSP);
692 response = *ntlmssp_blob;
695 reply_sesssetup_blob(req, response, nt_status);
697 data_blob_free(&response);
700 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
701 and the other end, that we are not finished yet. */
703 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
704 /* NB. This is *NOT* an error case. JRA */
705 auth_ntlmssp_end(auth_ntlmssp_state);
706 if (!NT_STATUS_IS_OK(nt_status)) {
707 /* Kill the intermediate vuid */
708 invalidate_vuid(vuid);
713 /****************************************************************************
714 Is this a krb5 mechanism ?
715 ****************************************************************************/
717 NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out,
720 char *OIDs[ASN1_MAX_OIDS];
725 /* parse out the OIDs and the first sec blob */
726 if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
727 return NT_STATUS_LOGON_FAILURE;
730 /* only look at the first OID for determining the mechToken --
731 according to RFC2478, we should choose the one we want
732 and renegotiate, but i smell a client bug here..
734 Problem observed when connecting to a member (samba box)
735 of an AD domain as a user in a Samba domain. Samba member
736 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
737 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
738 NTLMSSP mechtoken. --jerry */
741 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
742 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
747 for (i=0;OIDs[i];i++) {
748 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
754 /****************************************************************************
755 Reply to a session setup spnego negotiate packet.
756 ****************************************************************************/
758 static void reply_spnego_negotiate(struct smb_request *req,
761 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
765 bool got_kerberos_mechanism = False;
768 status = parse_spnego_mechanisms(blob1, &secblob,
769 &got_kerberos_mechanism);
770 if (!NT_STATUS_IS_OK(status)) {
771 /* Kill the intermediate vuid */
772 invalidate_vuid(vuid);
773 reply_nterror(req, nt_status_squash(status));
777 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
778 (unsigned long)secblob.length));
781 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) ||
782 lp_use_kerberos_keytab()) ) {
783 bool destroy_vuid = True;
784 reply_spnego_kerberos(req, &secblob, vuid,
786 data_blob_free(&secblob);
788 /* Kill the intermediate vuid */
789 invalidate_vuid(vuid);
795 if (*auth_ntlmssp_state) {
796 auth_ntlmssp_end(auth_ntlmssp_state);
799 status = auth_ntlmssp_start(auth_ntlmssp_state);
800 if (!NT_STATUS_IS_OK(status)) {
801 /* Kill the intermediate vuid */
802 invalidate_vuid(vuid);
803 reply_nterror(req, nt_status_squash(status));
807 status = auth_ntlmssp_update(*auth_ntlmssp_state,
810 data_blob_free(&secblob);
812 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
813 &chal, status, True);
815 data_blob_free(&chal);
817 /* already replied */
821 /****************************************************************************
822 Reply to a session setup spnego auth packet.
823 ****************************************************************************/
825 static void reply_spnego_auth(struct smb_request *req,
828 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
830 DATA_BLOB auth = data_blob_null;
831 DATA_BLOB auth_reply = data_blob_null;
832 DATA_BLOB secblob = data_blob_null;
833 NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
835 if (!spnego_parse_auth(blob1, &auth)) {
837 file_save("auth.dat", blob1.data, blob1.length);
839 /* Kill the intermediate vuid */
840 invalidate_vuid(vuid);
842 reply_nterror(req, nt_status_squash(
843 NT_STATUS_INVALID_PARAMETER));
847 if (auth.data[0] == ASN1_APPLICATION(0)) {
848 /* Might be a second negTokenTarg packet */
850 bool got_krb5_mechanism = False;
851 status = parse_spnego_mechanisms(auth, &secblob,
852 &got_krb5_mechanism);
853 if (NT_STATUS_IS_OK(status)) {
854 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
855 (unsigned long)secblob.length));
857 if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) ||
858 lp_use_kerberos_keytab()) ) {
859 bool destroy_vuid = True;
860 reply_spnego_kerberos(req, &secblob,
861 vuid, &destroy_vuid);
862 data_blob_free(&secblob);
863 data_blob_free(&auth);
865 /* Kill the intermediate vuid */
866 invalidate_vuid(vuid);
874 /* If we get here it wasn't a negTokenTarg auth packet. */
875 data_blob_free(&secblob);
877 if (!*auth_ntlmssp_state) {
878 /* Kill the intermediate vuid */
879 invalidate_vuid(vuid);
881 /* auth before negotiatiate? */
882 reply_nterror(req, nt_status_squash(
883 NT_STATUS_INVALID_PARAMETER));
887 status = auth_ntlmssp_update(*auth_ntlmssp_state,
890 data_blob_free(&auth);
892 reply_spnego_ntlmssp(req, vuid,
894 &auth_reply, status, True);
896 data_blob_free(&auth_reply);
898 /* and tell smbd that we have already replied to this packet */
902 /****************************************************************************
903 List to store partial SPNEGO auth fragments.
904 ****************************************************************************/
906 static struct pending_auth_data *pd_list;
908 /****************************************************************************
909 Delete an entry on the list.
910 ****************************************************************************/
912 static void delete_partial_auth(struct pending_auth_data *pad)
917 DLIST_REMOVE(pd_list, pad);
918 data_blob_free(&pad->partial_data);
922 /****************************************************************************
923 Search for a partial SPNEGO auth fragment matching an smbpid.
924 ****************************************************************************/
926 static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
928 struct pending_auth_data *pad;
930 for (pad = pd_list; pad; pad = pad->next) {
931 if (pad->smbpid == smbpid) {
938 /****************************************************************************
939 Check the size of an SPNEGO blob. If we need more return
940 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
941 the blob to be more than 64k.
942 ****************************************************************************/
944 static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid,
947 struct pending_auth_data *pad = NULL;
949 size_t needed_len = 0;
951 pad = get_pending_auth_data(smbpid);
953 /* Ensure we have some data. */
954 if (pblob->length == 0) {
955 /* Caller can cope. */
956 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
957 delete_partial_auth(pad);
961 /* Were we waiting for more data ? */
964 size_t copy_len = MIN(65536, pblob->length);
966 /* Integer wrap paranoia.... */
968 if (pad->partial_data.length + copy_len <
969 pad->partial_data.length ||
970 pad->partial_data.length + copy_len < copy_len) {
972 DEBUG(2,("check_spnego_blob_complete: integer wrap "
973 "pad->partial_data.length = %u, "
975 (unsigned int)pad->partial_data.length,
976 (unsigned int)copy_len ));
978 delete_partial_auth(pad);
979 return NT_STATUS_INVALID_PARAMETER;
982 DEBUG(10,("check_spnego_blob_complete: "
983 "pad->partial_data.length = %u, "
984 "pad->needed_len = %u, "
986 "pblob->length = %u,\n",
987 (unsigned int)pad->partial_data.length,
988 (unsigned int)pad->needed_len,
989 (unsigned int)copy_len,
990 (unsigned int)pblob->length ));
992 tmp_blob = data_blob(NULL,
993 pad->partial_data.length + copy_len);
995 /* Concatenate the two (up to copy_len) bytes. */
996 memcpy(tmp_blob.data,
997 pad->partial_data.data,
998 pad->partial_data.length);
999 memcpy(tmp_blob.data + pad->partial_data.length,
1003 /* Replace the partial data. */
1004 data_blob_free(&pad->partial_data);
1005 pad->partial_data = tmp_blob;
1006 ZERO_STRUCT(tmp_blob);
1009 if (pblob->length >= pad->needed_len) {
1010 /* Yes, replace pblob. */
1011 data_blob_free(pblob);
1012 *pblob = pad->partial_data;
1013 ZERO_STRUCT(pad->partial_data);
1014 delete_partial_auth(pad);
1015 return NT_STATUS_OK;
1018 /* Still need more data. */
1019 pad->needed_len -= copy_len;
1020 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1023 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
1024 (pblob->data[0] != ASN1_CONTEXT(1))) {
1025 /* Not something we can determine the
1028 return NT_STATUS_OK;
1031 /* This is a new SPNEGO sessionsetup - see if
1032 * the data given in this blob is enough.
1035 asn1_load(&data, *pblob);
1036 asn1_start_tag(&data, pblob->data[0]);
1037 if (data.has_error || data.nesting == NULL) {
1039 /* Let caller catch. */
1040 return NT_STATUS_OK;
1043 /* Integer wrap paranoia.... */
1045 if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
1046 data.nesting->taglen + data.nesting->start < data.nesting->start) {
1048 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1049 "data.nesting->taglen = %u, "
1050 "data.nesting->start = %u\n",
1051 (unsigned int)data.nesting->taglen,
1052 (unsigned int)data.nesting->start ));
1055 return NT_STATUS_INVALID_PARAMETER;
1058 /* Total length of the needed asn1 is the tag length
1059 * plus the current offset. */
1061 needed_len = data.nesting->taglen + data.nesting->start;
1064 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1065 "pblob->length = %u\n",
1066 (unsigned int)needed_len,
1067 (unsigned int)pblob->length ));
1069 if (needed_len <= pblob->length) {
1070 /* Nothing to do - blob is complete. */
1071 return NT_STATUS_OK;
1074 /* Refuse the blob if it's bigger than 64k. */
1075 if (needed_len > 65536) {
1076 DEBUG(2,("check_spnego_blob_complete: needed_len "
1078 (unsigned int)needed_len ));
1079 return NT_STATUS_INVALID_PARAMETER;
1082 /* We must store this blob until complete. */
1083 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1084 return NT_STATUS_NO_MEMORY;
1086 pad->needed_len = needed_len - pblob->length;
1087 pad->partial_data = data_blob(pblob->data, pblob->length);
1088 if (pad->partial_data.data == NULL) {
1090 return NT_STATUS_NO_MEMORY;
1092 pad->smbpid = smbpid;
1094 DLIST_ADD(pd_list, pad);
1096 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1099 /****************************************************************************
1100 Reply to a session setup command.
1101 conn POINTER CAN BE NULL HERE !
1102 ****************************************************************************/
1104 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1109 fstring native_os, native_lanman, primary_domain;
1111 uint16 data_blob_len = SVAL(req->inbuf, smb_vwv7);
1112 enum remote_arch_types ra_type = get_remote_arch();
1113 int vuid = SVAL(req->inbuf,smb_uid);
1114 user_struct *vuser = NULL;
1115 NTSTATUS status = NT_STATUS_OK;
1116 uint16 smbpid = req->smbpid;
1117 uint16 smb_flag2 = req->flags2;
1119 DEBUG(3,("Doing spnego session setup\n"));
1121 if (global_client_caps == 0) {
1122 global_client_caps = IVAL(req->inbuf,smb_vwv10);
1124 if (!(global_client_caps & CAP_STATUS32)) {
1125 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1130 p = (uint8 *)smb_buf(req->inbuf);
1132 if (data_blob_len == 0) {
1133 /* an invalid request */
1134 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1138 bufrem = smb_bufrem(req->inbuf, p);
1139 /* pull the spnego blob */
1140 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1143 file_save("negotiate.dat", blob1.data, blob1.length);
1146 p2 = (char *)req->inbuf + smb_vwv13 + data_blob_len;
1147 p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_os, p2,
1148 sizeof(native_os), STR_TERMINATE);
1149 p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_lanman, p2,
1150 sizeof(native_lanman), STR_TERMINATE);
1151 p2 += srvstr_pull_buf(req->inbuf, smb_flag2, primary_domain, p2,
1152 sizeof(primary_domain), STR_TERMINATE);
1153 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1154 native_os, native_lanman, primary_domain));
1156 if ( ra_type == RA_WIN2K ) {
1157 /* Vista sets neither the OS or lanman strings */
1159 if ( !strlen(native_os) && !strlen(native_lanman) )
1160 set_remote_arch(RA_VISTA);
1162 /* Windows 2003 doesn't set the native lanman string,
1163 but does set primary domain which is a bug I think */
1165 if ( !strlen(native_lanman) ) {
1166 ra_lanman_string( primary_domain );
1168 ra_lanman_string( native_lanman );
1172 /* Did we get a valid vuid ? */
1173 if (!is_partial_auth_vuid(vuid)) {
1174 /* No, then try and see if this is an intermediate sessionsetup
1175 * for a large SPNEGO packet. */
1176 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
1178 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1179 "pending vuid %u\n",
1180 (unsigned int)pad->vuid ));
1185 /* Do we have a valid vuid now ? */
1186 if (!is_partial_auth_vuid(vuid)) {
1187 /* No, start a new authentication setup. */
1188 vuid = register_initial_vuid();
1189 if (vuid == UID_FIELD_INVALID) {
1190 data_blob_free(&blob1);
1191 reply_nterror(req, nt_status_squash(
1192 NT_STATUS_INVALID_PARAMETER));
1197 vuser = get_partial_auth_user_struct(vuid);
1198 /* This MUST be valid. */
1200 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1203 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1204 * sessionsetup requests as the Windows limit on the security blob
1205 * field is 4k. Bug #4400. JRA.
1208 status = check_spnego_blob_complete(smbpid, vuid, &blob1);
1209 if (!NT_STATUS_IS_OK(status)) {
1210 if (!NT_STATUS_EQUAL(status,
1211 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1212 /* Real error - kill the intermediate vuid */
1213 invalidate_vuid(vuid);
1215 data_blob_free(&blob1);
1216 reply_nterror(req, nt_status_squash(status));
1220 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1222 /* its a negTokenTarg packet */
1224 reply_spnego_negotiate(req, vuid, blob1,
1225 &vuser->auth_ntlmssp_state);
1226 data_blob_free(&blob1);
1230 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1232 /* its a auth packet */
1234 reply_spnego_auth(req, vuid, blob1,
1235 &vuser->auth_ntlmssp_state);
1236 data_blob_free(&blob1);
1240 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1243 if (!vuser->auth_ntlmssp_state) {
1244 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1245 if (!NT_STATUS_IS_OK(status)) {
1246 /* Kill the intermediate vuid */
1247 invalidate_vuid(vuid);
1248 data_blob_free(&blob1);
1249 reply_nterror(req, nt_status_squash(status));
1254 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1257 data_blob_free(&blob1);
1259 reply_spnego_ntlmssp(req, vuid,
1260 &vuser->auth_ntlmssp_state,
1261 &chal, status, False);
1262 data_blob_free(&chal);
1266 /* what sort of packet is this? */
1267 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1269 data_blob_free(&blob1);
1271 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1274 /****************************************************************************
1275 On new VC == 0, shutdown *all* old connections and users.
1276 It seems that only NT4.x does this. At W2K and above (XP etc.).
1277 a new session setup with VC==0 is ignored.
1278 ****************************************************************************/
1280 static int shutdown_other_smbds(struct db_record *rec,
1281 const struct connections_key *key,
1282 const struct connections_data *crec,
1285 const char *ip = (const char *)private_data;
1287 if (!process_exists(crec->pid)) {
1291 if (procid_is_me(&crec->pid)) {
1295 if (strcmp(ip, crec->addr) != 0) {
1299 messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1304 static void setup_new_vc_session(void)
1306 char addr[INET6_ADDRSTRLEN];
1308 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1309 "compatible we would close all old resources.\n"));
1312 invalidate_all_vuids();
1314 if (lp_reset_on_zero_vc()) {
1315 connections_forall(shutdown_other_smbds,
1316 CONST_DISCARD(void *,
1317 client_addr(get_client_fd(),addr,sizeof(addr))));
1321 /****************************************************************************
1322 Reply to a session setup command.
1323 ****************************************************************************/
1325 void reply_sesssetup_and_X(struct smb_request *req)
1331 DATA_BLOB plaintext_password;
1333 fstring sub_user; /* Sainitised username for substituion */
1336 fstring native_lanman;
1337 fstring primary_domain;
1338 static bool done_sesssetup = False;
1339 auth_usersupplied_info *user_info = NULL;
1340 auth_serversupplied_info *server_info = NULL;
1341 uint16 smb_flag2 = req->flags2;
1345 bool doencrypt = global_encrypted_passwords_negotiated;
1347 DATA_BLOB session_key;
1349 START_PROFILE(SMBsesssetupX);
1351 ZERO_STRUCT(lm_resp);
1352 ZERO_STRUCT(nt_resp);
1353 ZERO_STRUCT(plaintext_password);
1355 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1357 /* a SPNEGO session setup has 12 command words, whereas a normal
1358 NT1 session setup has 13. See the cifs spec. */
1359 if (req->wct == 12 &&
1360 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1362 if (!global_spnego_negotiated) {
1363 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1364 "at SPNEGO session setup when it was not "
1366 reply_nterror(req, nt_status_squash(
1367 NT_STATUS_LOGON_FAILURE));
1368 END_PROFILE(SMBsesssetupX);
1372 if (SVAL(req->inbuf,smb_vwv4) == 0) {
1373 setup_new_vc_session();
1376 reply_sesssetup_and_X_spnego(req);
1377 END_PROFILE(SMBsesssetupX);
1381 smb_bufsize = SVAL(req->inbuf,smb_vwv2);
1383 if (Protocol < PROTOCOL_NT1) {
1384 uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
1386 /* Never do NT status codes with protocols before NT1 as we
1387 * don't get client caps. */
1388 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1390 if ((passlen1 > MAX_PASS_LEN)
1391 || (passlen1 > smb_bufrem(req->inbuf,
1392 smb_buf(req->inbuf)))) {
1393 reply_nterror(req, nt_status_squash(
1394 NT_STATUS_INVALID_PARAMETER));
1395 END_PROFILE(SMBsesssetupX);
1400 lm_resp = data_blob(smb_buf(req->inbuf), passlen1);
1402 plaintext_password = data_blob(smb_buf(req->inbuf),
1404 /* Ensure null termination */
1405 plaintext_password.data[passlen1] = 0;
1408 srvstr_pull_buf(req->inbuf, req->flags2, user,
1409 smb_buf(req->inbuf)+passlen1, sizeof(user),
1414 uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
1415 uint16 passlen2 = SVAL(req->inbuf,smb_vwv8);
1416 enum remote_arch_types ra_type = get_remote_arch();
1417 char *p = smb_buf(req->inbuf);
1418 char *save_p = smb_buf(req->inbuf);
1422 if(global_client_caps == 0) {
1423 global_client_caps = IVAL(req->inbuf,smb_vwv11);
1425 if (!(global_client_caps & CAP_STATUS32)) {
1426 remove_from_common_flags2(
1427 FLAGS2_32_BIT_ERROR_CODES);
1430 /* client_caps is used as final determination if
1431 * client is NT or Win95. This is needed to return
1432 * the correct error codes in some circumstances.
1435 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1436 ra_type == RA_WIN95) {
1437 if(!(global_client_caps & (CAP_NT_SMBS|
1439 set_remote_arch( RA_WIN95);
1445 /* both Win95 and WinNT stuff up the password
1446 * lengths for non-encrypting systems. Uggh.
1448 if passlen1==24 its a win95 system, and its setting
1449 the password length incorrectly. Luckily it still
1450 works with the default code because Win95 will null
1451 terminate the password anyway
1453 if passlen1>0 and passlen2>0 then maybe its a NT box
1454 and its setting passlen2 to some random value which
1455 really stuffs things up. we need to fix that one. */
1457 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1463 /* check for nasty tricks */
1464 if (passlen1 > MAX_PASS_LEN
1465 || passlen1 > smb_bufrem(req->inbuf, p)) {
1466 reply_nterror(req, nt_status_squash(
1467 NT_STATUS_INVALID_PARAMETER));
1468 END_PROFILE(SMBsesssetupX);
1472 if (passlen2 > MAX_PASS_LEN
1473 || passlen2 > smb_bufrem(req->inbuf, p+passlen1)) {
1474 reply_nterror(req, nt_status_squash(
1475 NT_STATUS_INVALID_PARAMETER));
1476 END_PROFILE(SMBsesssetupX);
1480 /* Save the lanman2 password and the NT md4 password. */
1482 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1487 lm_resp = data_blob(p, passlen1);
1488 nt_resp = data_blob(p+passlen1, passlen2);
1491 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1493 if (unic && (passlen2 == 0) && passlen1) {
1494 /* Only a ascii plaintext password was sent. */
1495 (void)srvstr_pull_talloc(talloc_tos(),
1499 smb_buf(req->inbuf),
1501 STR_TERMINATE|STR_ASCII);
1503 (void)srvstr_pull_talloc(talloc_tos(),
1507 smb_buf(req->inbuf),
1508 unic ? passlen2 : passlen1,
1512 reply_nterror(req, nt_status_squash(
1513 NT_STATUS_INVALID_PARAMETER));
1514 END_PROFILE(SMBsesssetupX);
1517 plaintext_password = data_blob(pass, strlen(pass)+1);
1520 p += passlen1 + passlen2;
1521 p += srvstr_pull_buf(req->inbuf, req->flags2, user, p,
1522 sizeof(user), STR_TERMINATE);
1523 p += srvstr_pull_buf(req->inbuf, req->flags2, domain, p,
1524 sizeof(domain), STR_TERMINATE);
1525 p += srvstr_pull_buf(req->inbuf, req->flags2, native_os,
1526 p, sizeof(native_os), STR_TERMINATE);
1527 p += srvstr_pull_buf(req->inbuf, req->flags2,
1528 native_lanman, p, sizeof(native_lanman),
1531 /* not documented or decoded by Ethereal but there is one more
1532 * string in the extra bytes which is the same as the
1533 * PrimaryDomain when using extended security. Windows NT 4
1534 * and 2003 use this string to store the native lanman string.
1535 * Windows 9x does not include a string here at all so we have
1536 * to check if we have any extra bytes left */
1538 byte_count = SVAL(req->inbuf, smb_vwv13);
1539 if ( PTR_DIFF(p, save_p) < byte_count) {
1540 p += srvstr_pull_buf(req->inbuf, req->flags2,
1542 sizeof(primary_domain),
1545 fstrcpy( primary_domain, "null" );
1548 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1549 "PrimaryDomain=[%s]\n",
1550 domain, native_os, native_lanman, primary_domain));
1552 if ( ra_type == RA_WIN2K ) {
1553 if ( strlen(native_lanman) == 0 )
1554 ra_lanman_string( primary_domain );
1556 ra_lanman_string( native_lanman );
1561 if (SVAL(req->inbuf,smb_vwv4) == 0) {
1562 setup_new_vc_session();
1565 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1566 domain, user, get_remote_machine_name()));
1569 if (global_spnego_negotiated) {
1571 /* This has to be here, because this is a perfectly
1572 * valid behaviour for guest logons :-( */
1574 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1575 "at 'normal' session setup after "
1576 "negotiating spnego.\n"));
1577 reply_nterror(req, nt_status_squash(
1578 NT_STATUS_LOGON_FAILURE));
1579 END_PROFILE(SMBsesssetupX);
1582 fstrcpy(sub_user, user);
1584 fstrcpy(sub_user, lp_guestaccount());
1587 sub_set_smb_name(sub_user);
1589 reload_services(True);
1591 if (lp_security() == SEC_SHARE) {
1592 /* in share level we should ignore any passwords */
1594 data_blob_free(&lm_resp);
1595 data_blob_free(&nt_resp);
1596 data_blob_clear_free(&plaintext_password);
1598 map_username(sub_user);
1599 add_session_user(sub_user);
1600 add_session_workgroup(domain);
1601 /* Then force it to null for the benfit of the code below */
1607 nt_status = check_guest_password(&server_info);
1609 } else if (doencrypt) {
1610 if (!negprot_global_auth_context) {
1611 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1612 "session setup without negprot denied!\n"));
1613 reply_nterror(req, nt_status_squash(
1614 NT_STATUS_LOGON_FAILURE));
1615 END_PROFILE(SMBsesssetupX);
1618 nt_status = make_user_info_for_reply_enc(&user_info, user,
1621 if (NT_STATUS_IS_OK(nt_status)) {
1622 nt_status = negprot_global_auth_context->check_ntlm_password(
1623 negprot_global_auth_context,
1628 struct auth_context *plaintext_auth_context = NULL;
1631 nt_status = make_auth_context_subsystem(
1632 &plaintext_auth_context);
1634 if (NT_STATUS_IS_OK(nt_status)) {
1635 chal = plaintext_auth_context->get_ntlm_challenge(
1636 plaintext_auth_context);
1638 if (!make_user_info_for_reply(&user_info,
1640 plaintext_password)) {
1641 nt_status = NT_STATUS_NO_MEMORY;
1644 if (NT_STATUS_IS_OK(nt_status)) {
1645 nt_status = plaintext_auth_context->check_ntlm_password(
1646 plaintext_auth_context,
1650 (plaintext_auth_context->free)(
1651 &plaintext_auth_context);
1656 free_user_info(&user_info);
1658 if (!NT_STATUS_IS_OK(nt_status)) {
1659 nt_status = do_map_to_guest(nt_status, &server_info,
1663 if (!NT_STATUS_IS_OK(nt_status)) {
1664 data_blob_free(&nt_resp);
1665 data_blob_free(&lm_resp);
1666 data_blob_clear_free(&plaintext_password);
1667 reply_nterror(req, nt_status_squash(nt_status));
1668 END_PROFILE(SMBsesssetupX);
1672 /* Ensure we can't possible take a code path leading to a
1675 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1676 END_PROFILE(SMBsesssetupX);
1680 nt_status = create_local_token(server_info);
1681 if (!NT_STATUS_IS_OK(nt_status)) {
1682 DEBUG(10, ("create_local_token failed: %s\n",
1683 nt_errstr(nt_status)));
1684 data_blob_free(&nt_resp);
1685 data_blob_free(&lm_resp);
1686 data_blob_clear_free(&plaintext_password);
1687 reply_nterror(req, nt_status_squash(nt_status));
1688 END_PROFILE(SMBsesssetupX);
1692 if (server_info->user_session_key.data) {
1693 session_key = data_blob(server_info->user_session_key.data,
1694 server_info->user_session_key.length);
1696 session_key = data_blob_null;
1699 data_blob_clear_free(&plaintext_password);
1701 /* it's ok - setup a reply */
1702 reply_outbuf(req, 3, 0);
1703 if (Protocol >= PROTOCOL_NT1) {
1704 push_signature(&req->outbuf);
1705 /* perhaps grab OS version here?? */
1708 if (server_info->guest) {
1709 SSVAL(req->outbuf,smb_vwv2,1);
1712 /* register the name and uid as being validated, so further connections
1713 to a uid can get through without a password, on the same VC */
1715 if (lp_security() == SEC_SHARE) {
1716 sess_vuid = UID_FIELD_INVALID;
1717 data_blob_free(&session_key);
1718 TALLOC_FREE(server_info);
1720 /* Ignore the initial vuid. */
1721 sess_vuid = register_initial_vuid();
1722 if (sess_vuid == UID_FIELD_INVALID) {
1723 data_blob_free(&nt_resp);
1724 data_blob_free(&lm_resp);
1725 data_blob_free(&session_key);
1726 reply_nterror(req, nt_status_squash(
1727 NT_STATUS_LOGON_FAILURE));
1728 END_PROFILE(SMBsesssetupX);
1731 /* register_existing_vuid keeps the server info */
1732 sess_vuid = register_existing_vuid(sess_vuid,
1735 nt_resp.data ? nt_resp : lm_resp,
1737 if (sess_vuid == UID_FIELD_INVALID) {
1738 data_blob_free(&nt_resp);
1739 data_blob_free(&lm_resp);
1740 data_blob_free(&session_key);
1741 reply_nterror(req, nt_status_squash(
1742 NT_STATUS_LOGON_FAILURE));
1743 END_PROFILE(SMBsesssetupX);
1747 /* current_user_info is changed on new vuid */
1748 reload_services( True );
1750 sessionsetup_start_signing_engine(server_info, req->inbuf);
1753 data_blob_free(&nt_resp);
1754 data_blob_free(&lm_resp);
1756 SSVAL(req->outbuf,smb_uid,sess_vuid);
1757 SSVAL(req->inbuf,smb_uid,sess_vuid);
1759 if (!done_sesssetup)
1760 max_send = MIN(max_send,smb_bufsize);
1762 done_sesssetup = True;
1764 END_PROFILE(SMBsesssetupX);