port latest changes from SAMBA_3_0 tree
[Samba/bb.git] / source3 / smbd / sesssetup.c
blob88b442215d66f78a4244e9be6122a2dfb9535de7
1 /*
2 Unix SMB/CIFS implementation.
3 handle SMBsessionsetup
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.
24 #include "includes.h"
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"
32 is set approriately
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",
41 user, domain));
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);
53 return status;
56 /****************************************************************************
57 Add the standard 'Samba' signature to the end of the session setup.
58 ****************************************************************************/
60 static int add_signature(char *outbuf, char *p)
62 char *start = p;
63 fstring lanman;
65 fstr_sprintf( lanman, "Samba %s", VERSION );
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)
81 char *p;
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);
89 p = smb_buf(outbuf);
91 /* should we cap this? */
92 memcpy(p, blob.data, blob.length);
93 p += 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;
111 NTSTATUS nt_status;
112 unsigned char chal[8];
114 ZERO_STRUCT(chal);
116 DEBUG(3,("Got anonymous request\n"));
118 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) {
119 return nt_status;
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);
130 return nt_status;
134 #ifdef HAVE_KRB5
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,
141 DATA_BLOB *secblob)
143 DATA_BLOB ticket;
144 char *client, *p;
145 const struct passwd *pw;
146 char *user;
147 int sess_vuid;
148 NTSTATUS ret;
149 DATA_BLOB auth_data;
150 DATA_BLOB ap_rep, ap_rep_wrapped, response;
151 auth_serversupplied_info *server_info = NULL;
152 ADS_STRUCT *ads;
153 uint8 session_key[16];
154 uint8 tok_id[2];
155 BOOL foreign = False;
156 DATA_BLOB nullblob = data_blob(NULL, 0);
158 ZERO_STRUCT(ticket);
159 ZERO_STRUCT(auth_data);
160 ZERO_STRUCT(ap_rep);
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 ads = ads_init_simple();
170 if (!ads) {
171 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
174 ads->auth.realm = strdup(lp_realm());
176 ret = ads_verify_ticket(ads, &ticket, &client, &auth_data, &ap_rep, session_key);
177 if (!NT_STATUS_IS_OK(ret)) {
178 DEBUG(1,("Failed to verify incoming ticket!\n"));
179 ads_destroy(&ads);
180 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
183 data_blob_free(&auth_data);
185 DEBUG(3,("Ticket name is [%s]\n", client));
187 p = strchr_m(client, '@');
188 if (!p) {
189 DEBUG(3,("Doesn't look like a valid principal\n"));
190 ads_destroy(&ads);
191 data_blob_free(&ap_rep);
192 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
195 *p = 0;
196 if (strcasecmp(p+1, ads->auth.realm) != 0) {
197 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
198 if (!lp_allow_trusted_domains()) {
199 data_blob_free(&ap_rep);
200 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
202 foreign = True;
205 /* this gives a fully qualified user name (ie. with full realm).
206 that leads to very long usernames, but what else can we do? */
207 asprintf(&user, "%s%s%s", p+1, lp_winbind_separator(), client);
209 pw = Get_Pwnam(user);
210 if (!pw && !foreign) {
211 pw = Get_Pwnam(client);
212 SAFE_FREE(user);
213 user = smb_xstrdup(client);
216 ads_destroy(&ads);
218 /* setup the string used by %U */
219 sub_set_smb_name(user);
221 reload_services(True);
223 if (!pw) {
224 DEBUG(1,("Username %s is invalid on this system\n",user));
225 data_blob_free(&ap_rep);
226 return ERROR_NT(NT_STATUS_NO_SUCH_USER);
229 if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info,pw))) {
230 DEBUG(1,("make_server_info_from_pw failed!\n"));
231 data_blob_free(&ap_rep);
232 return ERROR_NT(ret);
235 /* Copy out the session key from the AP_REQ. */
236 memcpy(server_info->session_key, session_key, sizeof(session_key));
238 /* register_vuid keeps the server info */
239 sess_vuid = register_vuid(server_info, nullblob, user);
241 free(user);
243 if (sess_vuid == -1) {
244 ret = NT_STATUS_LOGON_FAILURE;
245 } else {
246 set_message(outbuf,4,0,True);
247 SSVAL(outbuf, smb_vwv3, 0);
249 if (server_info->guest) {
250 SSVAL(outbuf,smb_vwv2,1);
253 SSVAL(outbuf, smb_uid, sess_vuid);
255 if (!server_info->guest) {
256 /* We need to start the signing engine
257 * here but a W2K client sends the old
258 * "BSRSPYL " signature instead of the
259 * correct one. Subsequent packets will
260 * be correct.
262 srv_check_sign_mac(inbuf);
266 /* wrap that up in a nice GSS-API wrapping */
267 if (NT_STATUS_IS_OK(ret)) {
268 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
269 } else {
270 ap_rep_wrapped = data_blob(NULL, 0);
272 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
273 reply_sesssetup_blob(conn, outbuf, response, ret);
275 data_blob_free(&ap_rep);
276 data_blob_free(&ap_rep_wrapped);
277 data_blob_free(&response);
279 return -1; /* already replied */
281 #endif
283 /****************************************************************************
284 Send a session setup reply, wrapped in SPNEGO.
285 Get vuid and check first.
286 End the NTLMSSP exchange context if we are OK/complete fail
287 ***************************************************************************/
289 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
290 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
291 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status)
293 BOOL ret;
294 DATA_BLOB response;
295 struct auth_serversupplied_info *server_info = NULL;
297 if (NT_STATUS_IS_OK(nt_status)) {
298 server_info = (*auth_ntlmssp_state)->server_info;
299 } else {
300 nt_status = do_map_to_guest(nt_status,
301 &server_info,
302 (*auth_ntlmssp_state)->ntlmssp_state->user,
303 (*auth_ntlmssp_state)->ntlmssp_state->domain);
306 if (NT_STATUS_IS_OK(nt_status)) {
307 int sess_vuid;
308 DATA_BLOB nullblob = data_blob(NULL, 0);
310 /* register_vuid keeps the server info */
311 sess_vuid = register_vuid(server_info, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
312 (*auth_ntlmssp_state)->server_info = NULL;
314 if (sess_vuid == -1) {
315 nt_status = NT_STATUS_LOGON_FAILURE;
316 } else {
318 set_message(outbuf,4,0,True);
319 SSVAL(outbuf, smb_vwv3, 0);
321 if (server_info->guest) {
322 SSVAL(outbuf,smb_vwv2,1);
325 SSVAL(outbuf,smb_uid,sess_vuid);
327 if (!server_info->guest) {
328 /* We need to start the signing engine
329 * here but a W2K client sends the old
330 * "BSRSPYL " signature instead of the
331 * correct one. Subsequent packets will
332 * be correct.
334 srv_check_sign_mac(inbuf);
339 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
340 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
341 data_blob_free(&response);
343 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
344 and the other end, that we are not finished yet. */
346 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
347 auth_ntlmssp_end(auth_ntlmssp_state);
350 return ret;
353 /****************************************************************************
354 Reply to a session setup spnego negotiate packet.
355 ****************************************************************************/
357 static int reply_spnego_negotiate(connection_struct *conn,
358 char *inbuf,
359 char *outbuf,
360 int length, int bufsize,
361 DATA_BLOB blob1)
363 char *OIDs[ASN1_MAX_OIDS];
364 DATA_BLOB secblob;
365 int i;
366 DATA_BLOB chal;
367 BOOL got_kerberos = False;
368 NTSTATUS nt_status;
370 /* parse out the OIDs and the first sec blob */
371 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
372 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
375 /* only look at the first OID for determining the mechToken --
376 accoirding to RFC2478, we should choose the one we want
377 and renegotiate, but i smell a client bug here..
379 Problem observed when connecting to a member (samba box)
380 of an AD domain as a user in a Samba domain. Samba member
381 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
382 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
383 NTLMSSP mechtoken. --jerry */
385 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
386 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
387 got_kerberos = True;
390 for (i=0;OIDs[i];i++) {
391 DEBUG(3,("Got OID %s\n", OIDs[i]));
392 free(OIDs[i]);
394 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
396 #ifdef HAVE_KRB5
397 if (got_kerberos && (SEC_ADS == lp_security())) {
398 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
399 length, bufsize, &secblob);
400 data_blob_free(&secblob);
401 return ret;
403 #endif
405 if (global_ntlmssp_state) {
406 auth_ntlmssp_end(&global_ntlmssp_state);
409 nt_status = auth_ntlmssp_start(&global_ntlmssp_state);
410 if (!NT_STATUS_IS_OK(nt_status)) {
411 return ERROR_NT(nt_status);
414 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
415 secblob, &chal);
417 data_blob_free(&secblob);
419 reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
420 &chal, nt_status);
422 data_blob_free(&chal);
424 /* already replied */
425 return -1;
428 /****************************************************************************
429 Reply to a session setup spnego auth packet.
430 ****************************************************************************/
432 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
433 int length, int bufsize,
434 DATA_BLOB blob1)
436 DATA_BLOB auth, auth_reply;
437 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
439 if (!spnego_parse_auth(blob1, &auth)) {
440 #if 0
441 file_save("auth.dat", blob1.data, blob1.length);
442 #endif
443 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
446 if (!global_ntlmssp_state) {
447 /* auth before negotiatiate? */
448 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
451 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
452 auth, &auth_reply);
454 data_blob_free(&auth);
456 reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
457 &auth_reply, nt_status);
459 data_blob_free(&auth_reply);
461 /* and tell smbd that we have already replied to this packet */
462 return -1;
465 /****************************************************************************
466 Reply to a session setup command.
467 ****************************************************************************/
469 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
470 char *outbuf,
471 int length,int bufsize)
473 uint8 *p;
474 DATA_BLOB blob1;
475 int ret;
476 size_t bufrem;
477 fstring native_os, native_lanman;
478 char *p2;
479 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
480 enum remote_arch_types ra_type = get_remote_arch();
482 DEBUG(3,("Doing spnego session setup\n"));
484 if (global_client_caps == 0) {
485 global_client_caps = IVAL(inbuf,smb_vwv10);
488 p = (uint8 *)smb_buf(inbuf);
490 if (data_blob_len == 0) {
491 /* an invalid request */
492 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
495 bufrem = smb_bufrem(inbuf, p);
496 /* pull the spnego blob */
497 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
499 #if 0
500 file_save("negotiate.dat", blob1.data, blob1.length);
501 #endif
503 p2 = inbuf + smb_vwv13 + data_blob_len;
504 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
505 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
506 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s]\n", native_os, native_lanman));
508 if ( ra_type == RA_WIN2K )
509 ra_lanman_string( native_lanman );
511 if (blob1.data[0] == ASN1_APPLICATION(0)) {
512 /* its a negTokenTarg packet */
513 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
514 data_blob_free(&blob1);
515 return ret;
518 if (blob1.data[0] == ASN1_CONTEXT(1)) {
519 /* its a auth packet */
520 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
521 data_blob_free(&blob1);
522 return ret;
525 /* what sort of packet is this? */
526 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
528 data_blob_free(&blob1);
530 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
533 /****************************************************************************
534 On new VC == 0, shutdown *all* old connections and users.
535 It seems that only NT4.x does this. At W2K and above (XP etc.).
536 a new session setup with VC==0 is ignored.
537 ****************************************************************************/
539 static void setup_new_vc_session(void)
541 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
542 #if 0
543 conn_close_all();
544 invalidate_all_vuids();
545 #endif
548 /****************************************************************************
549 Reply to a session setup command.
550 ****************************************************************************/
552 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
553 int length,int bufsize)
555 int sess_vuid;
556 int smb_bufsize;
557 DATA_BLOB lm_resp;
558 DATA_BLOB nt_resp;
559 DATA_BLOB plaintext_password;
560 fstring user;
561 fstring sub_user; /* Sainitised username for substituion */
562 fstring domain;
563 fstring native_os;
564 fstring native_lanman;
565 static BOOL done_sesssetup = False;
566 extern BOOL global_encrypted_passwords_negotiated;
567 extern BOOL global_spnego_negotiated;
568 extern int Protocol;
569 extern int max_send;
571 auth_usersupplied_info *user_info = NULL;
572 extern struct auth_context *negprot_global_auth_context;
573 auth_serversupplied_info *server_info = NULL;
575 NTSTATUS nt_status;
577 BOOL doencrypt = global_encrypted_passwords_negotiated;
579 START_PROFILE(SMBsesssetupX);
581 ZERO_STRUCT(lm_resp);
582 ZERO_STRUCT(nt_resp);
583 ZERO_STRUCT(plaintext_password);
585 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
587 /* a SPNEGO session setup has 12 command words, whereas a normal
588 NT1 session setup has 13. See the cifs spec. */
589 if (CVAL(inbuf, smb_wct) == 12 &&
590 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
591 if (!global_spnego_negotiated) {
592 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
593 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
596 if (SVAL(inbuf,smb_vwv4) == 0) {
597 setup_new_vc_session();
599 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
602 smb_bufsize = SVAL(inbuf,smb_vwv2);
604 if (Protocol < PROTOCOL_NT1) {
605 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
606 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
607 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
610 if (doencrypt) {
611 lm_resp = data_blob(smb_buf(inbuf), passlen1);
612 } else {
613 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
614 /* Ensure null termination */
615 plaintext_password.data[passlen1] = 0;
618 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
619 *domain = 0;
621 } else {
622 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
623 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
624 enum remote_arch_types ra_type = get_remote_arch();
625 char *p = smb_buf(inbuf);
627 if(global_client_caps == 0)
628 global_client_caps = IVAL(inbuf,smb_vwv11);
630 /* client_caps is used as final determination if client is NT or Win95.
631 This is needed to return the correct error codes in some
632 circumstances.
635 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
636 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
637 set_remote_arch( RA_WIN95);
641 if (!doencrypt) {
642 /* both Win95 and WinNT stuff up the password lengths for
643 non-encrypting systems. Uggh.
645 if passlen1==24 its a win95 system, and its setting the
646 password length incorrectly. Luckily it still works with the
647 default code because Win95 will null terminate the password
648 anyway
650 if passlen1>0 and passlen2>0 then maybe its a NT box and its
651 setting passlen2 to some random value which really stuffs
652 things up. we need to fix that one. */
654 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
655 passlen2 = 0;
658 /* check for nasty tricks */
659 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
660 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
663 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
664 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
667 /* Save the lanman2 password and the NT md4 password. */
669 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
670 doencrypt = False;
673 if (doencrypt) {
674 lm_resp = data_blob(p, passlen1);
675 nt_resp = data_blob(p+passlen1, passlen2);
676 } else {
677 pstring pass;
678 BOOL unic;
679 unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
680 srvstr_pull(inbuf, pass, smb_buf(inbuf),
681 sizeof(pass), unic ? passlen2 : passlen1,
682 STR_TERMINATE);
683 plaintext_password = data_blob(pass, strlen(pass)+1);
686 p += passlen1 + passlen2;
687 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
688 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
689 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
690 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
691 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
692 domain,native_os,native_lanman));
694 if ( ra_type == RA_WIN2K )
695 ra_lanman_string( native_lanman );
699 if (SVAL(inbuf,smb_vwv4) == 0) {
700 setup_new_vc_session();
703 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
705 if (*user) {
706 if (global_spnego_negotiated) {
708 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
710 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
711 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
713 fstrcpy(sub_user, user);
715 /* setup the string used by %U */
716 sub_set_smb_name(user);
717 } else {
718 fstrcpy(sub_user, lp_guestaccount());
721 sub_set_smb_name(sub_user);
723 reload_services(True);
725 if (lp_security() == SEC_SHARE) {
726 /* in share level we should ignore any passwords */
728 data_blob_free(&lm_resp);
729 data_blob_free(&nt_resp);
730 data_blob_clear_free(&plaintext_password);
732 map_username(sub_user);
733 add_session_user(sub_user);
734 /* Then force it to null for the benfit of the code below */
735 *user = 0;
738 if (!*user) {
740 nt_status = check_guest_password(&server_info);
742 } else if (doencrypt) {
743 if (!negprot_global_auth_context) {
744 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
745 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
747 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
748 lm_resp, nt_resp);
749 if (NT_STATUS_IS_OK(nt_status)) {
750 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
751 user_info,
752 &server_info);
754 } else {
755 struct auth_context *plaintext_auth_context = NULL;
756 const uint8 *chal;
757 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
758 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
760 if (!make_user_info_for_reply(&user_info,
761 user, domain, chal,
762 plaintext_password)) {
763 nt_status = NT_STATUS_NO_MEMORY;
766 if (NT_STATUS_IS_OK(nt_status)) {
767 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
768 user_info,
769 &server_info);
771 (plaintext_auth_context->free)(&plaintext_auth_context);
776 free_user_info(&user_info);
778 data_blob_free(&lm_resp);
779 data_blob_clear_free(&plaintext_password);
781 if (!NT_STATUS_IS_OK(nt_status)) {
782 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
785 if (!NT_STATUS_IS_OK(nt_status)) {
786 data_blob_free(&nt_resp);
787 return ERROR_NT(nt_status_squash(nt_status));
790 /* it's ok - setup a reply */
791 set_message(outbuf,3,0,True);
792 if (Protocol >= PROTOCOL_NT1) {
793 char *p = smb_buf( outbuf );
794 p += add_signature( outbuf, p );
795 set_message_end( outbuf, p );
796 /* perhaps grab OS version here?? */
799 if (server_info->guest) {
800 SSVAL(outbuf,smb_vwv2,1);
803 /* register the name and uid as being validated, so further connections
804 to a uid can get through without a password, on the same VC */
806 /* register_vuid keeps the server info */
807 sess_vuid = register_vuid(server_info, nt_resp, sub_user);
808 data_blob_free(&nt_resp);
810 if (sess_vuid == -1) {
811 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
814 if (!server_info->guest && !srv_check_sign_mac(inbuf)) {
815 exit_server("reply_sesssetup_and_X: bad smb signature");
818 SSVAL(outbuf,smb_uid,sess_vuid);
819 SSVAL(inbuf,smb_uid,sess_vuid);
821 if (!done_sesssetup)
822 max_send = MIN(max_send,smb_bufsize);
824 done_sesssetup = True;
826 END_PROFILE(SMBsesssetupX);
827 return chain_reply(inbuf,outbuf,length,bufsize);