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
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 extern struct auth_context *negprot_global_auth_context;
27 extern BOOL global_encrypted_passwords_negotiated;
28 extern BOOL global_spnego_negotiated;
29 extern enum protocol_types Protocol;
32 uint32 global_client_caps = 0;
35 on a logon error possibly map the error to success if "map to guest"
38 static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **server_info,
39 const char *user, const char *domain)
41 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
42 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
43 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
44 DEBUG(3,("No such user %s [%s] - using guest account\n",
46 status = make_server_info_guest(server_info);
50 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
51 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
52 DEBUG(3,("Registered username %s for guest access\n",user));
53 status = make_server_info_guest(server_info);
60 /****************************************************************************
61 Add the standard 'Samba' signature to the end of the session setup.
62 ****************************************************************************/
64 static int add_signature(char *outbuf, char *p)
69 fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
71 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
72 p += srvstr_push(outbuf, p, lanman, -1, STR_TERMINATE);
73 p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
75 return PTR_DIFF(p, start);
78 /****************************************************************************
79 Start the signing engine if needed. Don't fail signing here.
80 ****************************************************************************/
82 static void sessionsetup_start_signing_engine(const auth_serversupplied_info *server_info, char *inbuf)
84 if (!server_info->guest && !srv_signing_started()) {
85 /* We need to start the signing engine
86 * here but a W2K client sends the old
87 * "BSRSPYL " signature instead of the
88 * correct one. Subsequent packets will
91 srv_check_sign_mac(inbuf, False);
95 /****************************************************************************
96 Send a security blob via a session setup reply.
97 ****************************************************************************/
99 static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
100 DATA_BLOB blob, NTSTATUS nt_status)
104 if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
105 ERROR_NT(nt_status_squash(nt_status));
107 set_message(outbuf,4,0,True);
109 nt_status = nt_status_squash(nt_status);
110 SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
111 SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
112 SSVAL(outbuf, smb_vwv3, blob.length);
115 /* should we cap this? */
116 memcpy(p, blob.data, blob.length);
119 p += add_signature( outbuf, p );
121 set_message_end(outbuf,p);
125 return send_smb(smbd_server_fd(),outbuf);
128 /****************************************************************************
129 Do a 'guest' logon, getting back the
130 ****************************************************************************/
132 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
134 struct auth_context *auth_context;
135 auth_usersupplied_info *user_info = NULL;
138 unsigned char chal[8];
142 DEBUG(3,("Got anonymous request\n"));
144 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) {
148 if (!make_user_info_guest(&user_info)) {
149 (auth_context->free)(&auth_context);
150 return NT_STATUS_NO_MEMORY;
153 nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info);
154 (auth_context->free)(&auth_context);
155 free_user_info(&user_info);
163 /* Experiment that failed. See "only happens with a KDC" comment below. */
164 /****************************************************************************
165 Cerate a clock skew error blob for a Windows client.
166 ****************************************************************************/
168 static BOOL make_krb5_skew_error(DATA_BLOB *pblob_out)
170 krb5_context context = NULL;
171 krb5_error_code kerr = 0;
173 krb5_principal host_princ = NULL;
174 char *host_princ_s = NULL;
177 *pblob_out = data_blob(NULL,0);
179 kerr = krb5_init_context(&context);
183 /* Create server principal. */
184 asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
188 strlower_m(host_princ_s);
190 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
192 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed for name %s: Error %s\n",
193 host_princ_s, error_message(kerr) ));
197 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW, host_princ, &reply);
199 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error failed: Error %s\n",
200 error_message(kerr) ));
204 *pblob_out = data_blob(reply.data, reply.length);
205 kerberos_free_data_contents(context,&reply);
211 SAFE_FREE(host_princ_s);
214 krb5_free_principal(context, host_princ);
216 krb5_free_context(context);
221 /****************************************************************************
222 Reply to a session setup spnego negotiate packet for kerberos.
223 ****************************************************************************/
225 static int reply_spnego_kerberos(connection_struct *conn,
226 char *inbuf, char *outbuf,
227 int length, int bufsize,
229 BOOL *p_invalidate_vuid)
233 char *client, *p, *domain;
234 fstring netbios_domain_name;
240 DATA_BLOB ap_rep, ap_rep_wrapped, response;
241 auth_serversupplied_info *server_info = NULL;
242 DATA_BLOB session_key = data_blob(NULL, 0);
244 DATA_BLOB nullblob = data_blob(NULL, 0);
245 fstring real_username;
246 BOOL map_domainuser_to_guest = False;
247 BOOL username_was_mapped;
248 PAC_LOGON_INFO *logon_info = NULL;
251 ZERO_STRUCT(pac_data);
253 ZERO_STRUCT(ap_rep_wrapped);
254 ZERO_STRUCT(response);
256 /* Normally we will always invalidate the intermediate vuid. */
257 *p_invalidate_vuid = True;
259 mem_ctx = talloc_init("reply_spnego_kerberos");
260 if (mem_ctx == NULL) {
261 return ERROR_NT(nt_status_squash(NT_STATUS_NO_MEMORY));
264 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
265 talloc_destroy(mem_ctx);
266 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
269 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket, &client, &pac_data, &ap_rep, &session_key);
271 data_blob_free(&ticket);
273 if (!NT_STATUS_IS_OK(ret)) {
275 /* Experiment that failed. See "only happens with a KDC" comment below. */
277 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
280 * Windows in this case returns NT_STATUS_MORE_PROCESSING_REQUIRED
281 * with a negTokenTarg blob containing an krb5_error struct ASN1 encoded
282 * containing KRB5KRB_AP_ERR_SKEW. The client then fixes its
283 * clock and continues rather than giving an error. JRA.
284 * -- Looks like this only happens with a KDC. JRA.
287 BOOL ok = make_krb5_skew_error(&ap_rep);
289 talloc_destroy(mem_ctx);
290 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
292 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_ERROR);
293 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
294 reply_sesssetup_blob(conn, outbuf, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
297 * In this one case we don't invalidate the intermediate vuid.
298 * as we're expecting the client to re-use it for the next
299 * sessionsetupX packet. JRA.
302 *p_invalidate_vuid = False;
304 data_blob_free(&ap_rep);
305 data_blob_free(&ap_rep_wrapped);
306 data_blob_free(&response);
307 talloc_destroy(mem_ctx);
308 return -1; /* already replied */
311 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
312 ret = NT_STATUS_LOGON_FAILURE;
315 DEBUG(1,("Failed to verify incoming ticket with error %s!\n", nt_errstr(ret)));
316 talloc_destroy(mem_ctx);
317 return ERROR_NT(nt_status_squash(ret));
320 DEBUG(3,("Ticket name is [%s]\n", client));
322 p = strchr_m(client, '@');
324 DEBUG(3,("Doesn't look like a valid principal\n"));
325 data_blob_free(&ap_rep);
326 data_blob_free(&session_key);
328 talloc_destroy(mem_ctx);
329 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
334 /* save the PAC data if we have it */
337 logon_info = get_logon_info_from_pac(pac_data);
339 netsamlogon_cache_store( client, &logon_info->info3 );
343 if (!strequal(p+1, lp_realm())) {
344 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
345 if (!lp_allow_trusted_domains()) {
346 data_blob_free(&ap_rep);
347 data_blob_free(&session_key);
349 talloc_destroy(mem_ctx);
350 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
354 /* this gives a fully qualified user name (ie. with full realm).
355 that leads to very long usernames, but what else can we do? */
359 if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) {
361 unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, -1);
362 domain = netbios_domain_name;
363 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
367 /* If we have winbind running, we can (and must) shorten the
368 username by using the short netbios name. Otherwise we will
369 have inconsistent user names. With Kerberos, we get the
370 fully qualified realm, with ntlmssp we get the short
371 name. And even w2k3 does use ntlmssp if you for example
372 connect to an ip address. */
374 struct winbindd_request wb_request;
375 struct winbindd_response wb_response;
376 NSS_STATUS wb_result;
378 ZERO_STRUCT(wb_request);
379 ZERO_STRUCT(wb_response);
381 DEBUG(10, ("Mapping [%s] to short name\n", domain));
383 fstrcpy(wb_request.domain_name, domain);
385 wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
386 &wb_request, &wb_response);
388 if (wb_result == NSS_STATUS_SUCCESS) {
390 fstrcpy(netbios_domain_name,
391 wb_response.data.domain_info.name);
392 domain = netbios_domain_name;
394 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
396 DEBUG(3, ("Could not find short name -- winbind "
401 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
403 /* lookup the passwd struct, create a new user if necessary */
405 username_was_mapped = map_username( user );
407 pw = smb_getpwnam( mem_ctx, user, real_username, True );
410 /* if a real user check pam account restrictions */
411 /* only really perfomed if "obey pam restriction" is true */
412 /* do this before an eventual mappign to guest occurs */
413 ret = smb_pam_accountcheck(pw->pw_name);
414 if ( !NT_STATUS_IS_OK(ret)) {
415 DEBUG(1, ("PAM account restriction prevents user login\n"));
416 data_blob_free(&ap_rep);
417 data_blob_free(&session_key);
418 TALLOC_FREE(mem_ctx);
419 return ERROR_NT(nt_status_squash(ret));
425 /* this was originally the behavior of Samba 2.2, if a user
426 did not have a local uid but has been authenticated, then
427 map them to a guest account */
429 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
430 map_domainuser_to_guest = True;
431 fstrcpy(user,lp_guestaccount());
432 pw = smb_getpwnam( mem_ctx, user, real_username, True );
435 /* extra sanity check that the guest account is valid */
438 DEBUG(1,("Username %s is invalid on this system\n", user));
440 data_blob_free(&ap_rep);
441 data_blob_free(&session_key);
442 TALLOC_FREE(mem_ctx);
443 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
447 /* setup the string used by %U */
449 sub_set_smb_name( real_username );
450 reload_services(True);
452 if ( map_domainuser_to_guest ) {
453 make_server_info_guest(&server_info);
454 } else if (logon_info) {
455 /* pass the unmapped username here since map_username()
456 will be called again from inside make_server_info_info3() */
458 ret = make_server_info_info3(mem_ctx, client, domain,
459 &server_info, &logon_info->info3);
460 if ( !NT_STATUS_IS_OK(ret) ) {
461 DEBUG(1,("make_server_info_info3 failed: %s!\n",
464 data_blob_free(&ap_rep);
465 data_blob_free(&session_key);
466 TALLOC_FREE(mem_ctx);
467 return ERROR_NT(nt_status_squash(ret));
471 ret = make_server_info_pw(&server_info, real_username, pw);
473 if ( !NT_STATUS_IS_OK(ret) ) {
474 DEBUG(1,("make_server_info_pw failed: %s!\n",
477 data_blob_free(&ap_rep);
478 data_blob_free(&session_key);
479 TALLOC_FREE(mem_ctx);
480 return ERROR_NT(nt_status_squash(ret));
483 /* make_server_info_pw does not set the domain. Without this
484 * we end up with the local netbios name in substitutions for
487 if (server_info->sam_account != NULL) {
488 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
492 server_info->was_mapped |= username_was_mapped;
494 /* we need to build the token for the user. make_server_info_guest()
497 if ( !server_info->ptok ) {
498 ret = create_local_token( server_info );
499 if ( !NT_STATUS_IS_OK(ret) ) {
501 data_blob_free(&ap_rep);
502 data_blob_free(&session_key);
503 TALLOC_FREE( mem_ctx );
504 TALLOC_FREE( server_info );
505 return ERROR_NT(nt_status_squash(ret));
509 /* register_vuid keeps the server info */
510 /* register_vuid takes ownership of session_key, no need to free after this.
511 A better interface would copy it.... */
512 sess_vuid = register_vuid(server_info, session_key, nullblob, client);
516 if (sess_vuid == UID_FIELD_INVALID ) {
517 ret = NT_STATUS_LOGON_FAILURE;
519 /* current_user_info is changed on new vuid */
520 reload_services( True );
522 set_message(outbuf,4,0,True);
523 SSVAL(outbuf, smb_vwv3, 0);
525 if (server_info->guest) {
526 SSVAL(outbuf,smb_vwv2,1);
529 SSVAL(outbuf, smb_uid, sess_vuid);
531 sessionsetup_start_signing_engine(server_info, inbuf);
534 /* wrap that up in a nice GSS-API wrapping */
535 if (NT_STATUS_IS_OK(ret)) {
536 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
538 ap_rep_wrapped = data_blob(NULL, 0);
540 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
541 reply_sesssetup_blob(conn, outbuf, response, ret);
543 data_blob_free(&ap_rep);
544 data_blob_free(&ap_rep_wrapped);
545 data_blob_free(&response);
546 TALLOC_FREE(mem_ctx);
548 return -1; /* already replied */
552 /****************************************************************************
553 Send a session setup reply, wrapped in SPNEGO.
554 Get vuid and check first.
555 End the NTLMSSP exchange context if we are OK/complete fail
556 This should be split into two functions, one to handle each
557 leg of the NTLM auth steps.
558 ***************************************************************************/
560 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
562 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
563 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
568 struct auth_serversupplied_info *server_info = NULL;
570 if (NT_STATUS_IS_OK(nt_status)) {
571 server_info = (*auth_ntlmssp_state)->server_info;
573 nt_status = do_map_to_guest(nt_status,
575 (*auth_ntlmssp_state)->ntlmssp_state->user,
576 (*auth_ntlmssp_state)->ntlmssp_state->domain);
579 if (NT_STATUS_IS_OK(nt_status)) {
581 DATA_BLOB nullblob = data_blob(NULL, 0);
582 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
584 /* register_vuid keeps the server info */
585 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
586 (*auth_ntlmssp_state)->server_info = NULL;
588 if (sess_vuid == UID_FIELD_INVALID ) {
589 nt_status = NT_STATUS_LOGON_FAILURE;
592 /* current_user_info is changed on new vuid */
593 reload_services( True );
595 set_message(outbuf,4,0,True);
596 SSVAL(outbuf, smb_vwv3, 0);
598 if (server_info->guest) {
599 SSVAL(outbuf,smb_vwv2,1);
602 SSVAL(outbuf,smb_uid,sess_vuid);
604 sessionsetup_start_signing_engine(server_info, inbuf);
609 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
611 response = *ntlmssp_blob;
614 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
616 data_blob_free(&response);
619 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
620 and the other end, that we are not finished yet. */
622 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
623 /* NB. This is *NOT* an error case. JRA */
624 auth_ntlmssp_end(auth_ntlmssp_state);
625 /* Kill the intermediate vuid */
626 invalidate_vuid(vuid);
632 /****************************************************************************
633 Is this a krb5 mechanism ?
634 ****************************************************************************/
636 static NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, BOOL *p_is_krb5)
638 char *OIDs[ASN1_MAX_OIDS];
643 /* parse out the OIDs and the first sec blob */
644 if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
645 return NT_STATUS_LOGON_FAILURE;
648 /* only look at the first OID for determining the mechToken --
649 accoirding to RFC2478, we should choose the one we want
650 and renegotiate, but i smell a client bug here..
652 Problem observed when connecting to a member (samba box)
653 of an AD domain as a user in a Samba domain. Samba member
654 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
655 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
656 NTLMSSP mechtoken. --jerry */
659 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
660 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
665 for (i=0;OIDs[i];i++) {
666 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
672 /****************************************************************************
673 Reply to a session setup spnego negotiate packet.
674 ****************************************************************************/
676 static int reply_spnego_negotiate(connection_struct *conn,
680 int length, int bufsize,
682 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
686 BOOL got_kerberos_mechanism = False;
689 status = parse_spnego_mechanisms(blob1, &secblob, &got_kerberos_mechanism);
690 if (!NT_STATUS_IS_OK(status)) {
691 /* Kill the intermediate vuid */
692 invalidate_vuid(vuid);
693 return ERROR_NT(nt_status_squash(status));
696 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n", (unsigned long)secblob.length));
699 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
700 BOOL destroy_vuid = True;
701 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
702 length, bufsize, &secblob, &destroy_vuid);
703 data_blob_free(&secblob);
705 /* Kill the intermediate vuid */
706 invalidate_vuid(vuid);
712 if (*auth_ntlmssp_state) {
713 auth_ntlmssp_end(auth_ntlmssp_state);
716 status = auth_ntlmssp_start(auth_ntlmssp_state);
717 if (!NT_STATUS_IS_OK(status)) {
718 /* Kill the intermediate vuid */
719 invalidate_vuid(vuid);
720 return ERROR_NT(nt_status_squash(status));
723 status = auth_ntlmssp_update(*auth_ntlmssp_state,
726 data_blob_free(&secblob);
728 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
729 &chal, status, True);
731 data_blob_free(&chal);
733 /* already replied */
737 /****************************************************************************
738 Reply to a session setup spnego auth packet.
739 ****************************************************************************/
741 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
743 int length, int bufsize,
745 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
747 DATA_BLOB auth = data_blob(NULL,0);
748 DATA_BLOB auth_reply = data_blob(NULL,0);
749 DATA_BLOB secblob = data_blob(NULL,0);
750 NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
752 if (!spnego_parse_auth(blob1, &auth)) {
754 file_save("auth.dat", blob1.data, blob1.length);
756 /* Kill the intermediate vuid */
757 invalidate_vuid(vuid);
759 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
762 if (auth.data[0] == ASN1_APPLICATION(0)) {
763 /* Might be a second negTokenTarg packet */
765 BOOL got_krb5_mechanism = False;
766 status = parse_spnego_mechanisms(auth, &secblob, &got_krb5_mechanism);
767 if (NT_STATUS_IS_OK(status)) {
768 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n", (unsigned long)secblob.length));
770 if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
771 BOOL destroy_vuid = True;
772 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
773 length, bufsize, &secblob, &destroy_vuid);
774 data_blob_free(&secblob);
775 data_blob_free(&auth);
777 /* Kill the intermediate vuid */
778 invalidate_vuid(vuid);
786 /* If we get here it wasn't a negTokenTarg auth packet. */
787 data_blob_free(&secblob);
789 if (!*auth_ntlmssp_state) {
790 /* Kill the intermediate vuid */
791 invalidate_vuid(vuid);
793 /* auth before negotiatiate? */
794 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
797 status = auth_ntlmssp_update(*auth_ntlmssp_state,
800 data_blob_free(&auth);
802 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
804 &auth_reply, status, True);
806 data_blob_free(&auth_reply);
808 /* and tell smbd that we have already replied to this packet */
812 /****************************************************************************
813 List to store partial SPNEGO auth fragments.
814 ****************************************************************************/
816 static struct pending_auth_data *pd_list;
818 /****************************************************************************
819 Delete an entry on the list.
820 ****************************************************************************/
822 static void delete_partial_auth(struct pending_auth_data *pad)
827 DLIST_REMOVE(pd_list, pad);
828 data_blob_free(&pad->partial_data);
832 /****************************************************************************
833 Search for a partial SPNEGO auth fragment matching an smbpid.
834 ****************************************************************************/
836 static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
838 struct pending_auth_data *pad;
840 for (pad = pd_list; pad; pad = pad->next) {
841 if (pad->smbpid == smbpid) {
848 /****************************************************************************
849 Check the size of an SPNEGO blob. If we need more return NT_STATUS_MORE_PROCESSING_REQUIRED,
850 else return NT_STATUS_OK. Don't allow the blob to be more than 64k.
851 ****************************************************************************/
853 static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB *pblob)
855 struct pending_auth_data *pad = NULL;
857 size_t needed_len = 0;
859 pad = get_pending_auth_data(smbpid);
861 /* Ensure we have some data. */
862 if (pblob->length == 0) {
863 /* Caller can cope. */
864 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
865 delete_partial_auth(pad);
869 /* Were we waiting for more data ? */
872 size_t copy_len = MIN(65536, pblob->length);
874 /* Integer wrap paranoia.... */
876 if (pad->partial_data.length + copy_len < pad->partial_data.length ||
877 pad->partial_data.length + copy_len < copy_len) {
879 DEBUG(2,("check_spnego_blob_complete: integer wrap "
880 "pad->partial_data.length = %u, "
882 (unsigned int)pad->partial_data.length,
883 (unsigned int)copy_len ));
885 delete_partial_auth(pad);
886 return NT_STATUS_INVALID_PARAMETER;
889 DEBUG(10,("check_spnego_blob_complete: "
890 "pad->partial_data.length = %u, "
891 "pad->needed_len = %u, "
893 "pblob->length = %u,\n",
894 (unsigned int)pad->partial_data.length,
895 (unsigned int)pad->needed_len,
896 (unsigned int)copy_len,
897 (unsigned int)pblob->length ));
899 tmp_blob = data_blob(NULL,
900 pad->partial_data.length + copy_len);
902 /* Concatenate the two (up to copy_len) bytes. */
903 memcpy(tmp_blob.data,
904 pad->partial_data.data,
905 pad->partial_data.length);
906 memcpy(tmp_blob.data + pad->partial_data.length,
910 /* Replace the partial data. */
911 data_blob_free(&pad->partial_data);
912 pad->partial_data = tmp_blob;
913 ZERO_STRUCT(tmp_blob);
916 if (pblob->length >= pad->needed_len) {
917 /* Yes, replace pblob. */
918 data_blob_free(pblob);
919 *pblob = pad->partial_data;
920 ZERO_STRUCT(pad->partial_data);
921 delete_partial_auth(pad);
925 /* Still need more data. */
926 pad->needed_len -= copy_len;
927 return NT_STATUS_MORE_PROCESSING_REQUIRED;
930 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
931 (pblob->data[0] != ASN1_CONTEXT(1))) {
932 /* Not something we can determine the
938 /* This is a new SPNEGO sessionsetup - see if
939 * the data given in this blob is enough.
942 asn1_load(&data, *pblob);
943 asn1_start_tag(&data, pblob->data[0]);
944 if (data.has_error || data.nesting == NULL) {
946 /* Let caller catch. */
950 /* Integer wrap paranoia.... */
952 if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
953 data.nesting->taglen + data.nesting->start < data.nesting->start) {
955 DEBUG(2,("check_spnego_blob_complete: integer wrap "
956 "data.nesting->taglen = %u, "
957 "data.nesting->start = %u\n",
958 (unsigned int)data.nesting->taglen,
959 (unsigned int)data.nesting->start ));
962 return NT_STATUS_INVALID_PARAMETER;
965 /* Total length of the needed asn1 is the tag length
966 * plus the current offset. */
968 needed_len = data.nesting->taglen + data.nesting->start;
971 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
972 "pblob->length = %u\n",
973 (unsigned int)needed_len,
974 (unsigned int)pblob->length ));
976 if (needed_len <= pblob->length) {
977 /* Nothing to do - blob is complete. */
981 /* Refuse the blob if it's bigger than 64k. */
982 if (needed_len > 65536) {
983 DEBUG(2,("check_spnego_blob_complete: needed_len too large (%u)\n",
984 (unsigned int)needed_len ));
985 return NT_STATUS_INVALID_PARAMETER;
988 /* We must store this blob until complete. */
989 pad = SMB_MALLOC(sizeof(struct pending_auth_data));
991 return NT_STATUS_NO_MEMORY;
993 pad->needed_len = needed_len - pblob->length;
994 pad->partial_data = data_blob(pblob->data, pblob->length);
995 if (pad->partial_data.data == NULL) {
997 return NT_STATUS_NO_MEMORY;
999 pad->smbpid = smbpid;
1001 DLIST_ADD(pd_list, pad);
1003 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1006 /****************************************************************************
1007 Reply to a session setup command.
1008 conn POINTER CAN BE NULL HERE !
1009 ****************************************************************************/
1011 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
1013 int length,int bufsize)
1019 fstring native_os, native_lanman, primary_domain;
1021 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
1022 enum remote_arch_types ra_type = get_remote_arch();
1023 int vuid = SVAL(inbuf,smb_uid);
1024 user_struct *vuser = NULL;
1025 NTSTATUS status = NT_STATUS_OK;
1026 uint16 smbpid = SVAL(inbuf,smb_pid);
1028 DEBUG(3,("Doing spnego session setup\n"));
1030 if (global_client_caps == 0) {
1031 global_client_caps = IVAL(inbuf,smb_vwv10);
1033 if (!(global_client_caps & CAP_STATUS32)) {
1034 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1039 p = (uint8 *)smb_buf(inbuf);
1041 if (data_blob_len == 0) {
1042 /* an invalid request */
1043 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1046 bufrem = smb_bufrem(inbuf, p);
1047 /* pull the spnego blob */
1048 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1051 file_save("negotiate.dat", blob1.data, blob1.length);
1054 p2 = inbuf + smb_vwv13 + data_blob_len;
1055 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
1056 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
1057 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
1058 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1059 native_os, native_lanman, primary_domain));
1061 if ( ra_type == RA_WIN2K ) {
1062 /* Windows 2003 doesn't set the native lanman string,
1063 but does set primary domain which is a bug I think */
1065 if ( !strlen(native_lanman) ) {
1066 ra_lanman_string( primary_domain );
1068 ra_lanman_string( native_lanman );
1072 vuser = get_partial_auth_user_struct(vuid);
1074 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
1076 DEBUG(10,("reply_sesssetup_and_X_spnego: found pending vuid %u\n",
1077 (unsigned int)pad->vuid ));
1079 vuser = get_partial_auth_user_struct(vuid);
1084 vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);
1085 if (vuid == UID_FIELD_INVALID ) {
1086 data_blob_free(&blob1);
1087 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1090 vuser = get_partial_auth_user_struct(vuid);
1094 data_blob_free(&blob1);
1095 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1098 SSVAL(outbuf,smb_uid,vuid);
1100 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1101 * sessionsetup requests as the Windows limit on the security blob
1102 * field is 4k. Bug #4400. JRA.
1105 status = check_spnego_blob_complete(smbpid, vuid, &blob1);
1106 if (!NT_STATUS_IS_OK(status)) {
1107 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1108 /* Real error - kill the intermediate vuid */
1109 invalidate_vuid(vuid);
1111 data_blob_free(&blob1);
1112 return ERROR_NT(nt_status_squash(status));
1115 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1116 /* its a negTokenTarg packet */
1117 ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
1118 &vuser->auth_ntlmssp_state);
1119 data_blob_free(&blob1);
1123 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1124 /* its a auth packet */
1125 ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
1126 &vuser->auth_ntlmssp_state);
1127 data_blob_free(&blob1);
1131 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1133 if (!vuser->auth_ntlmssp_state) {
1134 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1135 if (!NT_STATUS_IS_OK(status)) {
1136 /* Kill the intermediate vuid */
1137 invalidate_vuid(vuid);
1138 data_blob_free(&blob1);
1139 return ERROR_NT(nt_status_squash(status));
1143 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1146 data_blob_free(&blob1);
1148 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
1149 &vuser->auth_ntlmssp_state,
1150 &chal, status, False);
1151 data_blob_free(&chal);
1155 /* what sort of packet is this? */
1156 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1158 data_blob_free(&blob1);
1160 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1163 /****************************************************************************
1164 On new VC == 0, shutdown *all* old connections and users.
1165 It seems that only NT4.x does this. At W2K and above (XP etc.).
1166 a new session setup with VC==0 is ignored.
1167 ****************************************************************************/
1169 static int shutdown_other_smbds(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
1172 struct sessionid *sessionid = (struct sessionid *)dbuf.dptr;
1173 const char *ip = (const char *)p;
1175 if (!process_exists(pid_to_procid(sessionid->pid))) {
1179 if (sessionid->pid == sys_getpid()) {
1183 if (strcmp(ip, sessionid->ip_addr) != 0) {
1187 message_send_pid(pid_to_procid(sessionid->pid), MSG_SHUTDOWN,
1192 static void setup_new_vc_session(void)
1194 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
1197 invalidate_all_vuids();
1199 if (lp_reset_on_zero_vc()) {
1200 session_traverse(shutdown_other_smbds, client_addr());
1204 /****************************************************************************
1205 Reply to a session setup command.
1206 ****************************************************************************/
1208 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
1209 int length,int bufsize)
1215 DATA_BLOB plaintext_password;
1217 fstring sub_user; /* Sainitised username for substituion */
1220 fstring native_lanman;
1221 fstring primary_domain;
1222 static BOOL done_sesssetup = False;
1223 auth_usersupplied_info *user_info = NULL;
1224 auth_serversupplied_info *server_info = NULL;
1228 BOOL doencrypt = global_encrypted_passwords_negotiated;
1230 DATA_BLOB session_key;
1232 START_PROFILE(SMBsesssetupX);
1234 ZERO_STRUCT(lm_resp);
1235 ZERO_STRUCT(nt_resp);
1236 ZERO_STRUCT(plaintext_password);
1238 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
1240 /* a SPNEGO session setup has 12 command words, whereas a normal
1241 NT1 session setup has 13. See the cifs spec. */
1242 if (CVAL(inbuf, smb_wct) == 12 &&
1243 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
1244 if (!global_spnego_negotiated) {
1245 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
1246 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1249 if (SVAL(inbuf,smb_vwv4) == 0) {
1250 setup_new_vc_session();
1252 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
1255 smb_bufsize = SVAL(inbuf,smb_vwv2);
1257 if (Protocol < PROTOCOL_NT1) {
1258 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
1260 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
1261 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1263 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
1264 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1268 lm_resp = data_blob(smb_buf(inbuf), passlen1);
1270 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
1271 /* Ensure null termination */
1272 plaintext_password.data[passlen1] = 0;
1275 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
1279 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
1280 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
1281 enum remote_arch_types ra_type = get_remote_arch();
1282 char *p = smb_buf(inbuf);
1283 char *save_p = smb_buf(inbuf);
1287 if(global_client_caps == 0) {
1288 global_client_caps = IVAL(inbuf,smb_vwv11);
1290 if (!(global_client_caps & CAP_STATUS32)) {
1291 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1294 /* client_caps is used as final determination if client is NT or Win95.
1295 This is needed to return the correct error codes in some
1299 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
1300 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
1301 set_remote_arch( RA_WIN95);
1307 /* both Win95 and WinNT stuff up the password lengths for
1308 non-encrypting systems. Uggh.
1310 if passlen1==24 its a win95 system, and its setting the
1311 password length incorrectly. Luckily it still works with the
1312 default code because Win95 will null terminate the password
1315 if passlen1>0 and passlen2>0 then maybe its a NT box and its
1316 setting passlen2 to some random value which really stuffs
1317 things up. we need to fix that one. */
1319 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
1323 /* check for nasty tricks */
1324 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
1325 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1328 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
1329 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1332 /* Save the lanman2 password and the NT md4 password. */
1334 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1339 lm_resp = data_blob(p, passlen1);
1340 nt_resp = data_blob(p+passlen1, passlen2);
1343 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
1346 /* This was the previous fix. Not sure if it's still valid. JRA. */
1347 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
1348 /* NT4.0 stuffs up plaintext unicode password lengths... */
1349 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
1350 sizeof(pass), passlen1, STR_TERMINATE);
1353 if (unic && (passlen2 == 0) && passlen1) {
1354 /* Only a ascii plaintext password was sent. */
1355 srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
1356 passlen1, STR_TERMINATE|STR_ASCII);
1358 srvstr_pull(inbuf, pass, smb_buf(inbuf),
1359 sizeof(pass), unic ? passlen2 : passlen1,
1362 plaintext_password = data_blob(pass, strlen(pass)+1);
1365 p += passlen1 + passlen2;
1366 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
1367 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
1368 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
1369 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
1371 /* not documented or decoded by Ethereal but there is one more string
1372 in the extra bytes which is the same as the PrimaryDomain when using
1373 extended security. Windows NT 4 and 2003 use this string to store
1374 the native lanman string. Windows 9x does not include a string here
1375 at all so we have to check if we have any extra bytes left */
1377 byte_count = SVAL(inbuf, smb_vwv13);
1378 if ( PTR_DIFF(p, save_p) < byte_count)
1379 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
1381 fstrcpy( primary_domain, "null" );
1383 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1384 domain, native_os, native_lanman, primary_domain));
1386 if ( ra_type == RA_WIN2K ) {
1387 if ( strlen(native_lanman) == 0 )
1388 ra_lanman_string( primary_domain );
1390 ra_lanman_string( native_lanman );
1395 if (SVAL(inbuf,smb_vwv4) == 0) {
1396 setup_new_vc_session();
1399 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
1402 if (global_spnego_negotiated) {
1404 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
1406 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
1407 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1409 fstrcpy(sub_user, user);
1411 fstrcpy(sub_user, lp_guestaccount());
1414 sub_set_smb_name(sub_user);
1416 reload_services(True);
1418 if (lp_security() == SEC_SHARE) {
1419 /* in share level we should ignore any passwords */
1421 data_blob_free(&lm_resp);
1422 data_blob_free(&nt_resp);
1423 data_blob_clear_free(&plaintext_password);
1425 map_username(sub_user);
1426 add_session_user(sub_user);
1427 add_session_workgroup(domain);
1428 /* Then force it to null for the benfit of the code below */
1434 nt_status = check_guest_password(&server_info);
1436 } else if (doencrypt) {
1437 if (!negprot_global_auth_context) {
1438 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
1439 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1441 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
1443 if (NT_STATUS_IS_OK(nt_status)) {
1444 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
1449 struct auth_context *plaintext_auth_context = NULL;
1452 nt_status = make_auth_context_subsystem(&plaintext_auth_context);
1454 if (NT_STATUS_IS_OK(nt_status)) {
1455 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
1457 if (!make_user_info_for_reply(&user_info,
1459 plaintext_password)) {
1460 nt_status = NT_STATUS_NO_MEMORY;
1463 if (NT_STATUS_IS_OK(nt_status)) {
1464 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
1468 (plaintext_auth_context->free)(&plaintext_auth_context);
1473 free_user_info(&user_info);
1475 if (!NT_STATUS_IS_OK(nt_status)) {
1476 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
1479 if (!NT_STATUS_IS_OK(nt_status)) {
1480 data_blob_free(&nt_resp);
1481 data_blob_free(&lm_resp);
1482 data_blob_clear_free(&plaintext_password);
1483 return ERROR_NT(nt_status_squash(nt_status));
1486 /* Ensure we can't possible take a code path leading to a null defref. */
1488 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1491 nt_status = create_local_token(server_info);
1492 if (!NT_STATUS_IS_OK(nt_status)) {
1493 DEBUG(10, ("create_local_token failed: %s\n",
1494 nt_errstr(nt_status)));
1495 data_blob_free(&nt_resp);
1496 data_blob_free(&lm_resp);
1497 data_blob_clear_free(&plaintext_password);
1498 return ERROR_NT(nt_status_squash(nt_status));
1501 if (server_info->user_session_key.data) {
1502 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
1504 session_key = data_blob(NULL, 0);
1507 data_blob_clear_free(&plaintext_password);
1509 /* it's ok - setup a reply */
1510 set_message(outbuf,3,0,True);
1511 if (Protocol >= PROTOCOL_NT1) {
1512 char *p = smb_buf( outbuf );
1513 p += add_signature( outbuf, p );
1514 set_message_end( outbuf, p );
1515 /* perhaps grab OS version here?? */
1518 if (server_info->guest) {
1519 SSVAL(outbuf,smb_vwv2,1);
1522 /* register the name and uid as being validated, so further connections
1523 to a uid can get through without a password, on the same VC */
1525 if (lp_security() == SEC_SHARE) {
1526 sess_vuid = UID_FIELD_INVALID;
1527 data_blob_free(&session_key);
1528 TALLOC_FREE(server_info);
1530 /* register_vuid keeps the server info */
1531 sess_vuid = register_vuid(server_info, session_key,
1532 nt_resp.data ? nt_resp : lm_resp,
1534 if (sess_vuid == UID_FIELD_INVALID) {
1535 data_blob_free(&nt_resp);
1536 data_blob_free(&lm_resp);
1537 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1540 /* current_user_info is changed on new vuid */
1541 reload_services( True );
1543 sessionsetup_start_signing_engine(server_info, inbuf);
1546 data_blob_free(&nt_resp);
1547 data_blob_free(&lm_resp);
1549 SSVAL(outbuf,smb_uid,sess_vuid);
1550 SSVAL(inbuf,smb_uid,sess_vuid);
1552 if (!done_sesssetup)
1553 max_send = MIN(max_send,smb_bufsize);
1555 done_sesssetup = True;
1557 END_PROFILE(SMBsesssetupX);
1558 return chain_reply(inbuf,outbuf,length,bufsize);