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
);
248 DEBUG(1,("Username %s is invalid on this system\n",user
));
249 data_blob_free(&ap_rep
);
250 return ERROR_NT(NT_STATUS_LOGON_FAILURE
);
253 /* setup the string used by %U */
255 sub_set_smb_name(pw
->pw_name
);
256 reload_services(True
);
258 if (!NT_STATUS_IS_OK(ret
= make_server_info_pw(&server_info
,pw
))) {
259 DEBUG(1,("make_server_info_from_pw failed!\n"));
260 data_blob_free(&ap_rep
);
261 return ERROR_NT(ret
);
264 /* register_vuid keeps the server info */
265 sess_vuid
= register_vuid(server_info
, session_key
, nullblob
, user
);
269 if (sess_vuid
== -1) {
270 ret
= NT_STATUS_LOGON_FAILURE
;
272 set_message(outbuf
,4,0,True
);
273 SSVAL(outbuf
, smb_vwv3
, 0);
275 if (server_info
->guest
) {
276 SSVAL(outbuf
,smb_vwv2
,1);
279 SSVAL(outbuf
, smb_uid
, sess_vuid
);
281 if (!server_info
->guest
) {
282 /* We need to start the signing engine
283 * here but a W2K client sends the old
284 * "BSRSPYL " signature instead of the
285 * correct one. Subsequent packets will
288 srv_check_sign_mac(inbuf
);
292 /* wrap that up in a nice GSS-API wrapping */
293 if (NT_STATUS_IS_OK(ret
)) {
294 ap_rep_wrapped
= spnego_gen_krb5_wrap(ap_rep
, TOK_ID_KRB_AP_REP
);
296 ap_rep_wrapped
= data_blob(NULL
, 0);
298 response
= spnego_gen_auth_response(&ap_rep_wrapped
, ret
, OID_KERBEROS5_OLD
);
299 reply_sesssetup_blob(conn
, outbuf
, response
, ret
);
301 data_blob_free(&ap_rep
);
302 data_blob_free(&ap_rep_wrapped
);
303 data_blob_free(&response
);
305 return -1; /* already replied */
309 /****************************************************************************
310 Send a session setup reply, wrapped in SPNEGO.
311 Get vuid and check first.
312 End the NTLMSSP exchange context if we are OK/complete fail
313 ***************************************************************************/
315 static BOOL
reply_spnego_ntlmssp(connection_struct
*conn
, char *inbuf
, char *outbuf
,
316 AUTH_NTLMSSP_STATE
**auth_ntlmssp_state
,
317 DATA_BLOB
*ntlmssp_blob
, NTSTATUS nt_status
)
321 struct auth_serversupplied_info
*server_info
= NULL
;
323 if (NT_STATUS_IS_OK(nt_status
)) {
324 server_info
= (*auth_ntlmssp_state
)->server_info
;
326 nt_status
= do_map_to_guest(nt_status
,
328 (*auth_ntlmssp_state
)->ntlmssp_state
->user
,
329 (*auth_ntlmssp_state
)->ntlmssp_state
->domain
);
332 if (NT_STATUS_IS_OK(nt_status
)) {
334 DATA_BLOB nullblob
= data_blob(NULL
, 0);
335 DATA_BLOB session_key
= data_blob((*auth_ntlmssp_state
)->ntlmssp_state
->session_key
.data
, (*auth_ntlmssp_state
)->ntlmssp_state
->session_key
.length
);
337 /* register_vuid keeps the server info */
338 sess_vuid
= register_vuid(server_info
, session_key
, nullblob
, (*auth_ntlmssp_state
)->ntlmssp_state
->user
);
339 (*auth_ntlmssp_state
)->server_info
= NULL
;
341 if (sess_vuid
== -1) {
342 nt_status
= NT_STATUS_LOGON_FAILURE
;
345 set_message(outbuf
,4,0,True
);
346 SSVAL(outbuf
, smb_vwv3
, 0);
348 if (server_info
->guest
) {
349 SSVAL(outbuf
,smb_vwv2
,1);
352 SSVAL(outbuf
,smb_uid
,sess_vuid
);
354 if (!server_info
->guest
) {
355 /* We need to start the signing engine
356 * here but a W2K client sends the old
357 * "BSRSPYL " signature instead of the
358 * correct one. Subsequent packets will
361 srv_check_sign_mac(inbuf
);
366 response
= spnego_gen_auth_response(ntlmssp_blob
, nt_status
, OID_NTLMSSP
);
367 ret
= reply_sesssetup_blob(conn
, outbuf
, response
, nt_status
);
368 data_blob_free(&response
);
370 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
371 and the other end, that we are not finished yet. */
373 if (!ret
|| !NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
374 auth_ntlmssp_end(auth_ntlmssp_state
);
380 /****************************************************************************
381 Reply to a session setup spnego negotiate packet.
382 ****************************************************************************/
384 static int reply_spnego_negotiate(connection_struct
*conn
,
387 int length
, int bufsize
,
390 char *OIDs
[ASN1_MAX_OIDS
];
394 BOOL got_kerberos
= False
;
397 /* parse out the OIDs and the first sec blob */
398 if (!parse_negTokenTarg(blob1
, OIDs
, &secblob
)) {
399 return ERROR_NT(NT_STATUS_LOGON_FAILURE
);
402 /* only look at the first OID for determining the mechToken --
403 accoirding to RFC2478, we should choose the one we want
404 and renegotiate, but i smell a client bug here..
406 Problem observed when connecting to a member (samba box)
407 of an AD domain as a user in a Samba domain. Samba member
408 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
409 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
410 NTLMSSP mechtoken. --jerry */
412 if (strcmp(OID_KERBEROS5
, OIDs
[0]) == 0 ||
413 strcmp(OID_KERBEROS5_OLD
, OIDs
[0]) == 0) {
417 for (i
=0;OIDs
[i
];i
++) {
418 DEBUG(3,("Got OID %s\n", OIDs
[i
]));
421 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob
.length
));
424 if (got_kerberos
&& (SEC_ADS
== lp_security())) {
425 int ret
= reply_spnego_kerberos(conn
, inbuf
, outbuf
,
426 length
, bufsize
, &secblob
);
427 data_blob_free(&secblob
);
432 if (global_ntlmssp_state
) {
433 auth_ntlmssp_end(&global_ntlmssp_state
);
436 nt_status
= auth_ntlmssp_start(&global_ntlmssp_state
);
437 if (!NT_STATUS_IS_OK(nt_status
)) {
438 return ERROR_NT(nt_status
);
441 nt_status
= auth_ntlmssp_update(global_ntlmssp_state
,
444 data_blob_free(&secblob
);
446 reply_spnego_ntlmssp(conn
, inbuf
, outbuf
, &global_ntlmssp_state
,
449 data_blob_free(&chal
);
451 /* already replied */
455 /****************************************************************************
456 Reply to a session setup spnego auth packet.
457 ****************************************************************************/
459 static int reply_spnego_auth(connection_struct
*conn
, char *inbuf
, char *outbuf
,
460 int length
, int bufsize
,
463 DATA_BLOB auth
, auth_reply
;
464 NTSTATUS nt_status
= NT_STATUS_INVALID_PARAMETER
;
466 if (!spnego_parse_auth(blob1
, &auth
)) {
468 file_save("auth.dat", blob1
.data
, blob1
.length
);
470 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
473 if (!global_ntlmssp_state
) {
474 /* auth before negotiatiate? */
475 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
478 nt_status
= auth_ntlmssp_update(global_ntlmssp_state
,
481 data_blob_free(&auth
);
483 reply_spnego_ntlmssp(conn
, inbuf
, outbuf
, &global_ntlmssp_state
,
484 &auth_reply
, nt_status
);
486 data_blob_free(&auth_reply
);
488 /* and tell smbd that we have already replied to this packet */
492 /****************************************************************************
493 Reply to a session setup command.
494 ****************************************************************************/
496 static int reply_sesssetup_and_X_spnego(connection_struct
*conn
, char *inbuf
,
498 int length
,int bufsize
)
504 fstring native_os
, native_lanman
, primary_domain
;
506 uint16 data_blob_len
= SVAL(inbuf
, smb_vwv7
);
507 enum remote_arch_types ra_type
= get_remote_arch();
509 DEBUG(3,("Doing spnego session setup\n"));
511 if (global_client_caps
== 0) {
512 global_client_caps
= IVAL(inbuf
,smb_vwv10
);
514 if (!(global_client_caps
& CAP_STATUS32
)) {
515 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
520 p
= (uint8
*)smb_buf(inbuf
);
522 if (data_blob_len
== 0) {
523 /* an invalid request */
524 return ERROR_NT(NT_STATUS_LOGON_FAILURE
);
527 bufrem
= smb_bufrem(inbuf
, p
);
528 /* pull the spnego blob */
529 blob1
= data_blob(p
, MIN(bufrem
, data_blob_len
));
532 file_save("negotiate.dat", blob1
.data
, blob1
.length
);
535 p2
= inbuf
+ smb_vwv13
+ data_blob_len
;
536 p2
+= srvstr_pull_buf(inbuf
, native_os
, p2
, sizeof(native_os
), STR_TERMINATE
);
537 p2
+= srvstr_pull_buf(inbuf
, native_lanman
, p2
, sizeof(native_lanman
), STR_TERMINATE
);
538 p2
+= srvstr_pull_buf(inbuf
, primary_domain
, p2
, sizeof(primary_domain
), STR_TERMINATE
);
539 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
540 native_os
, native_lanman
, primary_domain
));
542 if ( ra_type
== RA_WIN2K
) {
543 /* Windows 2003 doesn't set the native lanman string,
544 but does set primary domain which is a bug I think */
546 if ( !strlen(native_lanman
) )
547 ra_lanman_string( primary_domain
);
549 ra_lanman_string( native_lanman
);
552 if (blob1
.data
[0] == ASN1_APPLICATION(0)) {
553 /* its a negTokenTarg packet */
554 ret
= reply_spnego_negotiate(conn
, inbuf
, outbuf
, length
, bufsize
, blob1
);
555 data_blob_free(&blob1
);
559 if (blob1
.data
[0] == ASN1_CONTEXT(1)) {
560 /* its a auth packet */
561 ret
= reply_spnego_auth(conn
, inbuf
, outbuf
, length
, bufsize
, blob1
);
562 data_blob_free(&blob1
);
566 /* what sort of packet is this? */
567 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
569 data_blob_free(&blob1
);
571 return ERROR_NT(NT_STATUS_LOGON_FAILURE
);
574 /****************************************************************************
575 On new VC == 0, shutdown *all* old connections and users.
576 It seems that only NT4.x does this. At W2K and above (XP etc.).
577 a new session setup with VC==0 is ignored.
578 ****************************************************************************/
580 static void setup_new_vc_session(void)
582 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
585 invalidate_all_vuids();
589 /****************************************************************************
590 Reply to a session setup command.
591 ****************************************************************************/
593 int reply_sesssetup_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,
594 int length
,int bufsize
)
600 DATA_BLOB plaintext_password
;
602 fstring sub_user
; /* Sainitised username for substituion */
605 fstring native_lanman
;
606 fstring primary_domain
;
607 static BOOL done_sesssetup
= False
;
608 extern BOOL global_encrypted_passwords_negotiated
;
609 extern BOOL global_spnego_negotiated
;
613 auth_usersupplied_info
*user_info
= NULL
;
614 extern struct auth_context
*negprot_global_auth_context
;
615 auth_serversupplied_info
*server_info
= NULL
;
619 BOOL doencrypt
= global_encrypted_passwords_negotiated
;
621 DATA_BLOB session_key
;
623 START_PROFILE(SMBsesssetupX
);
625 ZERO_STRUCT(lm_resp
);
626 ZERO_STRUCT(nt_resp
);
627 ZERO_STRUCT(plaintext_password
);
629 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf
, smb_wct
), SVAL(inbuf
, smb_flg2
)));
631 /* a SPNEGO session setup has 12 command words, whereas a normal
632 NT1 session setup has 13. See the cifs spec. */
633 if (CVAL(inbuf
, smb_wct
) == 12 &&
634 (SVAL(inbuf
, smb_flg2
) & FLAGS2_EXTENDED_SECURITY
)) {
635 if (!global_spnego_negotiated
) {
636 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
637 return ERROR_NT(NT_STATUS_UNSUCCESSFUL
);
640 if (SVAL(inbuf
,smb_vwv4
) == 0) {
641 setup_new_vc_session();
643 return reply_sesssetup_and_X_spnego(conn
, inbuf
, outbuf
, length
, bufsize
);
646 smb_bufsize
= SVAL(inbuf
,smb_vwv2
);
648 if (Protocol
< PROTOCOL_NT1
) {
649 uint16 passlen1
= SVAL(inbuf
,smb_vwv7
);
650 if ((passlen1
> MAX_PASS_LEN
) || (passlen1
> smb_bufrem(inbuf
, smb_buf(inbuf
)))) {
651 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
655 lm_resp
= data_blob(smb_buf(inbuf
), passlen1
);
657 plaintext_password
= data_blob(smb_buf(inbuf
), passlen1
+1);
658 /* Ensure null termination */
659 plaintext_password
.data
[passlen1
] = 0;
662 srvstr_pull_buf(inbuf
, user
, smb_buf(inbuf
)+passlen1
, sizeof(user
), STR_TERMINATE
);
666 uint16 passlen1
= SVAL(inbuf
,smb_vwv7
);
667 uint16 passlen2
= SVAL(inbuf
,smb_vwv8
);
668 enum remote_arch_types ra_type
= get_remote_arch();
669 char *p
= smb_buf(inbuf
);
670 char *save_p
= smb_buf(inbuf
);
674 if(global_client_caps
== 0) {
675 global_client_caps
= IVAL(inbuf
,smb_vwv11
);
677 if (!(global_client_caps
& CAP_STATUS32
)) {
678 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
681 /* client_caps is used as final determination if client is NT or Win95.
682 This is needed to return the correct error codes in some
686 if(ra_type
== RA_WINNT
|| ra_type
== RA_WIN2K
|| ra_type
== RA_WIN95
) {
687 if(!(global_client_caps
& (CAP_NT_SMBS
| CAP_STATUS32
))) {
688 set_remote_arch( RA_WIN95
);
694 /* both Win95 and WinNT stuff up the password lengths for
695 non-encrypting systems. Uggh.
697 if passlen1==24 its a win95 system, and its setting the
698 password length incorrectly. Luckily it still works with the
699 default code because Win95 will null terminate the password
702 if passlen1>0 and passlen2>0 then maybe its a NT box and its
703 setting passlen2 to some random value which really stuffs
704 things up. we need to fix that one. */
706 if (passlen1
> 0 && passlen2
> 0 && passlen2
!= 24 && passlen2
!= 1)
710 /* check for nasty tricks */
711 if (passlen1
> MAX_PASS_LEN
|| passlen1
> smb_bufrem(inbuf
, p
)) {
712 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
715 if (passlen2
> MAX_PASS_LEN
|| passlen2
> smb_bufrem(inbuf
, p
+passlen1
)) {
716 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
719 /* Save the lanman2 password and the NT md4 password. */
721 if ((doencrypt
) && (passlen1
!= 0) && (passlen1
!= 24)) {
726 lm_resp
= data_blob(p
, passlen1
);
727 nt_resp
= data_blob(p
+passlen1
, passlen2
);
730 BOOL unic
=SVAL(inbuf
, smb_flg2
) & FLAGS2_UNICODE_STRINGS
;
732 if ((ra_type
== RA_WINNT
) && (passlen2
== 0) && unic
&& passlen1
) {
733 /* NT4.0 stuffs up plaintext unicode password lengths... */
734 srvstr_pull(inbuf
, pass
, smb_buf(inbuf
) + 1,
735 sizeof(pass
), passlen1
, STR_TERMINATE
);
737 srvstr_pull(inbuf
, pass
, smb_buf(inbuf
),
738 sizeof(pass
), unic
? passlen2
: passlen1
,
741 plaintext_password
= data_blob(pass
, strlen(pass
)+1);
744 p
+= passlen1
+ passlen2
;
745 p
+= srvstr_pull_buf(inbuf
, user
, p
, sizeof(user
), STR_TERMINATE
);
746 p
+= srvstr_pull_buf(inbuf
, domain
, p
, sizeof(domain
), STR_TERMINATE
);
747 p
+= srvstr_pull_buf(inbuf
, native_os
, p
, sizeof(native_os
), STR_TERMINATE
);
748 p
+= srvstr_pull_buf(inbuf
, native_lanman
, p
, sizeof(native_lanman
), STR_TERMINATE
);
750 /* not documented or decoded by Ethereal but there is one more string
751 in the extra bytes which is the same as the PrimaryDomain when using
752 extended security. Windows NT 4 and 2003 use this string to store
753 the native lanman string. Windows 9x does not include a string here
754 at all so we have to check if we have any extra bytes left */
756 byte_count
= SVAL(inbuf
, smb_vwv13
);
757 if ( PTR_DIFF(p
, save_p
) < byte_count
)
758 p
+= srvstr_pull_buf(inbuf
, primary_domain
, p
, sizeof(primary_domain
), STR_TERMINATE
);
760 fstrcpy( primary_domain
, "null" );
762 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
763 domain
, native_os
, native_lanman
, primary_domain
));
765 if ( ra_type
== RA_WIN2K
) {
766 if ( strlen(native_lanman
) == 0 )
767 ra_lanman_string( primary_domain
);
769 ra_lanman_string( native_lanman
);
774 if (SVAL(inbuf
,smb_vwv4
) == 0) {
775 setup_new_vc_session();
778 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain
, user
, get_remote_machine_name()));
781 if (global_spnego_negotiated
) {
783 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
785 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
786 return ERROR_NT(NT_STATUS_UNSUCCESSFUL
);
788 fstrcpy(sub_user
, user
);
790 /* setup the string used by %U */
791 sub_set_smb_name(user
);
793 fstrcpy(sub_user
, lp_guestaccount());
796 sub_set_smb_name(sub_user
);
798 reload_services(True
);
800 if (lp_security() == SEC_SHARE
) {
801 /* in share level we should ignore any passwords */
803 data_blob_free(&lm_resp
);
804 data_blob_free(&nt_resp
);
805 data_blob_clear_free(&plaintext_password
);
807 map_username(sub_user
);
808 add_session_user(sub_user
);
809 /* Then force it to null for the benfit of the code below */
815 nt_status
= check_guest_password(&server_info
);
817 } else if (doencrypt
) {
818 if (!negprot_global_auth_context
) {
819 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
820 return ERROR_NT(NT_STATUS_LOGON_FAILURE
);
822 nt_status
= make_user_info_for_reply_enc(&user_info
, user
, domain
,
824 if (NT_STATUS_IS_OK(nt_status
)) {
825 nt_status
= negprot_global_auth_context
->check_ntlm_password(negprot_global_auth_context
,
830 struct auth_context
*plaintext_auth_context
= NULL
;
832 if (NT_STATUS_IS_OK(nt_status
= make_auth_context_subsystem(&plaintext_auth_context
))) {
833 chal
= plaintext_auth_context
->get_ntlm_challenge(plaintext_auth_context
);
835 if (!make_user_info_for_reply(&user_info
,
837 plaintext_password
)) {
838 nt_status
= NT_STATUS_NO_MEMORY
;
841 if (NT_STATUS_IS_OK(nt_status
)) {
842 nt_status
= plaintext_auth_context
->check_ntlm_password(plaintext_auth_context
,
846 (plaintext_auth_context
->free
)(&plaintext_auth_context
);
851 free_user_info(&user_info
);
853 if (!NT_STATUS_IS_OK(nt_status
)) {
854 nt_status
= do_map_to_guest(nt_status
, &server_info
, user
, domain
);
857 if (!NT_STATUS_IS_OK(nt_status
)) {
858 data_blob_free(&nt_resp
);
859 data_blob_free(&lm_resp
);
860 data_blob_clear_free(&plaintext_password
);
861 return ERROR_NT(nt_status_squash(nt_status
));
864 if (server_info
->nt_session_key
.data
) {
865 session_key
= data_blob(server_info
->nt_session_key
.data
, server_info
->nt_session_key
.length
);
866 } else if (server_info
->lm_session_key
.length
>= 8 && lm_resp
.length
== 24) {
867 session_key
= data_blob(NULL
, 16);
868 SMBsesskeygen_lmv1(server_info
->lm_session_key
.data
, lm_resp
.data
,
872 data_blob_free(&lm_resp
);
873 data_blob_clear_free(&plaintext_password
);
875 /* it's ok - setup a reply */
876 set_message(outbuf
,3,0,True
);
877 if (Protocol
>= PROTOCOL_NT1
) {
878 char *p
= smb_buf( outbuf
);
879 p
+= add_signature( outbuf
, p
);
880 set_message_end( outbuf
, p
);
881 /* perhaps grab OS version here?? */
884 if (server_info
->guest
) {
885 SSVAL(outbuf
,smb_vwv2
,1);
888 /* register the name and uid as being validated, so further connections
889 to a uid can get through without a password, on the same VC */
891 /* register_vuid keeps the server info */
892 sess_vuid
= register_vuid(server_info
, session_key
, nt_resp
, sub_user
);
893 data_blob_free(&nt_resp
);
895 if (sess_vuid
== -1) {
896 return ERROR_NT(NT_STATUS_LOGON_FAILURE
);
899 if (!server_info
->guest
&& !srv_check_sign_mac(inbuf
)) {
900 exit_server("reply_sesssetup_and_X: bad smb signature");
903 SSVAL(outbuf
,smb_uid
,sess_vuid
);
904 SSVAL(inbuf
,smb_uid
,sess_vuid
);
907 max_send
= MIN(max_send
,smb_bufsize
);
909 done_sesssetup
= True
;
911 END_PROFILE(SMBsesssetupX
);
912 return chain_reply(inbuf
,outbuf
,length
,bufsize
);