Fix memleaks.
[Samba.git] / source / smbd / sesssetup.c
blob1435c38c99d2e1bfc3c9a2f998577fbafd94e558
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 uint8 session_key[16];
153 uint8 tok_id[2];
154 BOOL foreign = False;
155 DATA_BLOB nullblob = data_blob(NULL, 0);
157 ZERO_STRUCT(ticket);
158 ZERO_STRUCT(auth_data);
159 ZERO_STRUCT(ap_rep);
160 ZERO_STRUCT(ap_rep_wrapped);
161 ZERO_STRUCT(response);
163 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
164 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
167 ret = ads_verify_ticket(lp_realm(), &ticket, &client, &auth_data, &ap_rep, session_key);
168 if (!NT_STATUS_IS_OK(ret)) {
169 DEBUG(1,("Failed to verify incoming ticket!\n"));
170 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
173 data_blob_free(&auth_data);
174 data_blob_free(&ticket);
176 DEBUG(3,("Ticket name is [%s]\n", client));
178 p = strchr_m(client, '@');
179 if (!p) {
180 DEBUG(3,("Doesn't look like a valid principal\n"));
181 data_blob_free(&ap_rep);
182 SAFE_FREE(client);
183 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
186 *p = 0;
187 if (strcasecmp(p+1, lp_realm()) != 0) {
188 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
189 if (!lp_allow_trusted_domains()) {
190 data_blob_free(&ap_rep);
191 SAFE_FREE(client);
192 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
194 foreign = True;
197 /* this gives a fully qualified user name (ie. with full realm).
198 that leads to very long usernames, but what else can we do? */
199 asprintf(&user, "%s%s%s", p+1, lp_winbind_separator(), client);
201 pw = Get_Pwnam(user);
202 if (!pw && !foreign) {
203 pw = Get_Pwnam(client);
204 SAFE_FREE(user);
205 user = smb_xstrdup(client);
208 SAFE_FREE(client);
210 /* setup the string used by %U */
211 sub_set_smb_name(user);
213 reload_services(True);
215 if (!pw) {
216 DEBUG(1,("Username %s is invalid on this system\n",user));
217 data_blob_free(&ap_rep);
218 return ERROR_NT(NT_STATUS_NO_SUCH_USER);
221 if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info,pw))) {
222 DEBUG(1,("make_server_info_from_pw failed!\n"));
223 data_blob_free(&ap_rep);
224 return ERROR_NT(ret);
227 /* Copy out the session key from the AP_REQ. */
228 memcpy(server_info->session_key, session_key, sizeof(session_key));
230 /* register_vuid keeps the server info */
231 sess_vuid = register_vuid(server_info, nullblob, user);
233 free(user);
235 if (sess_vuid == -1) {
236 ret = NT_STATUS_LOGON_FAILURE;
237 } else {
238 set_message(outbuf,4,0,True);
239 SSVAL(outbuf, smb_vwv3, 0);
241 if (server_info->guest) {
242 SSVAL(outbuf,smb_vwv2,1);
245 SSVAL(outbuf, smb_uid, sess_vuid);
247 if (!server_info->guest) {
248 /* We need to start the signing engine
249 * here but a W2K client sends the old
250 * "BSRSPYL " signature instead of the
251 * correct one. Subsequent packets will
252 * be correct.
254 srv_check_sign_mac(inbuf);
258 /* wrap that up in a nice GSS-API wrapping */
259 if (NT_STATUS_IS_OK(ret)) {
260 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
261 } else {
262 ap_rep_wrapped = data_blob(NULL, 0);
264 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
265 reply_sesssetup_blob(conn, outbuf, response, ret);
267 data_blob_free(&ap_rep);
268 data_blob_free(&ap_rep_wrapped);
269 data_blob_free(&response);
271 return -1; /* already replied */
273 #endif
275 /****************************************************************************
276 Send a session setup reply, wrapped in SPNEGO.
277 Get vuid and check first.
278 End the NTLMSSP exchange context if we are OK/complete fail
279 ***************************************************************************/
281 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
282 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
283 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status)
285 BOOL ret;
286 DATA_BLOB response;
287 struct auth_serversupplied_info *server_info = NULL;
289 if (NT_STATUS_IS_OK(nt_status)) {
290 server_info = (*auth_ntlmssp_state)->server_info;
291 } else {
292 nt_status = do_map_to_guest(nt_status,
293 &server_info,
294 (*auth_ntlmssp_state)->ntlmssp_state->user,
295 (*auth_ntlmssp_state)->ntlmssp_state->domain);
298 if (NT_STATUS_IS_OK(nt_status)) {
299 int sess_vuid;
300 DATA_BLOB nullblob = data_blob(NULL, 0);
302 /* register_vuid keeps the server info */
303 sess_vuid = register_vuid(server_info, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
304 (*auth_ntlmssp_state)->server_info = NULL;
306 if (sess_vuid == -1) {
307 nt_status = NT_STATUS_LOGON_FAILURE;
308 } else {
310 set_message(outbuf,4,0,True);
311 SSVAL(outbuf, smb_vwv3, 0);
313 if (server_info->guest) {
314 SSVAL(outbuf,smb_vwv2,1);
317 SSVAL(outbuf,smb_uid,sess_vuid);
319 if (!server_info->guest) {
320 /* We need to start the signing engine
321 * here but a W2K client sends the old
322 * "BSRSPYL " signature instead of the
323 * correct one. Subsequent packets will
324 * be correct.
326 srv_check_sign_mac(inbuf);
331 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
332 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
333 data_blob_free(&response);
335 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
336 and the other end, that we are not finished yet. */
338 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
339 auth_ntlmssp_end(auth_ntlmssp_state);
342 return ret;
345 /****************************************************************************
346 Reply to a session setup spnego negotiate packet.
347 ****************************************************************************/
349 static int reply_spnego_negotiate(connection_struct *conn,
350 char *inbuf,
351 char *outbuf,
352 int length, int bufsize,
353 DATA_BLOB blob1)
355 char *OIDs[ASN1_MAX_OIDS];
356 DATA_BLOB secblob;
357 int i;
358 DATA_BLOB chal;
359 BOOL got_kerberos = False;
360 NTSTATUS nt_status;
362 /* parse out the OIDs and the first sec blob */
363 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
364 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
367 /* only look at the first OID for determining the mechToken --
368 accoirding to RFC2478, we should choose the one we want
369 and renegotiate, but i smell a client bug here..
371 Problem observed when connecting to a member (samba box)
372 of an AD domain as a user in a Samba domain. Samba member
373 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
374 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
375 NTLMSSP mechtoken. --jerry */
377 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
378 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
379 got_kerberos = True;
382 for (i=0;OIDs[i];i++) {
383 DEBUG(3,("Got OID %s\n", OIDs[i]));
384 free(OIDs[i]);
386 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
388 #ifdef HAVE_KRB5
389 if (got_kerberos && (SEC_ADS == lp_security())) {
390 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
391 length, bufsize, &secblob);
392 data_blob_free(&secblob);
393 return ret;
395 #endif
397 if (global_ntlmssp_state) {
398 auth_ntlmssp_end(&global_ntlmssp_state);
401 nt_status = auth_ntlmssp_start(&global_ntlmssp_state);
402 if (!NT_STATUS_IS_OK(nt_status)) {
403 return ERROR_NT(nt_status);
406 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
407 secblob, &chal);
409 data_blob_free(&secblob);
411 reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
412 &chal, nt_status);
414 data_blob_free(&chal);
416 /* already replied */
417 return -1;
420 /****************************************************************************
421 Reply to a session setup spnego auth packet.
422 ****************************************************************************/
424 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
425 int length, int bufsize,
426 DATA_BLOB blob1)
428 DATA_BLOB auth, auth_reply;
429 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
431 if (!spnego_parse_auth(blob1, &auth)) {
432 #if 0
433 file_save("auth.dat", blob1.data, blob1.length);
434 #endif
435 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
438 if (!global_ntlmssp_state) {
439 /* auth before negotiatiate? */
440 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
443 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
444 auth, &auth_reply);
446 data_blob_free(&auth);
448 reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
449 &auth_reply, nt_status);
451 data_blob_free(&auth_reply);
453 /* and tell smbd that we have already replied to this packet */
454 return -1;
457 /****************************************************************************
458 Reply to a session setup command.
459 ****************************************************************************/
461 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
462 char *outbuf,
463 int length,int bufsize)
465 uint8 *p;
466 DATA_BLOB blob1;
467 int ret;
468 size_t bufrem;
469 fstring native_os, native_lanman;
470 char *p2;
471 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
472 enum remote_arch_types ra_type = get_remote_arch();
474 DEBUG(3,("Doing spnego session setup\n"));
476 if (global_client_caps == 0) {
477 global_client_caps = IVAL(inbuf,smb_vwv10);
480 p = (uint8 *)smb_buf(inbuf);
482 if (data_blob_len == 0) {
483 /* an invalid request */
484 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
487 bufrem = smb_bufrem(inbuf, p);
488 /* pull the spnego blob */
489 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
491 #if 0
492 file_save("negotiate.dat", blob1.data, blob1.length);
493 #endif
495 p2 = inbuf + smb_vwv13 + data_blob_len;
496 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
497 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
498 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s]\n", native_os, native_lanman));
500 if ( ra_type == RA_WIN2K )
501 ra_lanman_string( native_lanman );
503 if (blob1.data[0] == ASN1_APPLICATION(0)) {
504 /* its a negTokenTarg packet */
505 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
506 data_blob_free(&blob1);
507 return ret;
510 if (blob1.data[0] == ASN1_CONTEXT(1)) {
511 /* its a auth packet */
512 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
513 data_blob_free(&blob1);
514 return ret;
517 /* what sort of packet is this? */
518 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
520 data_blob_free(&blob1);
522 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
525 /****************************************************************************
526 On new VC == 0, shutdown *all* old connections and users.
527 It seems that only NT4.x does this. At W2K and above (XP etc.).
528 a new session setup with VC==0 is ignored.
529 ****************************************************************************/
531 static void setup_new_vc_session(void)
533 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
534 #if 0
535 conn_close_all();
536 invalidate_all_vuids();
537 #endif
540 /****************************************************************************
541 Reply to a session setup command.
542 ****************************************************************************/
544 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
545 int length,int bufsize)
547 int sess_vuid;
548 int smb_bufsize;
549 DATA_BLOB lm_resp;
550 DATA_BLOB nt_resp;
551 DATA_BLOB plaintext_password;
552 fstring user;
553 fstring sub_user; /* Sainitised username for substituion */
554 fstring domain;
555 fstring native_os;
556 fstring native_lanman;
557 static BOOL done_sesssetup = False;
558 extern BOOL global_encrypted_passwords_negotiated;
559 extern BOOL global_spnego_negotiated;
560 extern int Protocol;
561 extern int max_send;
563 auth_usersupplied_info *user_info = NULL;
564 extern struct auth_context *negprot_global_auth_context;
565 auth_serversupplied_info *server_info = NULL;
567 NTSTATUS nt_status;
569 BOOL doencrypt = global_encrypted_passwords_negotiated;
571 START_PROFILE(SMBsesssetupX);
573 ZERO_STRUCT(lm_resp);
574 ZERO_STRUCT(nt_resp);
575 ZERO_STRUCT(plaintext_password);
577 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
579 /* a SPNEGO session setup has 12 command words, whereas a normal
580 NT1 session setup has 13. See the cifs spec. */
581 if (CVAL(inbuf, smb_wct) == 12 &&
582 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
583 if (!global_spnego_negotiated) {
584 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
585 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
588 if (SVAL(inbuf,smb_vwv4) == 0) {
589 setup_new_vc_session();
591 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
594 smb_bufsize = SVAL(inbuf,smb_vwv2);
596 if (Protocol < PROTOCOL_NT1) {
597 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
598 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
599 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
602 if (doencrypt) {
603 lm_resp = data_blob(smb_buf(inbuf), passlen1);
604 } else {
605 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
606 /* Ensure null termination */
607 plaintext_password.data[passlen1] = 0;
610 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
611 *domain = 0;
613 } else {
614 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
615 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
616 enum remote_arch_types ra_type = get_remote_arch();
617 char *p = smb_buf(inbuf);
619 if(global_client_caps == 0)
620 global_client_caps = IVAL(inbuf,smb_vwv11);
622 /* client_caps is used as final determination if client is NT or Win95.
623 This is needed to return the correct error codes in some
624 circumstances.
627 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
628 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
629 set_remote_arch( RA_WIN95);
633 if (!doencrypt) {
634 /* both Win95 and WinNT stuff up the password lengths for
635 non-encrypting systems. Uggh.
637 if passlen1==24 its a win95 system, and its setting the
638 password length incorrectly. Luckily it still works with the
639 default code because Win95 will null terminate the password
640 anyway
642 if passlen1>0 and passlen2>0 then maybe its a NT box and its
643 setting passlen2 to some random value which really stuffs
644 things up. we need to fix that one. */
646 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
647 passlen2 = 0;
650 /* check for nasty tricks */
651 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
652 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
655 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
656 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
659 /* Save the lanman2 password and the NT md4 password. */
661 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
662 doencrypt = False;
665 if (doencrypt) {
666 lm_resp = data_blob(p, passlen1);
667 nt_resp = data_blob(p+passlen1, passlen2);
668 } else {
669 pstring pass;
670 BOOL unic;
671 unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
672 srvstr_pull(inbuf, pass, smb_buf(inbuf),
673 sizeof(pass), unic ? passlen2 : passlen1,
674 STR_TERMINATE);
675 plaintext_password = data_blob(pass, strlen(pass)+1);
678 p += passlen1 + passlen2;
679 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
680 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
681 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
682 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
683 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
684 domain,native_os,native_lanman));
686 if ( ra_type == RA_WIN2K )
687 ra_lanman_string( native_lanman );
691 if (SVAL(inbuf,smb_vwv4) == 0) {
692 setup_new_vc_session();
695 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
697 if (*user) {
698 if (global_spnego_negotiated) {
700 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
702 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
703 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
705 fstrcpy(sub_user, user);
707 /* setup the string used by %U */
708 sub_set_smb_name(user);
709 } else {
710 fstrcpy(sub_user, lp_guestaccount());
713 sub_set_smb_name(sub_user);
715 reload_services(True);
717 if (lp_security() == SEC_SHARE) {
718 /* in share level we should ignore any passwords */
720 data_blob_free(&lm_resp);
721 data_blob_free(&nt_resp);
722 data_blob_clear_free(&plaintext_password);
724 map_username(sub_user);
725 add_session_user(sub_user);
726 /* Then force it to null for the benfit of the code below */
727 *user = 0;
730 if (!*user) {
732 nt_status = check_guest_password(&server_info);
734 } else if (doencrypt) {
735 if (!negprot_global_auth_context) {
736 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
737 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
739 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
740 lm_resp, nt_resp);
741 if (NT_STATUS_IS_OK(nt_status)) {
742 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
743 user_info,
744 &server_info);
746 } else {
747 struct auth_context *plaintext_auth_context = NULL;
748 const uint8 *chal;
749 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
750 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
752 if (!make_user_info_for_reply(&user_info,
753 user, domain, chal,
754 plaintext_password)) {
755 nt_status = NT_STATUS_NO_MEMORY;
758 if (NT_STATUS_IS_OK(nt_status)) {
759 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
760 user_info,
761 &server_info);
763 (plaintext_auth_context->free)(&plaintext_auth_context);
768 free_user_info(&user_info);
770 data_blob_free(&lm_resp);
771 data_blob_clear_free(&plaintext_password);
773 if (!NT_STATUS_IS_OK(nt_status)) {
774 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
777 if (!NT_STATUS_IS_OK(nt_status)) {
778 data_blob_free(&nt_resp);
779 return ERROR_NT(nt_status_squash(nt_status));
782 /* it's ok - setup a reply */
783 set_message(outbuf,3,0,True);
784 if (Protocol >= PROTOCOL_NT1) {
785 char *p = smb_buf( outbuf );
786 p += add_signature( outbuf, p );
787 set_message_end( outbuf, p );
788 /* perhaps grab OS version here?? */
791 if (server_info->guest) {
792 SSVAL(outbuf,smb_vwv2,1);
795 /* register the name and uid as being validated, so further connections
796 to a uid can get through without a password, on the same VC */
798 /* register_vuid keeps the server info */
799 sess_vuid = register_vuid(server_info, nt_resp, sub_user);
800 data_blob_free(&nt_resp);
802 if (sess_vuid == -1) {
803 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
806 if (!server_info->guest && !srv_check_sign_mac(inbuf)) {
807 exit_server("reply_sesssetup_and_X: bad smb signature");
810 SSVAL(outbuf,smb_uid,sess_vuid);
811 SSVAL(inbuf,smb_uid,sess_vuid);
813 if (!done_sesssetup)
814 max_send = MIN(max_send,smb_bufsize);
816 done_sesssetup = True;
818 END_PROFILE(SMBsesssetupX);
819 return chain_reply(inbuf,outbuf,length,bufsize);