Fix up the SPNEGO segfault.
[Samba.git] / source / smbd / sesssetup.c
blob8b7a29ea863c5102cb386a0f9f599d4396ff81e2
1 /*
2 Unix SMB/Netbios implementation.
3 Version 3.0
4 handle SMBsessionsetup
5 Copyright (C) Andrew Tridgell 1998-2001
6 Copyright (C) Andrew Bartlett 2001
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
25 uint32 global_client_caps = 0;
26 static struct auth_context *ntlmssp_auth_context = NULL;
29 on a logon error possibly map the error to success if "map to guest"
30 is set approriately
32 static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **server_info,
33 const char *user, const char *domain)
35 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
36 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
37 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
38 DEBUG(3,("No such user %s [%s] - using guest account\n",
39 user, domain));
40 make_server_info_guest(server_info);
41 status = NT_STATUS_OK;
45 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
46 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
47 DEBUG(3,("Registered username %s for guest access\n",user));
48 make_server_info_guest(server_info);
49 status = NT_STATUS_OK;
53 return status;
57 /****************************************************************************
58 Add the standard 'Samba' signature to the end of the session setup.
59 ****************************************************************************/
60 static void add_signature(char *outbuf)
62 char *p;
63 p = smb_buf(outbuf);
64 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
65 p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
66 p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
67 set_message_end(outbuf,p);
70 /****************************************************************************
71 Do a 'guest' logon, getting back the
72 ****************************************************************************/
73 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
75 struct auth_context *auth_context;
76 auth_usersupplied_info *user_info = NULL;
78 NTSTATUS nt_status;
79 unsigned char chal[8];
81 ZERO_STRUCT(chal);
83 DEBUG(3,("Got anonymous request\n"));
85 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) {
86 return nt_status;
89 if (!make_user_info_guest(&user_info)) {
90 auth_context->free(&auth_context);
91 return NT_STATUS_NO_MEMORY;
94 nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info);
95 auth_context->free(&auth_context);
96 free_user_info(&user_info);
97 return nt_status;
101 #ifdef HAVE_KRB5
102 /****************************************************************************
103 reply to a session setup spnego negotiate packet for kerberos
104 ****************************************************************************/
105 static int reply_spnego_kerberos(connection_struct *conn,
106 char *inbuf, char *outbuf,
107 int length, int bufsize,
108 DATA_BLOB *secblob)
110 DATA_BLOB ticket;
111 char *client, *p;
112 const struct passwd *pw;
113 char *user;
114 int sess_vuid;
115 NTSTATUS ret;
116 DATA_BLOB auth_data;
117 auth_serversupplied_info *server_info = NULL;
118 ADS_STRUCT *ads;
120 if (!spnego_parse_krb5_wrap(*secblob, &ticket)) {
121 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
124 ads = ads_init(NULL, NULL, NULL, NULL);
126 ret = ads_verify_ticket(ads, &ticket, &client, &auth_data);
127 if (!NT_STATUS_IS_OK(ret)) {
128 DEBUG(1,("Failed to verify incoming ticket!\n"));
129 ads_destroy(&ads);
130 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
133 DEBUG(3,("Ticket name is [%s]\n", client));
135 p = strchr_m(client, '@');
136 if (!p) {
137 DEBUG(3,("Doesn't look like a valid principal\n"));
138 ads_destroy(&ads);
139 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
142 *p = 0;
143 if (strcasecmp(p+1, ads->realm) != 0) {
144 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
145 if (!lp_allow_trusted_domains()) {
146 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
148 /* this gives a fully qualified user name (ie. with full realm).
149 that leads to very long usernames, but what else can we do? */
150 asprintf(&user, "%s%s%s", p+1, lp_winbind_separator(), client);
151 } else {
152 user = strdup(client);
154 ads_destroy(&ads);
156 /* the password is good - let them in */
157 pw = smb_getpwnam(user,False);
158 if (!pw && !strstr(user, lp_winbind_separator())) {
159 char *user2;
160 /* try it with a winbind domain prefix */
161 asprintf(&user2, "%s%s%s", lp_workgroup(), lp_winbind_separator(), user);
162 pw = smb_getpwnam(user2,False);
163 if (pw) {
164 free(user);
165 user = user2;
169 if (!pw) {
170 DEBUG(1,("Username %s is invalid on this system\n",user));
171 return ERROR_NT(NT_STATUS_NO_SUCH_USER);
174 if (!make_server_info_pw(&server_info,pw)) {
175 DEBUG(1,("make_server_info_from_pw failed!\n"));
176 return ERROR_NT(NT_STATUS_NO_MEMORY);
179 sess_vuid = register_vuid(server_info, user);
181 free(user);
182 free_server_info(&server_info);
184 if (sess_vuid == -1) {
185 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
188 set_message(outbuf,4,0,True);
189 SSVAL(outbuf, smb_vwv3, 0);
190 add_signature(outbuf);
192 SSVAL(outbuf,smb_uid,sess_vuid);
193 SSVAL(inbuf,smb_uid,sess_vuid);
195 return chain_reply(inbuf,outbuf,length,bufsize);
197 #endif
200 /****************************************************************************
201 send a security blob via a session setup reply
202 ****************************************************************************/
203 static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
204 DATA_BLOB blob)
206 char *p;
208 set_message(outbuf,4,0,True);
210 /* we set NT_STATUS_MORE_PROCESSING_REQUIRED to tell the other end
211 that we aren't finished yet */
213 SIVAL(outbuf, smb_rcls, NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED));
214 SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
215 SSVAL(outbuf, smb_vwv3, blob.length);
216 p = smb_buf(outbuf);
217 memcpy(p, blob.data, blob.length);
218 p += blob.length;
219 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
220 p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
221 p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
222 set_message_end(outbuf,p);
224 return send_smb(smbd_server_fd(),outbuf);
227 /****************************************************************************
228 reply to a session setup spnego negotiate packet
229 ****************************************************************************/
230 static int reply_spnego_negotiate(connection_struct *conn,
231 char *inbuf,
232 char *outbuf,
233 int length, int bufsize,
234 DATA_BLOB blob1)
236 char *OIDs[ASN1_MAX_OIDS];
237 DATA_BLOB secblob;
238 int i;
239 uint32 ntlmssp_command, neg_flags;
240 DATA_BLOB sess_key, chal, spnego_chal;
241 const uint8 *cryptkey;
242 BOOL got_kerberos = False;
243 NTSTATUS nt_status;
245 /* parse out the OIDs and the first sec blob */
246 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
247 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
250 for (i=0;OIDs[i];i++) {
251 DEBUG(3,("Got OID %s\n", OIDs[i]));
252 if (strcmp(OID_KERBEROS5, OIDs[i]) == 0 ||
253 strcmp(OID_KERBEROS5_OLD, OIDs[i]) == 0) {
254 got_kerberos = True;
256 free(OIDs[i]);
258 DEBUG(3,("Got secblob of size %d\n", secblob.length));
260 #ifdef HAVE_KRB5
261 if (got_kerberos) {
262 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
263 length, bufsize, &secblob);
264 data_blob_free(&secblob);
265 return ret;
267 #endif
269 /* parse the NTLMSSP packet */
270 #if 0
271 file_save("secblob.dat", secblob.data, secblob.length);
272 #endif
274 if (!msrpc_parse(&secblob, "CddB",
275 "NTLMSSP",
276 &ntlmssp_command,
277 &neg_flags,
278 &sess_key)) {
279 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
282 data_blob_free(&secblob);
283 data_blob_free(&sess_key);
285 if (ntlmssp_command != NTLMSSP_NEGOTIATE) {
286 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
289 DEBUG(3,("Got neg_flags=%08x\n", neg_flags));
291 if (ntlmssp_auth_context) {
292 ntlmssp_auth_context->free(&ntlmssp_auth_context);
295 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&ntlmssp_auth_context))) {
296 return ERROR_NT(nt_status);
299 cryptkey = ntlmssp_auth_context->get_ntlm_challenge(ntlmssp_auth_context);
301 /* Give them the challenge. For now, ignore neg_flags and just
302 return the flags we want. Obviously this is not correct */
304 neg_flags = NTLMSSP_NEGOTIATE_UNICODE |
305 NTLMSSP_NEGOTIATE_LM_KEY |
306 NTLMSSP_NEGOTIATE_NTLM;
308 msrpc_gen(&chal, "Cddddbdddd",
309 "NTLMSSP",
310 NTLMSSP_CHALLENGE,
312 0x30, /* ?? */
313 neg_flags,
314 cryptkey, sizeof(cryptkey),
315 0, 0, 0,
316 0x3000); /* ?? */
318 if (!spnego_gen_challenge(&spnego_chal, &chal, &chal)) {
319 DEBUG(3,("Failed to generate challenge\n"));
320 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
323 /* now tell the client to send the auth packet */
324 reply_sesssetup_blob(conn, outbuf, spnego_chal);
326 data_blob_free(&chal);
327 data_blob_free(&spnego_chal);
329 /* and tell smbd that we have already replied to this packet */
330 return -1;
334 /****************************************************************************
335 reply to a session setup spnego auth packet
336 ****************************************************************************/
337 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
338 int length, int bufsize,
339 DATA_BLOB blob1)
341 DATA_BLOB auth;
342 char *workgroup = NULL, *user = NULL, *machine = NULL;
343 DATA_BLOB lmhash, nthash, sess_key;
344 DATA_BLOB plaintext_password = data_blob(NULL, 0);
345 uint32 ntlmssp_command, neg_flags;
346 NTSTATUS nt_status;
347 int sess_vuid;
348 BOOL as_guest;
350 auth_usersupplied_info *user_info = NULL;
351 auth_serversupplied_info *server_info = NULL;
353 if (!spnego_parse_auth(blob1, &auth)) {
354 #if 0
355 file_save("auth.dat", blob1.data, blob1.length);
356 #endif
357 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
360 /* now the NTLMSSP encoded auth hashes */
361 if (!msrpc_parse(&auth, "CdBBUUUBd",
362 "NTLMSSP",
363 &ntlmssp_command,
364 &lmhash,
365 &nthash,
366 &workgroup,
367 &user,
368 &machine,
369 &sess_key,
370 &neg_flags)) {
371 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
374 data_blob_free(&auth);
375 data_blob_free(&sess_key);
377 DEBUG(3,("Got user=[%s] workgroup=[%s] machine=[%s] len1=%d len2=%d\n",
378 user, workgroup, machine, lmhash.length, nthash.length));
380 #if 0
381 file_save("nthash1.dat", nthash.data, nthash.length);
382 file_save("lmhash1.dat", lmhash.data, lmhash.length);
383 #endif
385 if (!make_user_info_map(&user_info,
386 user, workgroup,
387 machine,
388 lmhash, nthash,
389 plaintext_password,
390 neg_flags, True)) {
391 return ERROR_NT(NT_STATUS_NO_MEMORY);
394 nt_status = ntlmssp_auth_context->check_ntlm_password(ntlmssp_auth_context, user_info, &server_info);
396 if (!NT_STATUS_IS_OK(nt_status)) {
397 nt_status = do_map_to_guest(nt_status, &server_info, user, workgroup);
400 SAFE_FREE(workgroup);
401 SAFE_FREE(machine);
403 ntlmssp_auth_context->free(&ntlmssp_auth_context);
405 free_user_info(&user_info);
407 data_blob_free(&lmhash);
409 data_blob_free(&nthash);
411 if (!NT_STATUS_IS_OK(nt_status)) {
412 SAFE_FREE(user);
413 return ERROR_NT(nt_status_squash(nt_status));
416 as_guest = server_info->guest;
418 sess_vuid = register_vuid(server_info, user);
419 free_server_info(&server_info);
421 SAFE_FREE(user);
423 if (sess_vuid == -1) {
424 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
427 set_message(outbuf,4,0,True);
428 SSVAL(outbuf, smb_vwv3, 0);
430 if (as_guest) {
431 SSVAL(outbuf,smb_vwv2,1);
434 add_signature(outbuf);
436 SSVAL(outbuf,smb_uid,sess_vuid);
437 SSVAL(inbuf,smb_uid,sess_vuid);
439 return chain_reply(inbuf,outbuf,length,bufsize);
443 /****************************************************************************
444 reply to a session setup spnego anonymous packet
445 ****************************************************************************/
446 static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *outbuf,
447 int length, int bufsize)
449 int sess_vuid;
450 auth_serversupplied_info *server_info = NULL;
451 NTSTATUS nt_status;
453 nt_status = check_guest_password(&server_info);
455 if (!NT_STATUS_IS_OK(nt_status)) {
456 return ERROR_NT(nt_status_squash(nt_status));
459 sess_vuid = register_vuid(server_info, lp_guestaccount());
461 free_server_info(&server_info);
463 if (sess_vuid == -1) {
464 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
467 set_message(outbuf,4,0,True);
468 SSVAL(outbuf, smb_vwv3, 0);
469 add_signature(outbuf);
471 SSVAL(outbuf,smb_uid,sess_vuid);
472 SSVAL(inbuf,smb_uid,sess_vuid);
474 return chain_reply(inbuf,outbuf,length,bufsize);
478 /****************************************************************************
479 reply to a session setup command
480 ****************************************************************************/
481 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,char *outbuf,
482 int length,int bufsize)
484 uint8 *p;
485 DATA_BLOB blob1;
486 int ret;
488 DEBUG(3,("Doing spnego session setup\n"));
490 if (global_client_caps == 0) {
491 global_client_caps = IVAL(inbuf,smb_vwv10);
494 p = (uint8 *)smb_buf(inbuf);
496 if (SVAL(inbuf, smb_vwv7) == 0) {
497 /* an anonymous request */
498 return reply_spnego_anonymous(conn, inbuf, outbuf, length, bufsize);
501 /* pull the spnego blob */
502 blob1 = data_blob(p, SVAL(inbuf, smb_vwv7));
504 #if 0
505 file_save("negotiate.dat", blob1.data, blob1.length);
506 #endif
508 if (blob1.data[0] == ASN1_APPLICATION(0)) {
509 /* its a negTokenTarg packet */
510 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
511 data_blob_free(&blob1);
512 return ret;
515 if (blob1.data[0] == ASN1_CONTEXT(1)) {
516 /* its a auth packet */
517 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
518 data_blob_free(&blob1);
519 return ret;
522 /* what sort of packet is this? */
523 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
525 data_blob_free(&blob1);
527 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
531 /****************************************************************************
532 reply to a session setup command
533 ****************************************************************************/
534 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
535 int length,int bufsize)
537 int sess_vuid;
538 int smb_bufsize;
539 DATA_BLOB lm_resp;
540 DATA_BLOB nt_resp;
541 DATA_BLOB plaintext_password;
542 pstring user;
543 pstring sub_user; /* Sainitised username for substituion */
544 fstring domain;
545 fstring native_os;
546 fstring native_lanman;
547 static BOOL done_sesssetup = False;
548 extern BOOL global_encrypted_passwords_negotiated;
549 extern BOOL global_spnego_negotiated;
550 extern int Protocol;
551 extern fstring remote_machine;
552 extern userdom_struct current_user_info;
553 extern int max_send;
555 auth_usersupplied_info *user_info = NULL;
556 extern struct auth_context *negprot_global_auth_context;
557 auth_serversupplied_info *server_info = NULL;
559 NTSTATUS nt_status;
561 BOOL doencrypt = global_encrypted_passwords_negotiated;
563 START_PROFILE(SMBsesssetupX);
565 ZERO_STRUCT(lm_resp);
566 ZERO_STRUCT(nt_resp);
567 ZERO_STRUCT(plaintext_password);
569 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
571 /* a SPNEGO session setup has 12 command words, whereas a normal
572 NT1 session setup has 13. See the cifs spec. */
573 if (CVAL(inbuf, smb_wct) == 12 &&
574 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
575 if (!global_spnego_negotiated) {
576 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
577 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
580 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
583 smb_bufsize = SVAL(inbuf,smb_vwv2);
585 if (Protocol < PROTOCOL_NT1) {
586 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
587 if (passlen1 > MAX_PASS_LEN) {
588 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
591 if (doencrypt) {
592 lm_resp = data_blob(smb_buf(inbuf), passlen1);
593 } else {
594 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
595 /* Ensure null termination */
596 plaintext_password.data[passlen1] = 0;
599 srvstr_pull(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), -1, STR_TERMINATE);
600 *domain = 0;
602 } else {
603 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
604 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
605 enum remote_arch_types ra_type = get_remote_arch();
606 char *p = smb_buf(inbuf);
608 if(global_client_caps == 0)
609 global_client_caps = IVAL(inbuf,smb_vwv11);
611 /* client_caps is used as final determination if client is NT or Win95.
612 This is needed to return the correct error codes in some
613 circumstances.
616 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
617 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
618 set_remote_arch( RA_WIN95);
622 if (passlen1 > MAX_PASS_LEN) {
623 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
626 passlen1 = MIN(passlen1, MAX_PASS_LEN);
627 passlen2 = MIN(passlen2, MAX_PASS_LEN);
629 if (!doencrypt) {
630 /* both Win95 and WinNT stuff up the password lengths for
631 non-encrypting systems. Uggh.
633 if passlen1==24 its a win95 system, and its setting the
634 password length incorrectly. Luckily it still works with the
635 default code because Win95 will null terminate the password
636 anyway
638 if passlen1>0 and passlen2>0 then maybe its a NT box and its
639 setting passlen2 to some random value which really stuffs
640 things up. we need to fix that one. */
642 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
643 passlen2 = 0;
646 /* Save the lanman2 password and the NT md4 password. */
648 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
649 doencrypt = False;
652 if (doencrypt) {
653 lm_resp = data_blob(p, passlen1);
654 nt_resp = data_blob(p+passlen1, passlen2);
655 } else {
656 plaintext_password = data_blob(p, passlen1+1);
657 /* Ensure null termination */
658 plaintext_password.data[passlen1] = 0;
661 p += passlen1 + passlen2;
662 p += srvstr_pull(inbuf, user, p, sizeof(user), -1,
663 STR_TERMINATE);
664 p += srvstr_pull(inbuf, domain, p, sizeof(domain),
665 -1, STR_TERMINATE);
666 p += srvstr_pull(inbuf, native_os, p, sizeof(native_os),
667 -1, STR_TERMINATE);
668 p += srvstr_pull(inbuf, native_lanman, p, sizeof(native_lanman),
669 -1, STR_TERMINATE);
670 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
671 domain,native_os,native_lanman));
674 /* don't allow for weird usernames or domains */
675 alpha_strcpy(user, user, ". _-$", sizeof(user));
676 alpha_strcpy(domain, domain, ". _-", sizeof(domain));
677 if (strstr(user, "..") || strstr(domain,"..")) {
678 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
681 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, remote_machine));
683 if (*user) {
684 pstrcpy(sub_user, user);
685 } else {
686 pstrcpy(sub_user, lp_guestaccount());
689 pstrcpy(current_user_info.smb_name,sub_user);
691 reload_services(True);
693 if (lp_security() == SEC_SHARE) {
694 /* in share level we should ignore any passwords */
696 data_blob_free(&lm_resp);
697 data_blob_free(&nt_resp);
698 data_blob_clear_free(&plaintext_password);
700 map_username(sub_user);
701 add_session_user(sub_user);
702 /* Then force it to null for the benfit of the code below */
703 *user = 0;
706 if (!*user) {
707 if (global_spnego_negotiated) {
709 /* This has to be here, becouse this is a perfectly valid behaviour for guest logons :-( */
711 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
712 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
715 nt_status = check_guest_password(&server_info);
717 } else if (doencrypt) {
718 if (!make_user_info_for_reply_enc(&user_info,
719 user, domain,
720 lm_resp, nt_resp)) {
721 nt_status = NT_STATUS_NO_MEMORY;
722 } else {
723 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
724 user_info,
725 &server_info);
727 } else {
728 struct auth_context *plaintext_auth_context = NULL;
729 const uint8 *chal;
730 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
731 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
733 if (!make_user_info_for_reply(&user_info,
734 user, domain, chal,
735 plaintext_password)) {
736 nt_status = NT_STATUS_NO_MEMORY;
739 if (NT_STATUS_IS_OK(nt_status)) {
740 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
741 user_info,
742 &server_info);
744 plaintext_auth_context->free(&plaintext_auth_context);
749 free_user_info(&user_info);
751 data_blob_free(&lm_resp);
752 data_blob_free(&nt_resp);
753 data_blob_clear_free(&plaintext_password);
755 if (!NT_STATUS_IS_OK(nt_status)) {
756 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
759 if (!NT_STATUS_IS_OK(nt_status)) {
760 return ERROR_NT(nt_status_squash(nt_status));
763 /* it's ok - setup a reply */
764 if (Protocol < PROTOCOL_NT1) {
765 set_message(outbuf,3,0,True);
766 } else {
767 set_message(outbuf,3,0,True);
768 add_signature(outbuf);
769 /* perhaps grab OS version here?? */
772 if (server_info->guest) {
773 SSVAL(outbuf,smb_vwv2,1);
774 } else {
775 const char *home_dir = pdb_get_homedir(server_info->sam_account);
776 const char *username = pdb_get_username(server_info->sam_account);
777 if ((home_dir && *home_dir)
778 && (lp_servicenumber(username) < 0)) {
779 add_home_service(username, home_dir);
783 /* register the name and uid as being validated, so further connections
784 to a uid can get through without a password, on the same VC */
786 sess_vuid = register_vuid(server_info, sub_user);
788 free_server_info(&server_info);
790 if (sess_vuid == -1) {
791 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
795 SSVAL(outbuf,smb_uid,sess_vuid);
796 SSVAL(inbuf,smb_uid,sess_vuid);
798 if (!done_sesssetup)
799 max_send = MIN(max_send,smb_bufsize);
801 done_sesssetup = True;
803 END_PROFILE(SMBsesssetupX);
804 return chain_reply(inbuf,outbuf,length,bufsize);