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 extern BOOL global_encrypted_passwords_negotiated;
29 extern BOOL global_spnego_negotiated;
30 extern enum protocol_types Protocol;
32 extern struct auth_context *negprot_global_auth_context;
34 static struct auth_ntlmssp_state *global_ntlmssp_state;
37 on a logon error possibly map the error to success if "map to guest"
40 static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **server_info,
41 const char *user, const char *domain)
43 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
44 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
45 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
46 DEBUG(3,("No such user %s [%s] - using guest account\n",
48 status = make_server_info_guest(server_info);
52 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
53 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
54 DEBUG(3,("Registered username %s for guest access\n",user));
55 status = make_server_info_guest(server_info);
62 /****************************************************************************
63 Add the standard 'Samba' signature to the end of the session setup.
64 ****************************************************************************/
66 static int add_signature(char *outbuf, char *p)
71 fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
73 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
74 p += srvstr_push(outbuf, p, lanman, -1, STR_TERMINATE);
75 p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
77 return PTR_DIFF(p, start);
80 /****************************************************************************
81 Send a security blob via a session setup reply.
82 ****************************************************************************/
84 static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
85 DATA_BLOB blob, NTSTATUS nt_status)
89 set_message(outbuf,4,0,True);
91 nt_status = nt_status_squash(nt_status);
92 SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
93 SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
94 SSVAL(outbuf, smb_vwv3, blob.length);
97 /* should we cap this? */
98 memcpy(p, blob.data, blob.length);
101 p += add_signature( outbuf, p );
103 set_message_end(outbuf,p);
105 return send_smb(smbd_server_fd(),outbuf);
108 /****************************************************************************
109 Do a 'guest' logon, getting back the
110 ****************************************************************************/
112 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
114 struct auth_context *auth_context;
115 auth_usersupplied_info *user_info = NULL;
118 unsigned char chal[8];
122 DEBUG(3,("Got anonymous request\n"));
124 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) {
129 if (!make_user_info_guest(&user_info)) {
130 (auth_context->free)(&auth_context);
131 return NT_STATUS_NO_MEMORY;
134 nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info);
135 (auth_context->free)(&auth_context);
136 free_user_info(&user_info);
142 /****************************************************************************
143 reply to a session setup spnego negotiate packet for kerberos
144 ****************************************************************************/
145 static int reply_spnego_kerberos(connection_struct *conn,
146 char *inbuf, char *outbuf,
147 int length, int bufsize,
150 int map_domainuser_to_guest = 0;
152 char *client, *p, *domain;
153 fstring netbios_domain_name;
159 DATA_BLOB ap_rep, ap_rep_wrapped, response;
160 auth_serversupplied_info *server_info = NULL;
161 DATA_BLOB session_key = data_blob(NULL, 0);
163 DATA_BLOB nullblob = data_blob(NULL, 0);
164 fstring real_username;
167 ZERO_STRUCT(auth_data);
169 ZERO_STRUCT(ap_rep_wrapped);
170 ZERO_STRUCT(response);
172 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
173 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
176 ret = ads_verify_ticket(lp_realm(), &ticket, &client, &auth_data, &ap_rep, &session_key);
178 data_blob_free(&ticket);
180 if (!NT_STATUS_IS_OK(ret)) {
181 DEBUG(1,("Failed to verify incoming ticket!\n"));
182 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
185 data_blob_free(&auth_data);
187 DEBUG(3,("Ticket name is [%s]\n", client));
189 p = strchr_m(client, '@');
191 DEBUG(3,("Doesn't look like a valid principal\n"));
192 data_blob_free(&ap_rep);
193 data_blob_free(&session_key);
195 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
199 if (!strequal(p+1, lp_realm())) {
200 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
201 if (!lp_allow_trusted_domains()) {
202 data_blob_free(&ap_rep);
203 data_blob_free(&session_key);
205 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
209 /* this gives a fully qualified user name (ie. with full realm).
210 that leads to very long usernames, but what else can we do? */
215 /* If we have winbind running, we can (and must) shorten the
216 username by using the short netbios name. Otherwise we will
217 have inconsistent user names. With Kerberos, we get the
218 fully qualified realm, with ntlmssp we get the short
219 name. And even w2k3 does use ntlmssp if you for example
220 connect to an ip address. */
222 struct winbindd_request wb_request;
223 struct winbindd_response wb_response;
224 NSS_STATUS wb_result;
226 ZERO_STRUCT(wb_request);
227 ZERO_STRUCT(wb_response);
229 DEBUG(10, ("Mapping [%s] to short name\n", domain));
231 fstrcpy(wb_request.domain_name, domain);
233 wb_result = winbindd_request(WINBINDD_DOMAIN_INFO,
234 &wb_request, &wb_response);
236 if (wb_result == NSS_STATUS_SUCCESS) {
238 fstrcpy(netbios_domain_name,
239 wb_response.data.domain_info.name);
240 domain = netbios_domain_name;
242 DEBUG(10, ("Mapped to [%s]\n", domain));
244 DEBUG(3, ("Could not find short name -- winbind "
249 asprintf(&user, "%s%c%s", domain, *lp_winbind_separator(), client);
250 /* lookup the passwd struct, create a new user if necessary */
251 if (lp_map_to_guest() == MAP_TO_GUEST_ON_VALID_DOMAIN_USER ){
252 map_domainuser_to_guest == 1;
253 fstrcpy(user,lp_guestaccount());
254 pw = smb_getpwnam( user, real_username, True );
257 map_username( user );
259 pw = smb_getpwnam( user, real_username, True );
263 DEBUG(1,("Username %s is invalid on this system\n",user));
266 data_blob_free(&ap_rep);
267 data_blob_free(&session_key);
268 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
271 /* setup the string used by %U */
273 sub_set_smb_name( real_username );
274 reload_services(True);
275 if (map_domainuser_to_guest == 1) {
276 make_server_info_guest(&server_info);
278 if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info, real_username, pw)))
280 DEBUG(1,("make_server_info_from_pw failed!\n"));
283 data_blob_free(&ap_rep);
285 data_blob_free(&session_key);
286 return ERROR_NT(ret);
290 /* make_server_info_pw does not set the domain. Without this we end up
291 * with the local netbios name in substitutions for %D. */
293 if (server_info->sam_account != NULL) {
294 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
297 /* register_vuid keeps the server info */
298 /* register_vuid takes ownership of session_key, no need to free after this.
299 A better interface would copy it.... */
300 sess_vuid = register_vuid(server_info, session_key, nullblob, client);
305 if (sess_vuid == -1) {
306 ret = NT_STATUS_LOGON_FAILURE;
308 /* current_user_info is changed on new vuid */
309 reload_services( True );
311 set_message(outbuf,4,0,True);
312 SSVAL(outbuf, smb_vwv3, 0);
314 if (server_info->guest) {
315 SSVAL(outbuf,smb_vwv2,1);
318 SSVAL(outbuf, smb_uid, sess_vuid);
320 if (!server_info->guest && !srv_signing_started()) {
321 /* We need to start the signing engine
322 * here but a W2K client sends the old
323 * "BSRSPYL " signature instead of the
324 * correct one. Subsequent packets will
327 srv_check_sign_mac(inbuf, False);
331 /* wrap that up in a nice GSS-API wrapping */
332 if (NT_STATUS_IS_OK(ret)) {
333 ap_rep_wrapped = spnego_gen_krb5_wrap(
335 CONST_ADD(const uint8 *, TOK_ID_KRB_AP_REP));
337 ap_rep_wrapped = data_blob(NULL, 0);
339 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
340 reply_sesssetup_blob(conn, outbuf, response, ret);
342 data_blob_free(&ap_rep);
343 data_blob_free(&ap_rep_wrapped);
344 data_blob_free(&response);
346 return -1; /* already replied */
350 /****************************************************************************
351 Send a session setup reply, wrapped in SPNEGO.
352 Get vuid and check first.
353 End the NTLMSSP exchange context if we are OK/complete fail
354 ***************************************************************************/
356 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
357 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
358 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status)
362 struct auth_serversupplied_info *server_info = NULL;
364 if (NT_STATUS_IS_OK(nt_status)) {
365 server_info = (*auth_ntlmssp_state)->server_info;
367 nt_status = do_map_to_guest(nt_status,
369 (*auth_ntlmssp_state)->ntlmssp_state->user,
370 (*auth_ntlmssp_state)->ntlmssp_state->domain);
373 if (NT_STATUS_IS_OK(nt_status)) {
375 DATA_BLOB nullblob = data_blob(NULL, 0);
376 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
378 /* register_vuid keeps the server info */
379 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
380 (*auth_ntlmssp_state)->server_info = NULL;
382 if (sess_vuid == -1) {
383 nt_status = NT_STATUS_LOGON_FAILURE;
386 /* current_user_info is changed on new vuid */
387 reload_services( True );
389 set_message(outbuf,4,0,True);
390 SSVAL(outbuf, smb_vwv3, 0);
392 if (server_info->guest) {
393 SSVAL(outbuf,smb_vwv2,1);
396 SSVAL(outbuf,smb_uid,sess_vuid);
398 if (!server_info->guest && !srv_signing_started()) {
399 /* We need to start the signing engine
400 * here but a W2K client sends the old
401 * "BSRSPYL " signature instead of the
402 * correct one. Subsequent packets will
406 srv_check_sign_mac(inbuf, False);
411 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
412 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
413 data_blob_free(&response);
415 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
416 and the other end, that we are not finished yet. */
418 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
419 auth_ntlmssp_end(auth_ntlmssp_state);
425 /****************************************************************************
426 Reply to a session setup spnego negotiate packet.
427 ****************************************************************************/
429 static int reply_spnego_negotiate(connection_struct *conn,
432 int length, int bufsize,
435 char *OIDs[ASN1_MAX_OIDS];
440 BOOL got_kerberos_mechanism = False;
444 /* parse out the OIDs and the first sec blob */
445 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
446 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
449 /* only look at the first OID for determining the mechToken --
450 accoirding to RFC2478, we should choose the one we want
451 and renegotiate, but i smell a client bug here..
453 Problem observed when connecting to a member (samba box)
454 of an AD domain as a user in a Samba domain. Samba member
455 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
456 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
457 NTLMSSP mechtoken. --jerry */
460 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
461 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
462 got_kerberos_mechanism = True;
466 for (i=0;OIDs[i];i++) {
467 DEBUG(3,("Got OID %s\n", OIDs[i]));
470 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
473 if (got_kerberos_mechanism && (SEC_ADS == lp_security())) {
474 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
475 length, bufsize, &secblob);
476 data_blob_free(&secblob);
481 if (global_ntlmssp_state) {
482 auth_ntlmssp_end(&global_ntlmssp_state);
485 nt_status = auth_ntlmssp_start(&global_ntlmssp_state);
486 if (!NT_STATUS_IS_OK(nt_status)) {
487 return ERROR_NT(nt_status);
490 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
493 data_blob_free(&secblob);
495 reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
498 data_blob_free(&chal);
500 /* already replied */
504 /****************************************************************************
505 Reply to a session setup spnego auth packet.
506 ****************************************************************************/
508 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
509 int length, int bufsize,
512 DATA_BLOB auth, auth_reply;
513 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
515 if (!spnego_parse_auth(blob1, &auth)) {
517 file_save("auth.dat", blob1.data, blob1.length);
519 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
522 if (!global_ntlmssp_state) {
523 /* auth before negotiatiate? */
524 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
527 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
530 data_blob_free(&auth);
532 reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
533 &auth_reply, nt_status);
535 data_blob_free(&auth_reply);
537 /* and tell smbd that we have already replied to this packet */
541 /****************************************************************************
542 Reply to a session setup command.
543 ****************************************************************************/
545 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
547 int length,int bufsize)
553 fstring native_os, native_lanman, primary_domain;
555 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
556 enum remote_arch_types ra_type = get_remote_arch();
558 DEBUG(3,("Doing spnego session setup\n"));
560 if (global_client_caps == 0) {
561 global_client_caps = IVAL(inbuf,smb_vwv10);
563 if (!(global_client_caps & CAP_STATUS32)) {
564 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
569 p = (uint8 *)smb_buf(inbuf);
571 if (data_blob_len == 0) {
572 /* an invalid request */
573 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
576 bufrem = smb_bufrem(inbuf, p);
577 /* pull the spnego blob */
578 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
581 file_save("negotiate.dat", blob1.data, blob1.length);
584 p2 = inbuf + smb_vwv13 + data_blob_len;
585 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
586 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
587 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
588 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
589 native_os, native_lanman, primary_domain));
591 if ( ra_type == RA_WIN2K ) {
592 /* Windows 2003 doesn't set the native lanman string,
593 but does set primary domain which is a bug I think */
595 if ( !strlen(native_lanman) )
596 ra_lanman_string( primary_domain );
598 ra_lanman_string( native_lanman );
601 if (blob1.data[0] == ASN1_APPLICATION(0)) {
602 /* its a negTokenTarg packet */
603 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
604 data_blob_free(&blob1);
608 if (blob1.data[0] == ASN1_CONTEXT(1)) {
609 /* its a auth packet */
610 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
611 data_blob_free(&blob1);
615 /* what sort of packet is this? */
616 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
618 data_blob_free(&blob1);
620 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
623 /****************************************************************************
624 On new VC == 0, shutdown *all* old connections and users.
625 It seems that only NT4.x does this. At W2K and above (XP etc.).
626 a new session setup with VC==0 is ignored.
627 ****************************************************************************/
629 static void setup_new_vc_session(void)
631 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
634 invalidate_all_vuids();
638 /****************************************************************************
639 Reply to a session setup command.
640 ****************************************************************************/
642 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
643 int length,int bufsize)
649 DATA_BLOB plaintext_password;
651 fstring sub_user; /* Sainitised username for substituion */
654 fstring native_lanman;
655 fstring primary_domain;
656 static BOOL done_sesssetup = False;
658 auth_usersupplied_info *user_info = NULL;
659 auth_serversupplied_info *server_info = NULL;
663 BOOL doencrypt = global_encrypted_passwords_negotiated;
665 DATA_BLOB session_key;
667 START_PROFILE(SMBsesssetupX);
669 ZERO_STRUCT(lm_resp);
670 ZERO_STRUCT(nt_resp);
671 ZERO_STRUCT(plaintext_password);
673 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
675 /* a SPNEGO session setup has 12 command words, whereas a normal
676 NT1 session setup has 13. See the cifs spec. */
677 if (CVAL(inbuf, smb_wct) == 12 &&
678 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
679 if (!global_spnego_negotiated) {
680 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
681 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
684 if (SVAL(inbuf,smb_vwv4) == 0) {
685 setup_new_vc_session();
687 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
690 smb_bufsize = SVAL(inbuf,smb_vwv2);
692 if (Protocol < PROTOCOL_NT1) {
693 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
695 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
696 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
698 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
699 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
703 lm_resp = data_blob(smb_buf(inbuf), passlen1);
705 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
706 /* Ensure null termination */
707 plaintext_password.data[passlen1] = 0;
710 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
714 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
715 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
716 enum remote_arch_types ra_type = get_remote_arch();
717 char *p = smb_buf(inbuf);
718 char *save_p = smb_buf(inbuf);
722 if(global_client_caps == 0) {
723 global_client_caps = IVAL(inbuf,smb_vwv11);
725 if (!(global_client_caps & CAP_STATUS32)) {
726 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
729 /* client_caps is used as final determination if client is NT or Win95.
730 This is needed to return the correct error codes in some
734 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
735 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
736 set_remote_arch( RA_WIN95);
742 /* both Win95 and WinNT stuff up the password lengths for
743 non-encrypting systems. Uggh.
745 if passlen1==24 its a win95 system, and its setting the
746 password length incorrectly. Luckily it still works with the
747 default code because Win95 will null terminate the password
750 if passlen1>0 and passlen2>0 then maybe its a NT box and its
751 setting passlen2 to some random value which really stuffs
752 things up. we need to fix that one. */
754 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
758 /* check for nasty tricks */
759 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
760 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
763 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
764 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
767 /* Save the lanman2 password and the NT md4 password. */
769 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
774 lm_resp = data_blob(p, passlen1);
775 nt_resp = data_blob(p+passlen1, passlen2);
778 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
781 /* This was the previous fix. Not sure if it's still valid. JRA. */
782 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
783 /* NT4.0 stuffs up plaintext unicode password lengths... */
784 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
785 sizeof(pass), passlen1, STR_TERMINATE);
788 if (unic && (passlen2 == 0) && passlen1) {
789 /* Only a ascii plaintext password was sent. */
790 srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
791 passlen1, STR_TERMINATE|STR_ASCII);
793 srvstr_pull(inbuf, pass, smb_buf(inbuf),
794 sizeof(pass), unic ? passlen2 : passlen1,
797 plaintext_password = data_blob(pass, strlen(pass)+1);
800 p += passlen1 + passlen2;
801 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
802 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
803 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
804 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
806 /* not documented or decoded by Ethereal but there is one more string
807 in the extra bytes which is the same as the PrimaryDomain when using
808 extended security. Windows NT 4 and 2003 use this string to store
809 the native lanman string. Windows 9x does not include a string here
810 at all so we have to check if we have any extra bytes left */
812 byte_count = SVAL(inbuf, smb_vwv13);
813 if ( PTR_DIFF(p, save_p) < byte_count)
814 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
816 fstrcpy( primary_domain, "null" );
818 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
819 domain, native_os, native_lanman, primary_domain));
821 if ( ra_type == RA_WIN2K ) {
822 if ( strlen(native_lanman) == 0 )
823 ra_lanman_string( primary_domain );
825 ra_lanman_string( native_lanman );
830 if (SVAL(inbuf,smb_vwv4) == 0) {
831 setup_new_vc_session();
834 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
837 if (global_spnego_negotiated) {
839 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
841 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
842 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
844 fstrcpy(sub_user, user);
846 /* setup the string used by %U */
847 sub_set_smb_name(user);
849 fstrcpy(sub_user, lp_guestaccount());
852 sub_set_smb_name(sub_user);
854 reload_services(True);
856 if (lp_security() == SEC_SHARE) {
857 /* in share level we should ignore any passwords */
859 data_blob_free(&lm_resp);
860 data_blob_free(&nt_resp);
861 data_blob_clear_free(&plaintext_password);
863 map_username(sub_user);
864 add_session_user(sub_user);
865 /* Then force it to null for the benfit of the code below */
871 nt_status = check_guest_password(&server_info);
873 } else if (doencrypt) {
874 if (!negprot_global_auth_context) {
875 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
876 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
878 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
880 if (NT_STATUS_IS_OK(nt_status)) {
881 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
886 struct auth_context *plaintext_auth_context = NULL;
888 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
889 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
891 if (!make_user_info_for_reply(&user_info,
893 plaintext_password)) {
894 nt_status = NT_STATUS_NO_MEMORY;
897 if (NT_STATUS_IS_OK(nt_status)) {
898 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
902 (plaintext_auth_context->free)(&plaintext_auth_context);
907 free_user_info(&user_info);
909 if (!NT_STATUS_IS_OK(nt_status)) {
910 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
913 if (!NT_STATUS_IS_OK(nt_status)) {
914 data_blob_free(&nt_resp);
915 data_blob_free(&lm_resp);
916 data_blob_clear_free(&plaintext_password);
917 return ERROR_NT(nt_status_squash(nt_status));
920 if (server_info->user_session_key.data) {
921 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
923 session_key = data_blob(NULL, 0);
926 data_blob_clear_free(&plaintext_password);
928 /* it's ok - setup a reply */
929 set_message(outbuf,3,0,True);
930 if (Protocol >= PROTOCOL_NT1) {
931 char *p = smb_buf( outbuf );
932 p += add_signature( outbuf, p );
933 set_message_end( outbuf, p );
934 /* perhaps grab OS version here?? */
937 if (server_info->guest) {
938 SSVAL(outbuf,smb_vwv2,1);
941 /* register the name and uid as being validated, so further connections
942 to a uid can get through without a password, on the same VC */
944 /* register_vuid keeps the server info */
945 sess_vuid = register_vuid(server_info, session_key, nt_resp.data ? nt_resp : lm_resp, sub_user);
946 data_blob_free(&nt_resp);
947 data_blob_free(&lm_resp);
949 if (sess_vuid == -1) {
950 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
953 /* current_user_info is changed on new vuid */
954 reload_services( True );
956 if (!server_info->guest && !srv_signing_started() && !srv_check_sign_mac(inbuf, True)) {
957 exit_server("reply_sesssetup_and_X: bad smb signature");
960 SSVAL(outbuf,smb_uid,sess_vuid);
961 SSVAL(inbuf,smb_uid,sess_vuid);
964 max_send = MIN(max_send,smb_bufsize);
966 done_sesssetup = True;
968 END_PROFILE(SMBsesssetupX);
969 return chain_reply(inbuf,outbuf,length,bufsize);