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. */
413 struct winbindd_request wb_request;
414 struct winbindd_response wb_response;
415 NSS_STATUS wb_result;
417 ZERO_STRUCT(wb_request);
418 ZERO_STRUCT(wb_response);
420 DEBUG(10, ("Mapping [%s] to short name\n", domain));
422 fstrcpy(wb_request.domain_name, domain);
424 wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
425 &wb_request, &wb_response);
427 if (wb_result == NSS_STATUS_SUCCESS) {
429 fstrcpy(netbios_domain_name,
430 wb_response.data.domain_info.name);
431 domain = netbios_domain_name;
433 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
435 DEBUG(3, ("Could not find short name -- winbind "
440 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
442 /* lookup the passwd struct, create a new user if necessary */
444 username_was_mapped = map_username( user );
446 pw = smb_getpwnam( mem_ctx, user, real_username, True );
449 /* if a real user check pam account restrictions */
450 /* only really perfomed if "obey pam restriction" is true */
451 /* do this before an eventual mappign to guest occurs */
452 ret = smb_pam_accountcheck(pw->pw_name);
453 if ( !NT_STATUS_IS_OK(ret)) {
454 DEBUG(1,("PAM account restriction "
455 "prevents user login\n"));
456 data_blob_free(&ap_rep);
457 data_blob_free(&session_key);
458 TALLOC_FREE(mem_ctx);
459 reply_nterror(req, nt_status_squash(ret));
466 /* this was originally the behavior of Samba 2.2, if a user
467 did not have a local uid but has been authenticated, then
468 map them to a guest account */
470 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
471 map_domainuser_to_guest = True;
472 fstrcpy(user,lp_guestaccount());
473 pw = smb_getpwnam( mem_ctx, user, real_username, True );
476 /* extra sanity check that the guest account is valid */
479 DEBUG(1,("Username %s is invalid on this system\n",
482 data_blob_free(&ap_rep);
483 data_blob_free(&session_key);
484 TALLOC_FREE(mem_ctx);
485 reply_nterror(req, nt_status_squash(
486 NT_STATUS_LOGON_FAILURE));
491 /* setup the string used by %U */
493 sub_set_smb_name( real_username );
494 reload_services(True);
496 if ( map_domainuser_to_guest ) {
497 make_server_info_guest(&server_info);
498 } else if (logon_info) {
499 /* pass the unmapped username here since map_username()
500 will be called again from inside make_server_info_info3() */
502 ret = make_server_info_info3(mem_ctx, client, domain,
503 &server_info, &logon_info->info3);
504 if ( !NT_STATUS_IS_OK(ret) ) {
505 DEBUG(1,("make_server_info_info3 failed: %s!\n",
508 data_blob_free(&ap_rep);
509 data_blob_free(&session_key);
510 TALLOC_FREE(mem_ctx);
511 reply_nterror(req, nt_status_squash(ret));
516 ret = make_server_info_pw(&server_info, real_username, pw);
518 if ( !NT_STATUS_IS_OK(ret) ) {
519 DEBUG(1,("make_server_info_pw failed: %s!\n",
522 data_blob_free(&ap_rep);
523 data_blob_free(&session_key);
524 TALLOC_FREE(mem_ctx);
525 reply_nterror(req, nt_status_squash(ret));
529 /* make_server_info_pw does not set the domain. Without this
530 * we end up with the local netbios name in substitutions for
533 if (server_info->sam_account != NULL) {
534 pdb_set_domain(server_info->sam_account,
539 if (username_was_mapped) {
540 server_info->was_mapped = username_was_mapped;
543 /* we need to build the token for the user. make_server_info_guest()
546 if ( !server_info->ptok ) {
547 ret = create_local_token( server_info );
548 if ( !NT_STATUS_IS_OK(ret) ) {
550 data_blob_free(&ap_rep);
551 data_blob_free(&session_key);
552 TALLOC_FREE( mem_ctx );
553 TALLOC_FREE( server_info );
554 reply_nterror(req, nt_status_squash(ret));
559 /* register_existing_vuid keeps the server info */
560 /* register_existing_vuid takes ownership of session_key on success,
561 * no need to free after this on success. A better interface would copy
564 if (!is_partial_auth_vuid(sess_vuid)) {
565 sess_vuid = register_initial_vuid();
567 sess_vuid = register_existing_vuid(sess_vuid,
575 reply_outbuf(req, 4, 0);
576 SSVAL(req->outbuf,smb_uid,sess_vuid);
578 if (sess_vuid == UID_FIELD_INVALID ) {
579 ret = NT_STATUS_LOGON_FAILURE;
580 data_blob_free(&session_key);
582 /* current_user_info is changed on new vuid */
583 reload_services( True );
585 SSVAL(req->outbuf, smb_vwv3, 0);
587 if (server_info->guest) {
588 SSVAL(req->outbuf,smb_vwv2,1);
591 SSVAL(req->outbuf, smb_uid, sess_vuid);
593 sessionsetup_start_signing_engine(server_info, req->inbuf);
594 /* Successful logon. Keep this vuid. */
595 *p_invalidate_vuid = False;
598 /* wrap that up in a nice GSS-API wrapping */
599 if (NT_STATUS_IS_OK(ret)) {
600 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
603 ap_rep_wrapped = data_blob_null;
605 response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
607 reply_sesssetup_blob(req, response, ret);
609 data_blob_free(&ap_rep);
610 data_blob_free(&ap_rep_wrapped);
611 data_blob_free(&response);
612 TALLOC_FREE(mem_ctx);
617 /****************************************************************************
618 Send a session setup reply, wrapped in SPNEGO.
619 Get vuid and check first.
620 End the NTLMSSP exchange context if we are OK/complete fail
621 This should be split into two functions, one to handle each
622 leg of the NTLM auth steps.
623 ***************************************************************************/
625 static void reply_spnego_ntlmssp(struct smb_request *req,
627 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
628 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
632 struct auth_serversupplied_info *server_info = NULL;
634 if (NT_STATUS_IS_OK(nt_status)) {
635 server_info = (*auth_ntlmssp_state)->server_info;
637 nt_status = do_map_to_guest(nt_status,
639 (*auth_ntlmssp_state)->ntlmssp_state->user,
640 (*auth_ntlmssp_state)->ntlmssp_state->domain);
643 reply_outbuf(req, 4, 0);
645 SSVAL(req->outbuf, smb_uid, vuid);
647 if (NT_STATUS_IS_OK(nt_status)) {
648 DATA_BLOB nullblob = data_blob_null;
649 DATA_BLOB session_key =
651 (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
652 (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
654 if (!is_partial_auth_vuid(vuid)) {
655 data_blob_free(&session_key);
656 nt_status = NT_STATUS_LOGON_FAILURE;
659 /* register_existing_vuid keeps the server info */
660 if (register_existing_vuid(vuid,
662 session_key, nullblob,
663 (*auth_ntlmssp_state)->ntlmssp_state->user) !=
665 data_blob_free(&session_key);
666 nt_status = NT_STATUS_LOGON_FAILURE;
670 (*auth_ntlmssp_state)->server_info = NULL;
672 /* current_user_info is changed on new vuid */
673 reload_services( True );
675 SSVAL(req->outbuf, smb_vwv3, 0);
677 if (server_info->guest) {
678 SSVAL(req->outbuf,smb_vwv2,1);
681 sessionsetup_start_signing_engine(server_info,
682 (uint8 *)req->inbuf);
688 response = spnego_gen_auth_response(ntlmssp_blob,
689 nt_status, OID_NTLMSSP);
691 response = *ntlmssp_blob;
694 reply_sesssetup_blob(req, response, nt_status);
696 data_blob_free(&response);
699 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
700 and the other end, that we are not finished yet. */
702 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
703 /* NB. This is *NOT* an error case. JRA */
704 auth_ntlmssp_end(auth_ntlmssp_state);
705 if (!NT_STATUS_IS_OK(nt_status)) {
706 /* Kill the intermediate vuid */
707 invalidate_vuid(vuid);
712 /****************************************************************************
713 Is this a krb5 mechanism ?
714 ****************************************************************************/
716 NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out,
719 char *OIDs[ASN1_MAX_OIDS];
724 /* parse out the OIDs and the first sec blob */
725 if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
726 return NT_STATUS_LOGON_FAILURE;
729 /* only look at the first OID for determining the mechToken --
730 according to RFC2478, we should choose the one we want
731 and renegotiate, but i smell a client bug here..
733 Problem observed when connecting to a member (samba box)
734 of an AD domain as a user in a Samba domain. Samba member
735 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
736 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
737 NTLMSSP mechtoken. --jerry */
740 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
741 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
746 for (i=0;OIDs[i];i++) {
747 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
753 /****************************************************************************
754 Reply to a session setup spnego negotiate packet.
755 ****************************************************************************/
757 static void reply_spnego_negotiate(struct smb_request *req,
760 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
764 bool got_kerberos_mechanism = False;
767 status = parse_spnego_mechanisms(blob1, &secblob,
768 &got_kerberos_mechanism);
769 if (!NT_STATUS_IS_OK(status)) {
770 /* Kill the intermediate vuid */
771 invalidate_vuid(vuid);
772 reply_nterror(req, nt_status_squash(status));
776 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
777 (unsigned long)secblob.length));
780 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) ||
781 lp_use_kerberos_keytab()) ) {
782 bool destroy_vuid = True;
783 reply_spnego_kerberos(req, &secblob, vuid,
785 data_blob_free(&secblob);
787 /* Kill the intermediate vuid */
788 invalidate_vuid(vuid);
794 if (*auth_ntlmssp_state) {
795 auth_ntlmssp_end(auth_ntlmssp_state);
798 status = auth_ntlmssp_start(auth_ntlmssp_state);
799 if (!NT_STATUS_IS_OK(status)) {
800 /* Kill the intermediate vuid */
801 invalidate_vuid(vuid);
802 reply_nterror(req, nt_status_squash(status));
806 status = auth_ntlmssp_update(*auth_ntlmssp_state,
809 data_blob_free(&secblob);
811 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
812 &chal, status, True);
814 data_blob_free(&chal);
816 /* already replied */
820 /****************************************************************************
821 Reply to a session setup spnego auth packet.
822 ****************************************************************************/
824 static void reply_spnego_auth(struct smb_request *req,
827 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
829 DATA_BLOB auth = data_blob_null;
830 DATA_BLOB auth_reply = data_blob_null;
831 DATA_BLOB secblob = data_blob_null;
832 NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
834 if (!spnego_parse_auth(blob1, &auth)) {
836 file_save("auth.dat", blob1.data, blob1.length);
838 /* Kill the intermediate vuid */
839 invalidate_vuid(vuid);
841 reply_nterror(req, nt_status_squash(
842 NT_STATUS_INVALID_PARAMETER));
846 if (auth.data[0] == ASN1_APPLICATION(0)) {
847 /* Might be a second negTokenTarg packet */
849 bool got_krb5_mechanism = False;
850 status = parse_spnego_mechanisms(auth, &secblob,
851 &got_krb5_mechanism);
852 if (NT_STATUS_IS_OK(status)) {
853 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
854 (unsigned long)secblob.length));
856 if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) ||
857 lp_use_kerberos_keytab()) ) {
858 bool destroy_vuid = True;
859 reply_spnego_kerberos(req, &secblob,
860 vuid, &destroy_vuid);
861 data_blob_free(&secblob);
862 data_blob_free(&auth);
864 /* Kill the intermediate vuid */
865 invalidate_vuid(vuid);
873 /* If we get here it wasn't a negTokenTarg auth packet. */
874 data_blob_free(&secblob);
876 if (!*auth_ntlmssp_state) {
877 /* Kill the intermediate vuid */
878 invalidate_vuid(vuid);
880 /* auth before negotiatiate? */
881 reply_nterror(req, nt_status_squash(
882 NT_STATUS_INVALID_PARAMETER));
886 status = auth_ntlmssp_update(*auth_ntlmssp_state,
889 data_blob_free(&auth);
891 reply_spnego_ntlmssp(req, vuid,
893 &auth_reply, status, True);
895 data_blob_free(&auth_reply);
897 /* and tell smbd that we have already replied to this packet */
901 /****************************************************************************
902 List to store partial SPNEGO auth fragments.
903 ****************************************************************************/
905 static struct pending_auth_data *pd_list;
907 /****************************************************************************
908 Delete an entry on the list.
909 ****************************************************************************/
911 static void delete_partial_auth(struct pending_auth_data *pad)
916 DLIST_REMOVE(pd_list, pad);
917 data_blob_free(&pad->partial_data);
921 /****************************************************************************
922 Search for a partial SPNEGO auth fragment matching an smbpid.
923 ****************************************************************************/
925 static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
927 struct pending_auth_data *pad;
929 for (pad = pd_list; pad; pad = pad->next) {
930 if (pad->smbpid == smbpid) {
937 /****************************************************************************
938 Check the size of an SPNEGO blob. If we need more return
939 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
940 the blob to be more than 64k.
941 ****************************************************************************/
943 static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid,
946 struct pending_auth_data *pad = NULL;
948 size_t needed_len = 0;
950 pad = get_pending_auth_data(smbpid);
952 /* Ensure we have some data. */
953 if (pblob->length == 0) {
954 /* Caller can cope. */
955 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
956 delete_partial_auth(pad);
960 /* Were we waiting for more data ? */
963 size_t copy_len = MIN(65536, pblob->length);
965 /* Integer wrap paranoia.... */
967 if (pad->partial_data.length + copy_len <
968 pad->partial_data.length ||
969 pad->partial_data.length + copy_len < copy_len) {
971 DEBUG(2,("check_spnego_blob_complete: integer wrap "
972 "pad->partial_data.length = %u, "
974 (unsigned int)pad->partial_data.length,
975 (unsigned int)copy_len ));
977 delete_partial_auth(pad);
978 return NT_STATUS_INVALID_PARAMETER;
981 DEBUG(10,("check_spnego_blob_complete: "
982 "pad->partial_data.length = %u, "
983 "pad->needed_len = %u, "
985 "pblob->length = %u,\n",
986 (unsigned int)pad->partial_data.length,
987 (unsigned int)pad->needed_len,
988 (unsigned int)copy_len,
989 (unsigned int)pblob->length ));
991 tmp_blob = data_blob(NULL,
992 pad->partial_data.length + copy_len);
994 /* Concatenate the two (up to copy_len) bytes. */
995 memcpy(tmp_blob.data,
996 pad->partial_data.data,
997 pad->partial_data.length);
998 memcpy(tmp_blob.data + pad->partial_data.length,
1002 /* Replace the partial data. */
1003 data_blob_free(&pad->partial_data);
1004 pad->partial_data = tmp_blob;
1005 ZERO_STRUCT(tmp_blob);
1008 if (pblob->length >= pad->needed_len) {
1009 /* Yes, replace pblob. */
1010 data_blob_free(pblob);
1011 *pblob = pad->partial_data;
1012 ZERO_STRUCT(pad->partial_data);
1013 delete_partial_auth(pad);
1014 return NT_STATUS_OK;
1017 /* Still need more data. */
1018 pad->needed_len -= copy_len;
1019 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1022 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
1023 (pblob->data[0] != ASN1_CONTEXT(1))) {
1024 /* Not something we can determine the
1027 return NT_STATUS_OK;
1030 /* This is a new SPNEGO sessionsetup - see if
1031 * the data given in this blob is enough.
1034 asn1_load(&data, *pblob);
1035 asn1_start_tag(&data, pblob->data[0]);
1036 if (data.has_error || data.nesting == NULL) {
1038 /* Let caller catch. */
1039 return NT_STATUS_OK;
1042 /* Integer wrap paranoia.... */
1044 if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
1045 data.nesting->taglen + data.nesting->start < data.nesting->start) {
1047 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1048 "data.nesting->taglen = %u, "
1049 "data.nesting->start = %u\n",
1050 (unsigned int)data.nesting->taglen,
1051 (unsigned int)data.nesting->start ));
1054 return NT_STATUS_INVALID_PARAMETER;
1057 /* Total length of the needed asn1 is the tag length
1058 * plus the current offset. */
1060 needed_len = data.nesting->taglen + data.nesting->start;
1063 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1064 "pblob->length = %u\n",
1065 (unsigned int)needed_len,
1066 (unsigned int)pblob->length ));
1068 if (needed_len <= pblob->length) {
1069 /* Nothing to do - blob is complete. */
1070 return NT_STATUS_OK;
1073 /* Refuse the blob if it's bigger than 64k. */
1074 if (needed_len > 65536) {
1075 DEBUG(2,("check_spnego_blob_complete: needed_len "
1077 (unsigned int)needed_len ));
1078 return NT_STATUS_INVALID_PARAMETER;
1081 /* We must store this blob until complete. */
1082 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1083 return NT_STATUS_NO_MEMORY;
1085 pad->needed_len = needed_len - pblob->length;
1086 pad->partial_data = data_blob(pblob->data, pblob->length);
1087 if (pad->partial_data.data == NULL) {
1089 return NT_STATUS_NO_MEMORY;
1091 pad->smbpid = smbpid;
1093 DLIST_ADD(pd_list, pad);
1095 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1098 /****************************************************************************
1099 Reply to a session setup command.
1100 conn POINTER CAN BE NULL HERE !
1101 ****************************************************************************/
1103 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1108 fstring native_os, native_lanman, primary_domain;
1110 uint16 data_blob_len = SVAL(req->inbuf, smb_vwv7);
1111 enum remote_arch_types ra_type = get_remote_arch();
1112 int vuid = SVAL(req->inbuf,smb_uid);
1113 user_struct *vuser = NULL;
1114 NTSTATUS status = NT_STATUS_OK;
1115 uint16 smbpid = req->smbpid;
1116 uint16 smb_flag2 = req->flags2;
1118 DEBUG(3,("Doing spnego session setup\n"));
1120 if (global_client_caps == 0) {
1121 global_client_caps = IVAL(req->inbuf,smb_vwv10);
1123 if (!(global_client_caps & CAP_STATUS32)) {
1124 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1129 p = (uint8 *)smb_buf(req->inbuf);
1131 if (data_blob_len == 0) {
1132 /* an invalid request */
1133 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1137 bufrem = smb_bufrem(req->inbuf, p);
1138 /* pull the spnego blob */
1139 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1142 file_save("negotiate.dat", blob1.data, blob1.length);
1145 p2 = (char *)req->inbuf + smb_vwv13 + data_blob_len;
1146 p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_os, p2,
1147 sizeof(native_os), STR_TERMINATE);
1148 p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_lanman, p2,
1149 sizeof(native_lanman), STR_TERMINATE);
1150 p2 += srvstr_pull_buf(req->inbuf, smb_flag2, primary_domain, p2,
1151 sizeof(primary_domain), STR_TERMINATE);
1152 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1153 native_os, native_lanman, primary_domain));
1155 if ( ra_type == RA_WIN2K ) {
1156 /* Vista sets neither the OS or lanman strings */
1158 if ( !strlen(native_os) && !strlen(native_lanman) )
1159 set_remote_arch(RA_VISTA);
1161 /* Windows 2003 doesn't set the native lanman string,
1162 but does set primary domain which is a bug I think */
1164 if ( !strlen(native_lanman) ) {
1165 ra_lanman_string( primary_domain );
1167 ra_lanman_string( native_lanman );
1171 /* Did we get a valid vuid ? */
1172 if (!is_partial_auth_vuid(vuid)) {
1173 /* No, then try and see if this is an intermediate sessionsetup
1174 * for a large SPNEGO packet. */
1175 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
1177 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1178 "pending vuid %u\n",
1179 (unsigned int)pad->vuid ));
1184 /* Do we have a valid vuid now ? */
1185 if (!is_partial_auth_vuid(vuid)) {
1186 /* No, start a new authentication setup. */
1187 vuid = register_initial_vuid();
1188 if (vuid == UID_FIELD_INVALID) {
1189 data_blob_free(&blob1);
1190 reply_nterror(req, nt_status_squash(
1191 NT_STATUS_INVALID_PARAMETER));
1196 vuser = get_partial_auth_user_struct(vuid);
1197 /* This MUST be valid. */
1199 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1202 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1203 * sessionsetup requests as the Windows limit on the security blob
1204 * field is 4k. Bug #4400. JRA.
1207 status = check_spnego_blob_complete(smbpid, vuid, &blob1);
1208 if (!NT_STATUS_IS_OK(status)) {
1209 if (!NT_STATUS_EQUAL(status,
1210 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1211 /* Real error - kill the intermediate vuid */
1212 invalidate_vuid(vuid);
1214 data_blob_free(&blob1);
1215 reply_nterror(req, nt_status_squash(status));
1219 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1221 /* its a negTokenTarg packet */
1223 reply_spnego_negotiate(req, vuid, blob1,
1224 &vuser->auth_ntlmssp_state);
1225 data_blob_free(&blob1);
1229 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1231 /* its a auth packet */
1233 reply_spnego_auth(req, vuid, blob1,
1234 &vuser->auth_ntlmssp_state);
1235 data_blob_free(&blob1);
1239 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1242 if (!vuser->auth_ntlmssp_state) {
1243 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1244 if (!NT_STATUS_IS_OK(status)) {
1245 /* Kill the intermediate vuid */
1246 invalidate_vuid(vuid);
1247 data_blob_free(&blob1);
1248 reply_nterror(req, nt_status_squash(status));
1253 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1256 data_blob_free(&blob1);
1258 reply_spnego_ntlmssp(req, vuid,
1259 &vuser->auth_ntlmssp_state,
1260 &chal, status, False);
1261 data_blob_free(&chal);
1265 /* what sort of packet is this? */
1266 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1268 data_blob_free(&blob1);
1270 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1273 /****************************************************************************
1274 On new VC == 0, shutdown *all* old connections and users.
1275 It seems that only NT4.x does this. At W2K and above (XP etc.).
1276 a new session setup with VC==0 is ignored.
1277 ****************************************************************************/
1279 static int shutdown_other_smbds(struct db_record *rec,
1280 const struct connections_key *key,
1281 const struct connections_data *crec,
1284 const char *ip = (const char *)private_data;
1286 if (!process_exists(crec->pid)) {
1290 if (procid_is_me(&crec->pid)) {
1294 if (strcmp(ip, crec->addr) != 0) {
1298 messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1303 static void setup_new_vc_session(void)
1305 char addr[INET6_ADDRSTRLEN];
1307 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1308 "compatible we would close all old resources.\n"));
1311 invalidate_all_vuids();
1313 if (lp_reset_on_zero_vc()) {
1314 connections_forall(shutdown_other_smbds,
1315 CONST_DISCARD(void *,
1316 client_addr(get_client_fd(),addr,sizeof(addr))));
1320 /****************************************************************************
1321 Reply to a session setup command.
1322 ****************************************************************************/
1324 void reply_sesssetup_and_X(struct smb_request *req)
1330 DATA_BLOB plaintext_password;
1332 fstring sub_user; /* Sainitised username for substituion */
1335 fstring native_lanman;
1336 fstring primary_domain;
1337 static bool done_sesssetup = False;
1338 auth_usersupplied_info *user_info = NULL;
1339 auth_serversupplied_info *server_info = NULL;
1340 uint16 smb_flag2 = req->flags2;
1344 bool doencrypt = global_encrypted_passwords_negotiated;
1346 DATA_BLOB session_key;
1348 START_PROFILE(SMBsesssetupX);
1350 ZERO_STRUCT(lm_resp);
1351 ZERO_STRUCT(nt_resp);
1352 ZERO_STRUCT(plaintext_password);
1354 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1356 /* a SPNEGO session setup has 12 command words, whereas a normal
1357 NT1 session setup has 13. See the cifs spec. */
1358 if (req->wct == 12 &&
1359 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1361 if (!global_spnego_negotiated) {
1362 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1363 "at SPNEGO session setup when it was not "
1365 reply_nterror(req, nt_status_squash(
1366 NT_STATUS_LOGON_FAILURE));
1367 END_PROFILE(SMBsesssetupX);
1371 if (SVAL(req->inbuf,smb_vwv4) == 0) {
1372 setup_new_vc_session();
1375 reply_sesssetup_and_X_spnego(req);
1376 END_PROFILE(SMBsesssetupX);
1380 smb_bufsize = SVAL(req->inbuf,smb_vwv2);
1382 if (Protocol < PROTOCOL_NT1) {
1383 uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
1385 /* Never do NT status codes with protocols before NT1 as we
1386 * don't get client caps. */
1387 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1389 if ((passlen1 > MAX_PASS_LEN)
1390 || (passlen1 > smb_bufrem(req->inbuf,
1391 smb_buf(req->inbuf)))) {
1392 reply_nterror(req, nt_status_squash(
1393 NT_STATUS_INVALID_PARAMETER));
1394 END_PROFILE(SMBsesssetupX);
1399 lm_resp = data_blob(smb_buf(req->inbuf), passlen1);
1401 plaintext_password = data_blob(smb_buf(req->inbuf),
1403 /* Ensure null termination */
1404 plaintext_password.data[passlen1] = 0;
1407 srvstr_pull_buf(req->inbuf, req->flags2, user,
1408 smb_buf(req->inbuf)+passlen1, sizeof(user),
1413 uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
1414 uint16 passlen2 = SVAL(req->inbuf,smb_vwv8);
1415 enum remote_arch_types ra_type = get_remote_arch();
1416 char *p = smb_buf(req->inbuf);
1417 char *save_p = smb_buf(req->inbuf);
1421 if(global_client_caps == 0) {
1422 global_client_caps = IVAL(req->inbuf,smb_vwv11);
1424 if (!(global_client_caps & CAP_STATUS32)) {
1425 remove_from_common_flags2(
1426 FLAGS2_32_BIT_ERROR_CODES);
1429 /* client_caps is used as final determination if
1430 * client is NT or Win95. This is needed to return
1431 * the correct error codes in some circumstances.
1434 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1435 ra_type == RA_WIN95) {
1436 if(!(global_client_caps & (CAP_NT_SMBS|
1438 set_remote_arch( RA_WIN95);
1444 /* both Win95 and WinNT stuff up the password
1445 * lengths for non-encrypting systems. Uggh.
1447 if passlen1==24 its a win95 system, and its setting
1448 the password length incorrectly. Luckily it still
1449 works with the default code because Win95 will null
1450 terminate the password anyway
1452 if passlen1>0 and passlen2>0 then maybe its a NT box
1453 and its setting passlen2 to some random value which
1454 really stuffs things up. we need to fix that one. */
1456 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1462 /* check for nasty tricks */
1463 if (passlen1 > MAX_PASS_LEN
1464 || passlen1 > smb_bufrem(req->inbuf, p)) {
1465 reply_nterror(req, nt_status_squash(
1466 NT_STATUS_INVALID_PARAMETER));
1467 END_PROFILE(SMBsesssetupX);
1471 if (passlen2 > MAX_PASS_LEN
1472 || passlen2 > smb_bufrem(req->inbuf, p+passlen1)) {
1473 reply_nterror(req, nt_status_squash(
1474 NT_STATUS_INVALID_PARAMETER));
1475 END_PROFILE(SMBsesssetupX);
1479 /* Save the lanman2 password and the NT md4 password. */
1481 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1486 lm_resp = data_blob(p, passlen1);
1487 nt_resp = data_blob(p+passlen1, passlen2);
1490 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1492 if (unic && (passlen2 == 0) && passlen1) {
1493 /* Only a ascii plaintext password was sent. */
1494 (void)srvstr_pull_talloc(talloc_tos(),
1498 smb_buf(req->inbuf),
1500 STR_TERMINATE|STR_ASCII);
1502 (void)srvstr_pull_talloc(talloc_tos(),
1506 smb_buf(req->inbuf),
1507 unic ? passlen2 : passlen1,
1511 reply_nterror(req, nt_status_squash(
1512 NT_STATUS_INVALID_PARAMETER));
1513 END_PROFILE(SMBsesssetupX);
1516 plaintext_password = data_blob(pass, strlen(pass)+1);
1519 p += passlen1 + passlen2;
1520 p += srvstr_pull_buf(req->inbuf, req->flags2, user, p,
1521 sizeof(user), STR_TERMINATE);
1522 p += srvstr_pull_buf(req->inbuf, req->flags2, domain, p,
1523 sizeof(domain), STR_TERMINATE);
1524 p += srvstr_pull_buf(req->inbuf, req->flags2, native_os,
1525 p, sizeof(native_os), STR_TERMINATE);
1526 p += srvstr_pull_buf(req->inbuf, req->flags2,
1527 native_lanman, p, sizeof(native_lanman),
1530 /* not documented or decoded by Ethereal but there is one more
1531 * string in the extra bytes which is the same as the
1532 * PrimaryDomain when using extended security. Windows NT 4
1533 * and 2003 use this string to store the native lanman string.
1534 * Windows 9x does not include a string here at all so we have
1535 * to check if we have any extra bytes left */
1537 byte_count = SVAL(req->inbuf, smb_vwv13);
1538 if ( PTR_DIFF(p, save_p) < byte_count) {
1539 p += srvstr_pull_buf(req->inbuf, req->flags2,
1541 sizeof(primary_domain),
1544 fstrcpy( primary_domain, "null" );
1547 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1548 "PrimaryDomain=[%s]\n",
1549 domain, native_os, native_lanman, primary_domain));
1551 if ( ra_type == RA_WIN2K ) {
1552 if ( strlen(native_lanman) == 0 )
1553 ra_lanman_string( primary_domain );
1555 ra_lanman_string( native_lanman );
1560 if (SVAL(req->inbuf,smb_vwv4) == 0) {
1561 setup_new_vc_session();
1564 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1565 domain, user, get_remote_machine_name()));
1568 if (global_spnego_negotiated) {
1570 /* This has to be here, because this is a perfectly
1571 * valid behaviour for guest logons :-( */
1573 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1574 "at 'normal' session setup after "
1575 "negotiating spnego.\n"));
1576 reply_nterror(req, nt_status_squash(
1577 NT_STATUS_LOGON_FAILURE));
1578 END_PROFILE(SMBsesssetupX);
1581 fstrcpy(sub_user, user);
1583 fstrcpy(sub_user, lp_guestaccount());
1586 sub_set_smb_name(sub_user);
1588 reload_services(True);
1590 if (lp_security() == SEC_SHARE) {
1591 /* in share level we should ignore any passwords */
1593 data_blob_free(&lm_resp);
1594 data_blob_free(&nt_resp);
1595 data_blob_clear_free(&plaintext_password);
1597 map_username(sub_user);
1598 add_session_user(sub_user);
1599 add_session_workgroup(domain);
1600 /* Then force it to null for the benfit of the code below */
1606 nt_status = check_guest_password(&server_info);
1608 } else if (doencrypt) {
1609 if (!negprot_global_auth_context) {
1610 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1611 "session setup without negprot denied!\n"));
1612 reply_nterror(req, nt_status_squash(
1613 NT_STATUS_LOGON_FAILURE));
1614 END_PROFILE(SMBsesssetupX);
1617 nt_status = make_user_info_for_reply_enc(&user_info, user,
1620 if (NT_STATUS_IS_OK(nt_status)) {
1621 nt_status = negprot_global_auth_context->check_ntlm_password(
1622 negprot_global_auth_context,
1627 struct auth_context *plaintext_auth_context = NULL;
1630 nt_status = make_auth_context_subsystem(
1631 &plaintext_auth_context);
1633 if (NT_STATUS_IS_OK(nt_status)) {
1634 chal = plaintext_auth_context->get_ntlm_challenge(
1635 plaintext_auth_context);
1637 if (!make_user_info_for_reply(&user_info,
1639 plaintext_password)) {
1640 nt_status = NT_STATUS_NO_MEMORY;
1643 if (NT_STATUS_IS_OK(nt_status)) {
1644 nt_status = plaintext_auth_context->check_ntlm_password(
1645 plaintext_auth_context,
1649 (plaintext_auth_context->free)(
1650 &plaintext_auth_context);
1655 free_user_info(&user_info);
1657 if (!NT_STATUS_IS_OK(nt_status)) {
1658 nt_status = do_map_to_guest(nt_status, &server_info,
1662 if (!NT_STATUS_IS_OK(nt_status)) {
1663 data_blob_free(&nt_resp);
1664 data_blob_free(&lm_resp);
1665 data_blob_clear_free(&plaintext_password);
1666 reply_nterror(req, nt_status_squash(nt_status));
1667 END_PROFILE(SMBsesssetupX);
1671 /* Ensure we can't possible take a code path leading to a
1674 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1675 END_PROFILE(SMBsesssetupX);
1679 nt_status = create_local_token(server_info);
1680 if (!NT_STATUS_IS_OK(nt_status)) {
1681 DEBUG(10, ("create_local_token failed: %s\n",
1682 nt_errstr(nt_status)));
1683 data_blob_free(&nt_resp);
1684 data_blob_free(&lm_resp);
1685 data_blob_clear_free(&plaintext_password);
1686 reply_nterror(req, nt_status_squash(nt_status));
1687 END_PROFILE(SMBsesssetupX);
1691 if (server_info->user_session_key.data) {
1692 session_key = data_blob(server_info->user_session_key.data,
1693 server_info->user_session_key.length);
1695 session_key = data_blob_null;
1698 data_blob_clear_free(&plaintext_password);
1700 /* it's ok - setup a reply */
1701 reply_outbuf(req, 3, 0);
1702 if (Protocol >= PROTOCOL_NT1) {
1703 push_signature(&req->outbuf);
1704 /* perhaps grab OS version here?? */
1707 if (server_info->guest) {
1708 SSVAL(req->outbuf,smb_vwv2,1);
1711 /* register the name and uid as being validated, so further connections
1712 to a uid can get through without a password, on the same VC */
1714 if (lp_security() == SEC_SHARE) {
1715 sess_vuid = UID_FIELD_INVALID;
1716 data_blob_free(&session_key);
1717 TALLOC_FREE(server_info);
1719 /* Ignore the initial vuid. */
1720 sess_vuid = register_initial_vuid();
1721 if (sess_vuid == UID_FIELD_INVALID) {
1722 data_blob_free(&nt_resp);
1723 data_blob_free(&lm_resp);
1724 data_blob_free(&session_key);
1725 reply_nterror(req, nt_status_squash(
1726 NT_STATUS_LOGON_FAILURE));
1727 END_PROFILE(SMBsesssetupX);
1730 /* register_existing_vuid keeps the server info */
1731 sess_vuid = register_existing_vuid(sess_vuid,
1734 nt_resp.data ? nt_resp : lm_resp,
1736 if (sess_vuid == UID_FIELD_INVALID) {
1737 data_blob_free(&nt_resp);
1738 data_blob_free(&lm_resp);
1739 data_blob_free(&session_key);
1740 reply_nterror(req, nt_status_squash(
1741 NT_STATUS_LOGON_FAILURE));
1742 END_PROFILE(SMBsesssetupX);
1746 /* current_user_info is changed on new vuid */
1747 reload_services( True );
1749 sessionsetup_start_signing_engine(server_info, req->inbuf);
1752 data_blob_free(&nt_resp);
1753 data_blob_free(&lm_resp);
1755 SSVAL(req->outbuf,smb_uid,sess_vuid);
1756 SSVAL(req->inbuf,smb_uid,sess_vuid);
1758 if (!done_sesssetup)
1759 max_send = MIN(max_send,smb_bufsize);
1761 done_sesssetup = True;
1763 END_PROFILE(SMBsesssetupX);