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 uint32 global_client_caps
= 0;
28 static struct auth_ntlmssp_state
*global_ntlmssp_state
;
31 on a logon error possibly map the error to success if "map to guest"
34 static NTSTATUS
do_map_to_guest(NTSTATUS status
, auth_serversupplied_info
**server_info
,
35 const char *user
, const char *domain
)
37 if (NT_STATUS_EQUAL(status
, NT_STATUS_NO_SUCH_USER
)) {
38 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER
) ||
39 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
)) {
40 DEBUG(3,("No such user %s [%s] - using guest account\n",
42 status
= make_server_info_guest(server_info
);
46 if (NT_STATUS_EQUAL(status
, NT_STATUS_WRONG_PASSWORD
)) {
47 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
) {
48 DEBUG(3,("Registered username %s for guest access\n",user
));
49 status
= make_server_info_guest(server_info
);
56 /****************************************************************************
57 Add the standard 'Samba' signature to the end of the session setup.
58 ****************************************************************************/
60 static int add_signature(char *outbuf
, char *p
)
65 fstr_sprintf( lanman
, "Samba %s", SAMBA_VERSION_STRING
);
67 p
+= srvstr_push(outbuf
, p
, "Unix", -1, STR_TERMINATE
);
68 p
+= srvstr_push(outbuf
, p
, lanman
, -1, STR_TERMINATE
);
69 p
+= srvstr_push(outbuf
, p
, lp_workgroup(), -1, STR_TERMINATE
);
71 return PTR_DIFF(p
, start
);
74 /****************************************************************************
75 Send a security blob via a session setup reply.
76 ****************************************************************************/
78 static BOOL
reply_sesssetup_blob(connection_struct
*conn
, char *outbuf
,
79 DATA_BLOB blob
, NTSTATUS nt_status
)
83 set_message(outbuf
,4,0,True
);
85 nt_status
= nt_status_squash(nt_status
);
86 SIVAL(outbuf
, smb_rcls
, NT_STATUS_V(nt_status
));
87 SSVAL(outbuf
, smb_vwv0
, 0xFF); /* no chaining possible */
88 SSVAL(outbuf
, smb_vwv3
, blob
.length
);
91 /* should we cap this? */
92 memcpy(p
, blob
.data
, blob
.length
);
95 p
+= add_signature( outbuf
, p
);
97 set_message_end(outbuf
,p
);
99 return send_smb(smbd_server_fd(),outbuf
);
102 /****************************************************************************
103 Do a 'guest' logon, getting back the
104 ****************************************************************************/
106 static NTSTATUS
check_guest_password(auth_serversupplied_info
**server_info
)
108 struct auth_context
*auth_context
;
109 auth_usersupplied_info
*user_info
= NULL
;
112 unsigned char chal
[8];
116 DEBUG(3,("Got anonymous request\n"));
118 if (!NT_STATUS_IS_OK(nt_status
= make_auth_context_fixed(&auth_context
, chal
))) {
122 if (!make_user_info_guest(&user_info
)) {
123 (auth_context
->free
)(&auth_context
);
124 return NT_STATUS_NO_MEMORY
;
127 nt_status
= auth_context
->check_ntlm_password(auth_context
, user_info
, server_info
);
128 (auth_context
->free
)(&auth_context
);
129 free_user_info(&user_info
);
135 /****************************************************************************
136 reply to a session setup spnego negotiate packet for kerberos
137 ****************************************************************************/
138 static int reply_spnego_kerberos(connection_struct
*conn
,
139 char *inbuf
, char *outbuf
,
140 int length
, int bufsize
,
144 char *client
, *p
, *domain
;
145 fstring netbios_domain_name
;
146 const struct passwd
*pw
;
151 DATA_BLOB ap_rep
, ap_rep_wrapped
, response
;
152 auth_serversupplied_info
*server_info
= NULL
;
153 DATA_BLOB session_key
;
155 BOOL foreign
= False
;
156 DATA_BLOB nullblob
= data_blob(NULL
, 0);
159 ZERO_STRUCT(auth_data
);
161 ZERO_STRUCT(ap_rep_wrapped
);
162 ZERO_STRUCT(response
);
164 if (!spnego_parse_krb5_wrap(*secblob
, &ticket
, tok_id
)) {
165 return ERROR_NT(NT_STATUS_LOGON_FAILURE
);
168 ret
= ads_verify_ticket(lp_realm(), &ticket
, &client
, &auth_data
, &ap_rep
, &session_key
);
170 data_blob_free(&ticket
);
172 if (!NT_STATUS_IS_OK(ret
)) {
173 DEBUG(1,("Failed to verify incoming ticket!\n"));
174 return ERROR_NT(NT_STATUS_LOGON_FAILURE
);
177 data_blob_free(&auth_data
);
179 DEBUG(3,("Ticket name is [%s]\n", client
));
181 p
= strchr_m(client
, '@');
183 DEBUG(3,("Doesn't look like a valid principal\n"));
184 data_blob_free(&ap_rep
);
186 return ERROR_NT(NT_STATUS_LOGON_FAILURE
);
190 if (!strequal(p
+1, lp_realm())) {
191 DEBUG(3,("Ticket for foreign realm %s@%s\n", client
, p
+1));
192 if (!lp_allow_trusted_domains()) {
193 data_blob_free(&ap_rep
);
195 return ERROR_NT(NT_STATUS_LOGON_FAILURE
);
200 /* this gives a fully qualified user name (ie. with full realm).
201 that leads to very long usernames, but what else can we do? */
206 /* If we have winbind running, we can (and must) shorten the
207 username by using the short netbios name. Otherwise we will
208 have inconsistent user names. With Kerberos, we get the
209 fully qualified realm, with ntlmssp we get the short
210 name. And even w2k3 does use ntlmssp if you for example
211 connect to an ip address. */
213 struct winbindd_request wb_request
;
214 struct winbindd_response wb_response
;
215 NSS_STATUS wb_result
;
217 ZERO_STRUCT(wb_request
);
218 ZERO_STRUCT(wb_response
);
220 DEBUG(10, ("Mapping [%s] to short name\n", domain
));
222 fstrcpy(wb_request
.domain_name
, domain
);
224 wb_result
= winbindd_request(WINBINDD_DOMAIN_INFO
,
225 &wb_request
, &wb_response
);
227 if (wb_result
== NSS_STATUS_SUCCESS
) {
229 fstrcpy(netbios_domain_name
,
230 wb_response
.data
.domain_info
.name
);
231 domain
= netbios_domain_name
;
233 DEBUG(10, ("Mapped to [%s]\n", domain
));
235 DEBUG(3, ("Could not find short name -- winbind "
240 asprintf(&user
, "%s%c%s", domain
, *lp_winbind_separator(), client
);
242 pw
= smb_getpwnam( user
);
245 DEBUG(1,("Username %s is invalid on this system\n",user
));
248 data_blob_free(&ap_rep
);
249 return ERROR_NT(NT_STATUS_LOGON_FAILURE
);
252 /* setup the string used by %U */
254 sub_set_smb_name(pw
->pw_name
);
255 reload_services(True
);
257 if (!NT_STATUS_IS_OK(ret
= make_server_info_pw(&server_info
,pw
))) {
258 DEBUG(1,("make_server_info_from_pw failed!\n"));
261 data_blob_free(&ap_rep
);
262 return ERROR_NT(ret
);
265 /* make_server_info_pw does not set the domain. Without this we end up
266 * with the local netbios name in substitutions for %D. */
268 if (server_info
->sam_account
!= NULL
) {
269 pdb_set_domain(server_info
->sam_account
, domain
, PDB_SET
);
272 /* register_vuid keeps the server info */
273 sess_vuid
= register_vuid(server_info
, session_key
, nullblob
, client
);
278 if (sess_vuid
== -1) {
279 ret
= NT_STATUS_LOGON_FAILURE
;
281 set_message(outbuf
,4,0,True
);
282 SSVAL(outbuf
, smb_vwv3
, 0);
284 if (server_info
->guest
) {
285 SSVAL(outbuf
,smb_vwv2
,1);
288 SSVAL(outbuf
, smb_uid
, sess_vuid
);
290 if (!server_info
->guest
&& !srv_signing_started()) {
291 /* We need to start the signing engine
292 * here but a W2K client sends the old
293 * "BSRSPYL " signature instead of the
294 * correct one. Subsequent packets will
297 srv_check_sign_mac(inbuf
, False
);
301 /* wrap that up in a nice GSS-API wrapping */
302 if (NT_STATUS_IS_OK(ret
)) {
303 ap_rep_wrapped
= spnego_gen_krb5_wrap(ap_rep
, TOK_ID_KRB_AP_REP
);
305 ap_rep_wrapped
= data_blob(NULL
, 0);
307 response
= spnego_gen_auth_response(&ap_rep_wrapped
, ret
, OID_KERBEROS5_OLD
);
308 reply_sesssetup_blob(conn
, outbuf
, response
, ret
);
310 data_blob_free(&ap_rep
);
311 data_blob_free(&ap_rep_wrapped
);
312 data_blob_free(&response
);
314 return -1; /* already replied */
318 /****************************************************************************
319 Send a session setup reply, wrapped in SPNEGO.
320 Get vuid and check first.
321 End the NTLMSSP exchange context if we are OK/complete fail
322 ***************************************************************************/
324 static BOOL
reply_spnego_ntlmssp(connection_struct
*conn
, char *inbuf
, char *outbuf
,
325 AUTH_NTLMSSP_STATE
**auth_ntlmssp_state
,
326 DATA_BLOB
*ntlmssp_blob
, NTSTATUS nt_status
)
330 struct auth_serversupplied_info
*server_info
= NULL
;
332 if (NT_STATUS_IS_OK(nt_status
)) {
333 server_info
= (*auth_ntlmssp_state
)->server_info
;
335 nt_status
= do_map_to_guest(nt_status
,
337 (*auth_ntlmssp_state
)->ntlmssp_state
->user
,
338 (*auth_ntlmssp_state
)->ntlmssp_state
->domain
);
341 if (NT_STATUS_IS_OK(nt_status
)) {
343 DATA_BLOB nullblob
= data_blob(NULL
, 0);
344 DATA_BLOB session_key
= data_blob((*auth_ntlmssp_state
)->ntlmssp_state
->session_key
.data
, (*auth_ntlmssp_state
)->ntlmssp_state
->session_key
.length
);
346 /* register_vuid keeps the server info */
347 sess_vuid
= register_vuid(server_info
, session_key
, nullblob
, (*auth_ntlmssp_state
)->ntlmssp_state
->user
);
348 (*auth_ntlmssp_state
)->server_info
= NULL
;
350 if (sess_vuid
== -1) {
351 nt_status
= NT_STATUS_LOGON_FAILURE
;
354 set_message(outbuf
,4,0,True
);
355 SSVAL(outbuf
, smb_vwv3
, 0);
357 if (server_info
->guest
) {
358 SSVAL(outbuf
,smb_vwv2
,1);
361 SSVAL(outbuf
,smb_uid
,sess_vuid
);
363 if (!server_info
->guest
&& !srv_signing_started()) {
364 /* We need to start the signing engine
365 * here but a W2K client sends the old
366 * "BSRSPYL " signature instead of the
367 * correct one. Subsequent packets will
371 srv_check_sign_mac(inbuf
, False
);
376 response
= spnego_gen_auth_response(ntlmssp_blob
, nt_status
, OID_NTLMSSP
);
377 ret
= reply_sesssetup_blob(conn
, outbuf
, response
, nt_status
);
378 data_blob_free(&response
);
380 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
381 and the other end, that we are not finished yet. */
383 if (!ret
|| !NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
384 auth_ntlmssp_end(auth_ntlmssp_state
);
390 /****************************************************************************
391 Reply to a session setup spnego negotiate packet.
392 ****************************************************************************/
394 static int reply_spnego_negotiate(connection_struct
*conn
,
397 int length
, int bufsize
,
400 char *OIDs
[ASN1_MAX_OIDS
];
404 BOOL got_kerberos
= False
;
407 /* parse out the OIDs and the first sec blob */
408 if (!parse_negTokenTarg(blob1
, OIDs
, &secblob
)) {
409 return ERROR_NT(NT_STATUS_LOGON_FAILURE
);
412 /* only look at the first OID for determining the mechToken --
413 accoirding to RFC2478, we should choose the one we want
414 and renegotiate, but i smell a client bug here..
416 Problem observed when connecting to a member (samba box)
417 of an AD domain as a user in a Samba domain. Samba member
418 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
419 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
420 NTLMSSP mechtoken. --jerry */
422 if (strcmp(OID_KERBEROS5
, OIDs
[0]) == 0 ||
423 strcmp(OID_KERBEROS5_OLD
, OIDs
[0]) == 0) {
427 for (i
=0;OIDs
[i
];i
++) {
428 DEBUG(3,("Got OID %s\n", OIDs
[i
]));
431 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob
.length
));
434 if (got_kerberos
&& (SEC_ADS
== lp_security())) {
435 int ret
= reply_spnego_kerberos(conn
, inbuf
, outbuf
,
436 length
, bufsize
, &secblob
);
437 data_blob_free(&secblob
);
442 if (global_ntlmssp_state
) {
443 auth_ntlmssp_end(&global_ntlmssp_state
);
446 nt_status
= auth_ntlmssp_start(&global_ntlmssp_state
);
447 if (!NT_STATUS_IS_OK(nt_status
)) {
448 return ERROR_NT(nt_status
);
451 nt_status
= auth_ntlmssp_update(global_ntlmssp_state
,
454 data_blob_free(&secblob
);
456 reply_spnego_ntlmssp(conn
, inbuf
, outbuf
, &global_ntlmssp_state
,
459 data_blob_free(&chal
);
461 /* already replied */
465 /****************************************************************************
466 Reply to a session setup spnego auth packet.
467 ****************************************************************************/
469 static int reply_spnego_auth(connection_struct
*conn
, char *inbuf
, char *outbuf
,
470 int length
, int bufsize
,
473 DATA_BLOB auth
, auth_reply
;
474 NTSTATUS nt_status
= NT_STATUS_INVALID_PARAMETER
;
476 if (!spnego_parse_auth(blob1
, &auth
)) {
478 file_save("auth.dat", blob1
.data
, blob1
.length
);
480 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
483 if (!global_ntlmssp_state
) {
484 /* auth before negotiatiate? */
485 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
488 nt_status
= auth_ntlmssp_update(global_ntlmssp_state
,
491 data_blob_free(&auth
);
493 reply_spnego_ntlmssp(conn
, inbuf
, outbuf
, &global_ntlmssp_state
,
494 &auth_reply
, nt_status
);
496 data_blob_free(&auth_reply
);
498 /* and tell smbd that we have already replied to this packet */
502 /****************************************************************************
503 Reply to a session setup command.
504 ****************************************************************************/
506 static int reply_sesssetup_and_X_spnego(connection_struct
*conn
, char *inbuf
,
508 int length
,int bufsize
)
514 fstring native_os
, native_lanman
, primary_domain
;
516 uint16 data_blob_len
= SVAL(inbuf
, smb_vwv7
);
517 enum remote_arch_types ra_type
= get_remote_arch();
519 DEBUG(3,("Doing spnego session setup\n"));
521 if (global_client_caps
== 0) {
522 global_client_caps
= IVAL(inbuf
,smb_vwv10
);
524 if (!(global_client_caps
& CAP_STATUS32
)) {
525 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
530 p
= (uint8
*)smb_buf(inbuf
);
532 if (data_blob_len
== 0) {
533 /* an invalid request */
534 return ERROR_NT(NT_STATUS_LOGON_FAILURE
);
537 bufrem
= smb_bufrem(inbuf
, p
);
538 /* pull the spnego blob */
539 blob1
= data_blob(p
, MIN(bufrem
, data_blob_len
));
542 file_save("negotiate.dat", blob1
.data
, blob1
.length
);
545 p2
= inbuf
+ smb_vwv13
+ data_blob_len
;
546 p2
+= srvstr_pull_buf(inbuf
, native_os
, p2
, sizeof(native_os
), STR_TERMINATE
);
547 p2
+= srvstr_pull_buf(inbuf
, native_lanman
, p2
, sizeof(native_lanman
), STR_TERMINATE
);
548 p2
+= srvstr_pull_buf(inbuf
, primary_domain
, p2
, sizeof(primary_domain
), STR_TERMINATE
);
549 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
550 native_os
, native_lanman
, primary_domain
));
552 if ( ra_type
== RA_WIN2K
) {
553 /* Windows 2003 doesn't set the native lanman string,
554 but does set primary domain which is a bug I think */
556 if ( !strlen(native_lanman
) )
557 ra_lanman_string( primary_domain
);
559 ra_lanman_string( native_lanman
);
562 if (blob1
.data
[0] == ASN1_APPLICATION(0)) {
563 /* its a negTokenTarg packet */
564 ret
= reply_spnego_negotiate(conn
, inbuf
, outbuf
, length
, bufsize
, blob1
);
565 data_blob_free(&blob1
);
569 if (blob1
.data
[0] == ASN1_CONTEXT(1)) {
570 /* its a auth packet */
571 ret
= reply_spnego_auth(conn
, inbuf
, outbuf
, length
, bufsize
, blob1
);
572 data_blob_free(&blob1
);
576 /* what sort of packet is this? */
577 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
579 data_blob_free(&blob1
);
581 return ERROR_NT(NT_STATUS_LOGON_FAILURE
);
584 /****************************************************************************
585 On new VC == 0, shutdown *all* old connections and users.
586 It seems that only NT4.x does this. At W2K and above (XP etc.).
587 a new session setup with VC==0 is ignored.
588 ****************************************************************************/
590 static void setup_new_vc_session(void)
592 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
595 invalidate_all_vuids();
599 /****************************************************************************
600 Reply to a session setup command.
601 ****************************************************************************/
603 int reply_sesssetup_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,
604 int length
,int bufsize
)
610 DATA_BLOB plaintext_password
;
612 fstring sub_user
; /* Sainitised username for substituion */
615 fstring native_lanman
;
616 fstring primary_domain
;
617 static BOOL done_sesssetup
= False
;
618 extern BOOL global_encrypted_passwords_negotiated
;
619 extern BOOL global_spnego_negotiated
;
623 auth_usersupplied_info
*user_info
= NULL
;
624 extern struct auth_context
*negprot_global_auth_context
;
625 auth_serversupplied_info
*server_info
= NULL
;
629 BOOL doencrypt
= global_encrypted_passwords_negotiated
;
631 DATA_BLOB session_key
;
633 START_PROFILE(SMBsesssetupX
);
635 ZERO_STRUCT(lm_resp
);
636 ZERO_STRUCT(nt_resp
);
637 ZERO_STRUCT(plaintext_password
);
639 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf
, smb_wct
), SVAL(inbuf
, smb_flg2
)));
641 /* a SPNEGO session setup has 12 command words, whereas a normal
642 NT1 session setup has 13. See the cifs spec. */
643 if (CVAL(inbuf
, smb_wct
) == 12 &&
644 (SVAL(inbuf
, smb_flg2
) & FLAGS2_EXTENDED_SECURITY
)) {
645 if (!global_spnego_negotiated
) {
646 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
647 return ERROR_NT(NT_STATUS_UNSUCCESSFUL
);
650 if (SVAL(inbuf
,smb_vwv4
) == 0) {
651 setup_new_vc_session();
653 return reply_sesssetup_and_X_spnego(conn
, inbuf
, outbuf
, length
, bufsize
);
656 smb_bufsize
= SVAL(inbuf
,smb_vwv2
);
658 if (Protocol
< PROTOCOL_NT1
) {
659 uint16 passlen1
= SVAL(inbuf
,smb_vwv7
);
660 if ((passlen1
> MAX_PASS_LEN
) || (passlen1
> smb_bufrem(inbuf
, smb_buf(inbuf
)))) {
661 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
665 lm_resp
= data_blob(smb_buf(inbuf
), passlen1
);
667 plaintext_password
= data_blob(smb_buf(inbuf
), passlen1
+1);
668 /* Ensure null termination */
669 plaintext_password
.data
[passlen1
] = 0;
672 srvstr_pull_buf(inbuf
, user
, smb_buf(inbuf
)+passlen1
, sizeof(user
), STR_TERMINATE
);
676 uint16 passlen1
= SVAL(inbuf
,smb_vwv7
);
677 uint16 passlen2
= SVAL(inbuf
,smb_vwv8
);
678 enum remote_arch_types ra_type
= get_remote_arch();
679 char *p
= smb_buf(inbuf
);
680 char *save_p
= smb_buf(inbuf
);
684 if(global_client_caps
== 0) {
685 global_client_caps
= IVAL(inbuf
,smb_vwv11
);
687 if (!(global_client_caps
& CAP_STATUS32
)) {
688 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
691 /* client_caps is used as final determination if client is NT or Win95.
692 This is needed to return the correct error codes in some
696 if(ra_type
== RA_WINNT
|| ra_type
== RA_WIN2K
|| ra_type
== RA_WIN95
) {
697 if(!(global_client_caps
& (CAP_NT_SMBS
| CAP_STATUS32
))) {
698 set_remote_arch( RA_WIN95
);
704 /* both Win95 and WinNT stuff up the password lengths for
705 non-encrypting systems. Uggh.
707 if passlen1==24 its a win95 system, and its setting the
708 password length incorrectly. Luckily it still works with the
709 default code because Win95 will null terminate the password
712 if passlen1>0 and passlen2>0 then maybe its a NT box and its
713 setting passlen2 to some random value which really stuffs
714 things up. we need to fix that one. */
716 if (passlen1
> 0 && passlen2
> 0 && passlen2
!= 24 && passlen2
!= 1)
720 /* check for nasty tricks */
721 if (passlen1
> MAX_PASS_LEN
|| passlen1
> smb_bufrem(inbuf
, p
)) {
722 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
725 if (passlen2
> MAX_PASS_LEN
|| passlen2
> smb_bufrem(inbuf
, p
+passlen1
)) {
726 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
729 /* Save the lanman2 password and the NT md4 password. */
731 if ((doencrypt
) && (passlen1
!= 0) && (passlen1
!= 24)) {
736 lm_resp
= data_blob(p
, passlen1
);
737 nt_resp
= data_blob(p
+passlen1
, passlen2
);
740 BOOL unic
=SVAL(inbuf
, smb_flg2
) & FLAGS2_UNICODE_STRINGS
;
742 if ((ra_type
== RA_WINNT
) && (passlen2
== 0) && unic
&& passlen1
) {
743 /* NT4.0 stuffs up plaintext unicode password lengths... */
744 srvstr_pull(inbuf
, pass
, smb_buf(inbuf
) + 1,
745 sizeof(pass
), passlen1
, STR_TERMINATE
);
747 srvstr_pull(inbuf
, pass
, smb_buf(inbuf
),
748 sizeof(pass
), unic
? passlen2
: passlen1
,
751 plaintext_password
= data_blob(pass
, strlen(pass
)+1);
754 p
+= passlen1
+ passlen2
;
755 p
+= srvstr_pull_buf(inbuf
, user
, p
, sizeof(user
), STR_TERMINATE
);
756 p
+= srvstr_pull_buf(inbuf
, domain
, p
, sizeof(domain
), STR_TERMINATE
);
757 p
+= srvstr_pull_buf(inbuf
, native_os
, p
, sizeof(native_os
), STR_TERMINATE
);
758 p
+= srvstr_pull_buf(inbuf
, native_lanman
, p
, sizeof(native_lanman
), STR_TERMINATE
);
760 /* not documented or decoded by Ethereal but there is one more string
761 in the extra bytes which is the same as the PrimaryDomain when using
762 extended security. Windows NT 4 and 2003 use this string to store
763 the native lanman string. Windows 9x does not include a string here
764 at all so we have to check if we have any extra bytes left */
766 byte_count
= SVAL(inbuf
, smb_vwv13
);
767 if ( PTR_DIFF(p
, save_p
) < byte_count
)
768 p
+= srvstr_pull_buf(inbuf
, primary_domain
, p
, sizeof(primary_domain
), STR_TERMINATE
);
770 fstrcpy( primary_domain
, "null" );
772 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
773 domain
, native_os
, native_lanman
, primary_domain
));
775 if ( ra_type
== RA_WIN2K
) {
776 if ( strlen(native_lanman
) == 0 )
777 ra_lanman_string( primary_domain
);
779 ra_lanman_string( native_lanman
);
784 if (SVAL(inbuf
,smb_vwv4
) == 0) {
785 setup_new_vc_session();
788 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain
, user
, get_remote_machine_name()));
791 if (global_spnego_negotiated
) {
793 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
795 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
796 return ERROR_NT(NT_STATUS_UNSUCCESSFUL
);
798 fstrcpy(sub_user
, user
);
800 /* setup the string used by %U */
801 sub_set_smb_name(user
);
803 fstrcpy(sub_user
, lp_guestaccount());
806 sub_set_smb_name(sub_user
);
808 reload_services(True
);
810 if (lp_security() == SEC_SHARE
) {
811 /* in share level we should ignore any passwords */
813 data_blob_free(&lm_resp
);
814 data_blob_free(&nt_resp
);
815 data_blob_clear_free(&plaintext_password
);
817 map_username(sub_user
);
818 add_session_user(sub_user
);
819 /* Then force it to null for the benfit of the code below */
825 nt_status
= check_guest_password(&server_info
);
827 } else if (doencrypt
) {
828 if (!negprot_global_auth_context
) {
829 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
830 return ERROR_NT(NT_STATUS_LOGON_FAILURE
);
832 nt_status
= make_user_info_for_reply_enc(&user_info
, user
, domain
,
834 if (NT_STATUS_IS_OK(nt_status
)) {
835 nt_status
= negprot_global_auth_context
->check_ntlm_password(negprot_global_auth_context
,
840 struct auth_context
*plaintext_auth_context
= NULL
;
842 if (NT_STATUS_IS_OK(nt_status
= make_auth_context_subsystem(&plaintext_auth_context
))) {
843 chal
= plaintext_auth_context
->get_ntlm_challenge(plaintext_auth_context
);
845 if (!make_user_info_for_reply(&user_info
,
847 plaintext_password
)) {
848 nt_status
= NT_STATUS_NO_MEMORY
;
851 if (NT_STATUS_IS_OK(nt_status
)) {
852 nt_status
= plaintext_auth_context
->check_ntlm_password(plaintext_auth_context
,
856 (plaintext_auth_context
->free
)(&plaintext_auth_context
);
861 free_user_info(&user_info
);
863 if (!NT_STATUS_IS_OK(nt_status
)) {
864 nt_status
= do_map_to_guest(nt_status
, &server_info
, user
, domain
);
867 if (!NT_STATUS_IS_OK(nt_status
)) {
868 data_blob_free(&nt_resp
);
869 data_blob_free(&lm_resp
);
870 data_blob_clear_free(&plaintext_password
);
871 return ERROR_NT(nt_status_squash(nt_status
));
874 if (server_info
->nt_session_key
.data
) {
875 session_key
= data_blob(server_info
->nt_session_key
.data
, server_info
->nt_session_key
.length
);
876 } else if (server_info
->lm_session_key
.length
>= 8 && lm_resp
.length
== 24) {
877 session_key
= data_blob(NULL
, 16);
878 SMBsesskeygen_lmv1(server_info
->lm_session_key
.data
, lm_resp
.data
,
881 session_key
= data_blob(NULL
, 0);
884 data_blob_free(&lm_resp
);
885 data_blob_clear_free(&plaintext_password
);
887 /* it's ok - setup a reply */
888 set_message(outbuf
,3,0,True
);
889 if (Protocol
>= PROTOCOL_NT1
) {
890 char *p
= smb_buf( outbuf
);
891 p
+= add_signature( outbuf
, p
);
892 set_message_end( outbuf
, p
);
893 /* perhaps grab OS version here?? */
896 if (server_info
->guest
) {
897 SSVAL(outbuf
,smb_vwv2
,1);
900 /* register the name and uid as being validated, so further connections
901 to a uid can get through without a password, on the same VC */
903 /* register_vuid keeps the server info */
904 sess_vuid
= register_vuid(server_info
, session_key
, nt_resp
, sub_user
);
905 data_blob_free(&nt_resp
);
907 if (sess_vuid
== -1) {
908 return ERROR_NT(NT_STATUS_LOGON_FAILURE
);
911 if (!server_info
->guest
&& !srv_signing_started() && !srv_check_sign_mac(inbuf
, True
)) {
912 exit_server("reply_sesssetup_and_X: bad smb signature");
915 SSVAL(outbuf
,smb_uid
,sess_vuid
);
916 SSVAL(inbuf
,smb_uid
,sess_vuid
);
919 max_send
= MIN(max_send
,smb_bufsize
);
921 done_sesssetup
= True
;
923 END_PROFILE(SMBsesssetupX
);
924 return chain_reply(inbuf
,outbuf
,length
,bufsize
);