must add one to the extra_data size to transfer the 0 string terminator.
[Samba/gebeck_regimport.git] / source3 / smbd / sesssetup.c
blobb9af7200089aba2c103afc15e505b769be9bb696
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 2002
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_simple();
126 if (!ads) {
127 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
130 ads->auth.realm = strdup(lp_realm());
132 ret = ads_verify_ticket(ads, &ticket, &client, &auth_data);
133 if (!NT_STATUS_IS_OK(ret)) {
134 DEBUG(1,("Failed to verify incoming ticket!\n"));
135 ads_destroy(&ads);
136 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
139 DEBUG(3,("Ticket name is [%s]\n", client));
141 p = strchr_m(client, '@');
142 if (!p) {
143 DEBUG(3,("Doesn't look like a valid principal\n"));
144 ads_destroy(&ads);
145 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
148 *p = 0;
149 if (strcasecmp(p+1, ads->auth.realm) != 0) {
150 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
151 if (!lp_allow_trusted_domains()) {
152 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
154 /* this gives a fully qualified user name (ie. with full realm).
155 that leads to very long usernames, but what else can we do? */
156 asprintf(&user, "%s%s%s", p+1, lp_winbind_separator(), client);
157 } else {
158 user = strdup(client);
160 ads_destroy(&ads);
162 /* the password is good - let them in */
163 pw = Get_Pwnam(user);
164 if (!pw && !strstr(user, lp_winbind_separator())) {
165 char *user2;
166 /* try it with a winbind domain prefix */
167 asprintf(&user2, "%s%s%s", lp_workgroup(), lp_winbind_separator(), user);
168 pw = Get_Pwnam(user2);
169 if (pw) {
170 free(user);
171 user = user2;
175 if (!pw) {
176 DEBUG(1,("Username %s is invalid on this system\n",user));
177 return ERROR_NT(NT_STATUS_NO_SUCH_USER);
180 if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info,pw))) {
181 DEBUG(1,("make_server_info_from_pw failed!\n"));
182 return ERROR_NT(ret);
185 sess_vuid = register_vuid(server_info, user);
187 free(user);
188 free_server_info(&server_info);
190 if (sess_vuid == -1) {
191 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
194 set_message(outbuf,4,0,True);
195 SSVAL(outbuf, smb_vwv3, 0);
196 add_signature(outbuf);
198 SSVAL(outbuf,smb_uid,sess_vuid);
199 SSVAL(inbuf,smb_uid,sess_vuid);
201 return chain_reply(inbuf,outbuf,length,bufsize);
203 #endif
206 /****************************************************************************
207 send a security blob via a session setup reply
208 ****************************************************************************/
209 static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
210 DATA_BLOB blob, uint32 errcode)
212 char *p;
214 set_message(outbuf,4,0,True);
216 /* we set NT_STATUS_MORE_PROCESSING_REQUIRED to tell the other end
217 that we aren't finished yet */
219 SIVAL(outbuf, smb_rcls, errcode);
220 SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
221 SSVAL(outbuf, smb_vwv3, blob.length);
222 p = smb_buf(outbuf);
223 memcpy(p, blob.data, blob.length);
224 p += blob.length;
225 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
226 p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
227 p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
228 set_message_end(outbuf,p);
230 return send_smb(smbd_server_fd(),outbuf);
233 /****************************************************************************
234 reply to a session setup spnego negotiate packet
235 ****************************************************************************/
236 static int reply_spnego_negotiate(connection_struct *conn,
237 char *inbuf,
238 char *outbuf,
239 int length, int bufsize,
240 DATA_BLOB blob1)
242 char *OIDs[ASN1_MAX_OIDS];
243 DATA_BLOB secblob;
244 int i;
245 uint32 ntlmssp_command, neg_flags, chal_flags;
246 DATA_BLOB chal, spnego_chal;
247 const uint8 *cryptkey;
248 BOOL got_kerberos = False;
249 NTSTATUS nt_status;
250 extern pstring global_myname;
251 char *cliname=NULL, *domname=NULL;
253 /* parse out the OIDs and the first sec blob */
254 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
255 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
258 for (i=0;OIDs[i];i++) {
259 DEBUG(3,("Got OID %s\n", OIDs[i]));
260 if (strcmp(OID_KERBEROS5, OIDs[i]) == 0 ||
261 strcmp(OID_KERBEROS5_OLD, OIDs[i]) == 0) {
262 got_kerberos = True;
264 free(OIDs[i]);
266 DEBUG(3,("Got secblob of size %d\n", secblob.length));
268 #ifdef HAVE_KRB5
269 if (got_kerberos && (SEC_ADS == lp_security())) {
270 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
271 length, bufsize, &secblob);
272 data_blob_free(&secblob);
273 return ret;
275 #endif
277 /* parse the NTLMSSP packet */
278 #if 0
279 file_save("secblob.dat", secblob.data, secblob.length);
280 #endif
282 if (!msrpc_parse(&secblob, "CddAA",
283 "NTLMSSP",
284 &ntlmssp_command,
285 &neg_flags,
286 &cliname,
287 &domname)) {
288 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
291 data_blob_free(&secblob);
293 if (ntlmssp_command != NTLMSSP_NEGOTIATE) {
294 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
297 debug_ntlmssp_flags(neg_flags);
299 if (ntlmssp_auth_context) {
300 (ntlmssp_auth_context->free)(&ntlmssp_auth_context);
303 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&ntlmssp_auth_context))) {
304 return ERROR_NT(nt_status);
307 cryptkey = ntlmssp_auth_context->get_ntlm_challenge(ntlmssp_auth_context);
309 /* Give them the challenge. For now, ignore neg_flags and just
310 return the flags we want. Obviously this is not correct */
312 chal_flags = NTLMSSP_NEGOTIATE_UNICODE |
313 NTLMSSP_NEGOTIATE_128 |
314 NTLMSSP_NEGOTIATE_NTLM |
315 NTLMSSP_CHAL_TARGET_INFO;
318 DATA_BLOB domain_blob, struct_blob;
319 fstring dnsname, dnsdomname;
321 msrpc_gen(&domain_blob,
322 "U",
323 lp_workgroup());
325 fstrcpy(dnsdomname, (SEC_ADS == lp_security())?lp_realm():"");
326 strlower(dnsdomname);
328 fstrcpy(dnsname, global_myname);
329 fstrcat(dnsname, ".");
330 fstrcat(dnsname, dnsdomname);
331 strlower(dnsname);
333 msrpc_gen(&struct_blob, "aaaaa",
334 2, lp_workgroup(),
335 1, global_myname,
336 4, dnsdomname,
337 3, dnsname,
338 0, "");
340 msrpc_gen(&chal, "CdUdbddB",
341 "NTLMSSP",
342 NTLMSSP_CHALLENGE,
343 lp_workgroup(),
344 chal_flags,
345 cryptkey, 8,
346 0, 0,
347 struct_blob.data, struct_blob.length);
349 data_blob_free(&domain_blob);
350 data_blob_free(&struct_blob);
353 if (!spnego_gen_challenge(&spnego_chal, &chal, &chal)) {
354 DEBUG(3,("Failed to generate challenge\n"));
355 data_blob_free(&chal);
356 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
359 /* now tell the client to send the auth packet */
360 reply_sesssetup_blob(conn, outbuf, spnego_chal, NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED));
362 data_blob_free(&chal);
363 data_blob_free(&spnego_chal);
365 /* and tell smbd that we have already replied to this packet */
366 return -1;
370 /****************************************************************************
371 reply to a session setup spnego auth packet
372 ****************************************************************************/
373 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
374 int length, int bufsize,
375 DATA_BLOB blob1)
377 DATA_BLOB auth, response;
378 char *workgroup = NULL, *user = NULL, *machine = NULL;
379 DATA_BLOB lmhash, nthash, sess_key;
380 DATA_BLOB plaintext_password = data_blob(NULL, 0);
381 uint32 ntlmssp_command, neg_flags;
382 NTSTATUS nt_status;
383 int sess_vuid;
384 BOOL as_guest;
385 uint32 auth_flags = AUTH_FLAG_NONE;
386 auth_usersupplied_info *user_info = NULL;
387 auth_serversupplied_info *server_info = NULL;
389 /* we must have setup the auth context by now */
390 if (!ntlmssp_auth_context) {
391 DEBUG(2,("ntlmssp_auth_context is NULL in reply_spnego_auth\n"));
392 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
395 if (!spnego_parse_auth(blob1, &auth)) {
396 #if 0
397 file_save("auth.dat", blob1.data, blob1.length);
398 #endif
399 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
402 /* now the NTLMSSP encoded auth hashes */
403 if (!msrpc_parse(&auth, "CdBBUUUBd",
404 "NTLMSSP",
405 &ntlmssp_command,
406 &lmhash,
407 &nthash,
408 &workgroup,
409 &user,
410 &machine,
411 &sess_key,
412 &neg_flags)) {
413 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
416 data_blob_free(&auth);
417 data_blob_free(&sess_key);
419 DEBUG(3,("Got user=[%s] workgroup=[%s] machine=[%s] len1=%d len2=%d\n",
420 user, workgroup, machine, lmhash.length, nthash.length));
422 /* the client has given us its machine name (which we otherwise would not get on port 445).
423 we need to possibly reload smb.conf if smb.conf includes depend on the machine name */
425 set_remote_machine_name(machine);
427 reload_services(True);
429 #if 0
430 file_save("nthash1.dat", nthash.data, nthash.length);
431 file_save("lmhash1.dat", lmhash.data, lmhash.length);
432 #endif
434 if (lmhash.length) {
435 auth_flags |= AUTH_FLAG_LM_RESP;
438 if (nthash.length == 24) {
439 auth_flags |= AUTH_FLAG_NTLM_RESP;
440 } else if (nthash.length > 24) {
441 auth_flags |= AUTH_FLAG_NTLMv2_RESP;
444 nt_status = make_user_info_map(&user_info, user, workgroup, machine,
445 lmhash, nthash, plaintext_password,
446 auth_flags, True);
448 /* it looks a bit weird, but this function returns int type... */
449 if (!NT_STATUS_IS_OK(nt_status)) {
450 return ERROR_NT(NT_STATUS_NO_MEMORY);
453 nt_status = ntlmssp_auth_context->check_ntlm_password(ntlmssp_auth_context, user_info, &server_info);
455 if (!NT_STATUS_IS_OK(nt_status)) {
456 nt_status = do_map_to_guest(nt_status, &server_info, user, workgroup);
459 SAFE_FREE(workgroup);
460 SAFE_FREE(machine);
462 (ntlmssp_auth_context->free)(&ntlmssp_auth_context);
464 free_user_info(&user_info);
466 data_blob_free(&lmhash);
468 data_blob_free(&nthash);
470 if (!NT_STATUS_IS_OK(nt_status)) {
471 SAFE_FREE(user);
472 return ERROR_NT(nt_status_squash(nt_status));
475 as_guest = server_info->guest;
477 sess_vuid = register_vuid(server_info, user);
478 free_server_info(&server_info);
480 SAFE_FREE(user);
482 if (sess_vuid == -1) {
483 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
486 set_message(outbuf,4,0,True);
487 SSVAL(outbuf, smb_vwv3, 0);
489 if (as_guest) {
490 SSVAL(outbuf,smb_vwv2,1);
493 add_signature(outbuf);
495 SSVAL(outbuf,smb_uid,sess_vuid);
496 SSVAL(inbuf,smb_uid,sess_vuid);
498 response = spnego_gen_auth_response();
499 reply_sesssetup_blob(conn, outbuf, response, 0);
501 /* and tell smbd that we have already replied to this packet */
502 return -1;
506 /****************************************************************************
507 reply to a session setup spnego anonymous packet
508 ****************************************************************************/
509 static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *outbuf,
510 int length, int bufsize)
512 int sess_vuid;
513 auth_serversupplied_info *server_info = NULL;
514 NTSTATUS nt_status;
516 nt_status = check_guest_password(&server_info);
518 if (!NT_STATUS_IS_OK(nt_status)) {
519 return ERROR_NT(nt_status_squash(nt_status));
522 sess_vuid = register_vuid(server_info, lp_guestaccount());
524 free_server_info(&server_info);
526 if (sess_vuid == -1) {
527 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
530 set_message(outbuf,4,0,True);
531 SSVAL(outbuf, smb_vwv3, 0);
532 add_signature(outbuf);
534 SSVAL(outbuf,smb_uid,sess_vuid);
535 SSVAL(inbuf,smb_uid,sess_vuid);
537 return chain_reply(inbuf,outbuf,length,bufsize);
541 /****************************************************************************
542 reply to a session setup command
543 ****************************************************************************/
544 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,char *outbuf,
545 int length,int bufsize)
547 uint8 *p;
548 DATA_BLOB blob1;
549 int ret;
551 DEBUG(3,("Doing spnego session setup\n"));
553 if (global_client_caps == 0) {
554 global_client_caps = IVAL(inbuf,smb_vwv10);
557 p = (uint8 *)smb_buf(inbuf);
559 if (SVAL(inbuf, smb_vwv7) == 0) {
560 /* an anonymous request */
561 return reply_spnego_anonymous(conn, inbuf, outbuf, length, bufsize);
564 /* pull the spnego blob */
565 blob1 = data_blob(p, SVAL(inbuf, smb_vwv7));
567 #if 0
568 file_save("negotiate.dat", blob1.data, blob1.length);
569 #endif
571 if (blob1.data[0] == ASN1_APPLICATION(0)) {
572 /* its a negTokenTarg packet */
573 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
574 data_blob_free(&blob1);
575 return ret;
578 if (blob1.data[0] == ASN1_CONTEXT(1)) {
579 /* its a auth packet */
580 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
581 data_blob_free(&blob1);
582 return ret;
585 /* what sort of packet is this? */
586 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
588 data_blob_free(&blob1);
590 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
594 /****************************************************************************
595 reply to a session setup command
596 ****************************************************************************/
597 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
598 int length,int bufsize)
600 int sess_vuid;
601 int smb_bufsize;
602 DATA_BLOB lm_resp;
603 DATA_BLOB nt_resp;
604 DATA_BLOB plaintext_password;
605 pstring user;
606 pstring sub_user; /* Sainitised username for substituion */
607 fstring domain;
608 fstring native_os;
609 fstring native_lanman;
610 static BOOL done_sesssetup = False;
611 extern BOOL global_encrypted_passwords_negotiated;
612 extern BOOL global_spnego_negotiated;
613 extern int Protocol;
614 extern userdom_struct current_user_info;
615 extern int max_send;
617 auth_usersupplied_info *user_info = NULL;
618 extern struct auth_context *negprot_global_auth_context;
619 auth_serversupplied_info *server_info = NULL;
621 NTSTATUS nt_status;
623 BOOL doencrypt = global_encrypted_passwords_negotiated;
625 START_PROFILE(SMBsesssetupX);
627 ZERO_STRUCT(lm_resp);
628 ZERO_STRUCT(nt_resp);
629 ZERO_STRUCT(plaintext_password);
631 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
633 /* a SPNEGO session setup has 12 command words, whereas a normal
634 NT1 session setup has 13. See the cifs spec. */
635 if (CVAL(inbuf, smb_wct) == 12 &&
636 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
637 if (!global_spnego_negotiated) {
638 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
639 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
642 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
645 smb_bufsize = SVAL(inbuf,smb_vwv2);
647 if (Protocol < PROTOCOL_NT1) {
648 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
649 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
650 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
653 if (doencrypt) {
654 lm_resp = data_blob(smb_buf(inbuf), passlen1);
655 } else {
656 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
657 /* Ensure null termination */
658 plaintext_password.data[passlen1] = 0;
661 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
662 *domain = 0;
664 } else {
665 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
666 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
667 enum remote_arch_types ra_type = get_remote_arch();
668 char *p = smb_buf(inbuf);
670 if(global_client_caps == 0)
671 global_client_caps = IVAL(inbuf,smb_vwv11);
673 /* client_caps is used as final determination if client is NT or Win95.
674 This is needed to return the correct error codes in some
675 circumstances.
678 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
679 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
680 set_remote_arch( RA_WIN95);
684 if (!doencrypt) {
685 /* both Win95 and WinNT stuff up the password lengths for
686 non-encrypting systems. Uggh.
688 if passlen1==24 its a win95 system, and its setting the
689 password length incorrectly. Luckily it still works with the
690 default code because Win95 will null terminate the password
691 anyway
693 if passlen1>0 and passlen2>0 then maybe its a NT box and its
694 setting passlen2 to some random value which really stuffs
695 things up. we need to fix that one. */
697 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
698 passlen2 = 0;
701 /* check for nasty tricks */
702 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
703 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
706 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
707 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
710 /* Save the lanman2 password and the NT md4 password. */
712 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
713 doencrypt = False;
716 if (doencrypt) {
717 lm_resp = data_blob(p, passlen1);
718 nt_resp = data_blob(p+passlen1, passlen2);
719 } else {
720 pstring pass;
721 srvstr_pull(inbuf, pass, smb_buf(inbuf),
722 sizeof(pass), passlen1, STR_TERMINATE);
723 plaintext_password = data_blob(pass, strlen(pass)+1);
726 p += passlen1 + passlen2;
727 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
728 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
729 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
730 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
731 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
732 domain,native_os,native_lanman));
735 /* don't allow for weird usernames or domains */
736 alpha_strcpy(user, user, ". _-$", sizeof(user));
737 alpha_strcpy(domain, domain, ". _-@", sizeof(domain));
738 if (strstr(user, "..") || strstr(domain,"..")) {
739 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
742 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
744 if (*user) {
745 if (global_spnego_negotiated) {
747 /* This has to be here, becouse this is a perfectly valid behaviour for guest logons :-( */
749 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
750 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
752 pstrcpy(sub_user, user);
753 } else {
754 pstrcpy(sub_user, lp_guestaccount());
757 pstrcpy(current_user_info.smb_name,sub_user);
759 reload_services(True);
761 if (lp_security() == SEC_SHARE) {
762 /* in share level we should ignore any passwords */
764 data_blob_free(&lm_resp);
765 data_blob_free(&nt_resp);
766 data_blob_clear_free(&plaintext_password);
768 map_username(sub_user);
769 add_session_user(sub_user);
770 /* Then force it to null for the benfit of the code below */
771 *user = 0;
774 if (!*user) {
776 nt_status = check_guest_password(&server_info);
778 } else if (doencrypt) {
779 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
780 lm_resp, nt_resp);
781 if (NT_STATUS_IS_OK(nt_status)) {
782 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
783 user_info,
784 &server_info);
786 } else {
787 struct auth_context *plaintext_auth_context = NULL;
788 const uint8 *chal;
789 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
790 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
792 if (!make_user_info_for_reply(&user_info,
793 user, domain, chal,
794 plaintext_password)) {
795 nt_status = NT_STATUS_NO_MEMORY;
798 if (NT_STATUS_IS_OK(nt_status)) {
799 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
800 user_info,
801 &server_info);
803 (plaintext_auth_context->free)(&plaintext_auth_context);
808 free_user_info(&user_info);
810 data_blob_free(&lm_resp);
811 data_blob_free(&nt_resp);
812 data_blob_clear_free(&plaintext_password);
814 if (!NT_STATUS_IS_OK(nt_status)) {
815 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
818 if (!NT_STATUS_IS_OK(nt_status)) {
819 return ERROR_NT(nt_status_squash(nt_status));
822 /* it's ok - setup a reply */
823 if (Protocol < PROTOCOL_NT1) {
824 set_message(outbuf,3,0,True);
825 } else {
826 set_message(outbuf,3,0,True);
827 add_signature(outbuf);
828 /* perhaps grab OS version here?? */
831 if (server_info->guest) {
832 SSVAL(outbuf,smb_vwv2,1);
835 /* register the name and uid as being validated, so further connections
836 to a uid can get through without a password, on the same VC */
838 sess_vuid = register_vuid(server_info, sub_user);
840 free_server_info(&server_info);
842 if (sess_vuid == -1) {
843 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
847 SSVAL(outbuf,smb_uid,sess_vuid);
848 SSVAL(inbuf,smb_uid,sess_vuid);
850 if (!done_sesssetup)
851 max_send = MIN(max_send,smb_bufsize);
853 done_sesssetup = True;
855 END_PROFILE(SMBsesssetupX);
856 return chain_reply(inbuf,outbuf,length,bufsize);