Fairly large change to printing code.
[Samba.git] / source / smbd / sesssetup.c
blob8fb5a50697bce6328d07de206a660dc630d7a59e
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 = smb_getpwnam(user,False);
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 = smb_getpwnam(user2,False);
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 (!make_server_info_pw(&server_info,pw)) {
181 DEBUG(1,("make_server_info_from_pw failed!\n"));
182 return ERROR_NT(NT_STATUS_NO_MEMORY);
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(3,("Got neg_flags=0x%08x\n", neg_flags));
299 debug_ntlmssp_flags(neg_flags);
301 if (ntlmssp_auth_context) {
302 (ntlmssp_auth_context->free)(&ntlmssp_auth_context);
305 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&ntlmssp_auth_context))) {
306 return ERROR_NT(nt_status);
309 cryptkey = ntlmssp_auth_context->get_ntlm_challenge(ntlmssp_auth_context);
311 /* Give them the challenge. For now, ignore neg_flags and just
312 return the flags we want. Obviously this is not correct */
314 chal_flags = NTLMSSP_NEGOTIATE_UNICODE |
315 NTLMSSP_NEGOTIATE_LM_KEY |
316 NTLMSSP_NEGOTIATE_NTLM |
317 NTLMSSP_CHAL_TARGET_INFO;
320 DATA_BLOB domain_blob, struct_blob;
321 fstring dnsname, dnsdomname;
323 msrpc_gen(&domain_blob,
324 "U",
325 lp_workgroup());
327 fstrcpy(dnsdomname, lp_realm());
328 strlower(dnsdomname);
330 fstrcpy(dnsname, global_myname);
331 fstrcat(dnsname, ".");
332 fstrcat(dnsname, lp_realm());
333 strlower(dnsname);
335 msrpc_gen(&struct_blob, "aaaaa",
336 2, lp_workgroup(),
337 1, global_myname,
338 4, dnsdomname,
339 3, dnsname,
340 0, "");
342 msrpc_gen(&chal, "CdUdbddB",
343 "NTLMSSP",
344 NTLMSSP_CHALLENGE,
345 lp_workgroup(),
346 chal_flags,
347 cryptkey, 8,
348 0, 0,
349 struct_blob.data, struct_blob.length);
351 data_blob_free(&domain_blob);
352 data_blob_free(&struct_blob);
355 if (!spnego_gen_challenge(&spnego_chal, &chal, &chal)) {
356 DEBUG(3,("Failed to generate challenge\n"));
357 data_blob_free(&chal);
358 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
361 /* now tell the client to send the auth packet */
362 reply_sesssetup_blob(conn, outbuf, spnego_chal, NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED));
364 data_blob_free(&chal);
365 data_blob_free(&spnego_chal);
367 /* and tell smbd that we have already replied to this packet */
368 return -1;
372 /****************************************************************************
373 reply to a session setup spnego auth packet
374 ****************************************************************************/
375 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
376 int length, int bufsize,
377 DATA_BLOB blob1)
379 DATA_BLOB auth, response;
380 char *workgroup = NULL, *user = NULL, *machine = NULL;
381 DATA_BLOB lmhash, nthash, sess_key;
382 DATA_BLOB plaintext_password = data_blob(NULL, 0);
383 uint32 ntlmssp_command, neg_flags;
384 NTSTATUS nt_status;
385 int sess_vuid;
386 BOOL as_guest;
387 uint32 auth_flags = AUTH_FLAG_NONE;
388 auth_usersupplied_info *user_info = NULL;
389 auth_serversupplied_info *server_info = NULL;
391 /* we must have setup the auth context by now */
392 if (!ntlmssp_auth_context) {
393 DEBUG(2,("ntlmssp_auth_context is NULL in reply_spnego_auth\n"));
394 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
397 if (!spnego_parse_auth(blob1, &auth)) {
398 #if 0
399 file_save("auth.dat", blob1.data, blob1.length);
400 #endif
401 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
404 /* now the NTLMSSP encoded auth hashes */
405 if (!msrpc_parse(&auth, "CdBBUUUBd",
406 "NTLMSSP",
407 &ntlmssp_command,
408 &lmhash,
409 &nthash,
410 &workgroup,
411 &user,
412 &machine,
413 &sess_key,
414 &neg_flags)) {
415 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
418 data_blob_free(&auth);
419 data_blob_free(&sess_key);
421 DEBUG(3,("Got user=[%s] workgroup=[%s] machine=[%s] len1=%d len2=%d\n",
422 user, workgroup, machine, lmhash.length, nthash.length));
424 /* the client has given us its machine name (which we otherwise would not get on port 445).
425 we need to possibly reload smb.conf if smb.conf includes depend on the machine name */
427 set_remote_machine_name(machine);
429 reload_services(True);
431 #if 0
432 file_save("nthash1.dat", nthash.data, nthash.length);
433 file_save("lmhash1.dat", lmhash.data, lmhash.length);
434 #endif
436 if (lmhash.length) {
437 auth_flags |= AUTH_FLAG_LM_RESP;
440 if (nthash.length == 24) {
441 auth_flags |= AUTH_FLAG_NTLM_RESP;
442 } else if (nthash.length > 24) {
443 auth_flags |= AUTH_FLAG_NTLMv2_RESP;
446 if (!make_user_info_map(&user_info,
447 user, workgroup,
448 machine,
449 lmhash, nthash,
450 plaintext_password,
451 auth_flags, True)) {
452 return ERROR_NT(NT_STATUS_NO_MEMORY);
455 nt_status = ntlmssp_auth_context->check_ntlm_password(ntlmssp_auth_context, user_info, &server_info);
457 if (!NT_STATUS_IS_OK(nt_status)) {
458 nt_status = do_map_to_guest(nt_status, &server_info, user, workgroup);
461 SAFE_FREE(workgroup);
462 SAFE_FREE(machine);
464 (ntlmssp_auth_context->free)(&ntlmssp_auth_context);
466 free_user_info(&user_info);
468 data_blob_free(&lmhash);
470 data_blob_free(&nthash);
472 if (!NT_STATUS_IS_OK(nt_status)) {
473 SAFE_FREE(user);
474 return ERROR_NT(nt_status_squash(nt_status));
477 as_guest = server_info->guest;
479 sess_vuid = register_vuid(server_info, user);
480 free_server_info(&server_info);
482 SAFE_FREE(user);
484 if (sess_vuid == -1) {
485 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
488 set_message(outbuf,4,0,True);
489 SSVAL(outbuf, smb_vwv3, 0);
491 if (as_guest) {
492 SSVAL(outbuf,smb_vwv2,1);
495 add_signature(outbuf);
497 SSVAL(outbuf,smb_uid,sess_vuid);
498 SSVAL(inbuf,smb_uid,sess_vuid);
500 response = spnego_gen_auth_response();
501 reply_sesssetup_blob(conn, outbuf, response, 0);
503 /* and tell smbd that we have already replied to this packet */
504 return -1;
508 /****************************************************************************
509 reply to a session setup spnego anonymous packet
510 ****************************************************************************/
511 static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *outbuf,
512 int length, int bufsize)
514 int sess_vuid;
515 auth_serversupplied_info *server_info = NULL;
516 NTSTATUS nt_status;
518 nt_status = check_guest_password(&server_info);
520 if (!NT_STATUS_IS_OK(nt_status)) {
521 return ERROR_NT(nt_status_squash(nt_status));
524 sess_vuid = register_vuid(server_info, lp_guestaccount());
526 free_server_info(&server_info);
528 if (sess_vuid == -1) {
529 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
532 set_message(outbuf,4,0,True);
533 SSVAL(outbuf, smb_vwv3, 0);
534 add_signature(outbuf);
536 SSVAL(outbuf,smb_uid,sess_vuid);
537 SSVAL(inbuf,smb_uid,sess_vuid);
539 return chain_reply(inbuf,outbuf,length,bufsize);
543 /****************************************************************************
544 reply to a session setup command
545 ****************************************************************************/
546 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,char *outbuf,
547 int length,int bufsize)
549 uint8 *p;
550 DATA_BLOB blob1;
551 int ret;
553 DEBUG(3,("Doing spnego session setup\n"));
555 if (global_client_caps == 0) {
556 global_client_caps = IVAL(inbuf,smb_vwv10);
559 p = (uint8 *)smb_buf(inbuf);
561 if (SVAL(inbuf, smb_vwv7) == 0) {
562 /* an anonymous request */
563 return reply_spnego_anonymous(conn, inbuf, outbuf, length, bufsize);
566 /* pull the spnego blob */
567 blob1 = data_blob(p, SVAL(inbuf, smb_vwv7));
569 #if 0
570 file_save("negotiate.dat", blob1.data, blob1.length);
571 #endif
573 if (blob1.data[0] == ASN1_APPLICATION(0)) {
574 /* its a negTokenTarg packet */
575 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
576 data_blob_free(&blob1);
577 return ret;
580 if (blob1.data[0] == ASN1_CONTEXT(1)) {
581 /* its a auth packet */
582 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
583 data_blob_free(&blob1);
584 return ret;
587 /* what sort of packet is this? */
588 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
590 data_blob_free(&blob1);
592 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
596 /****************************************************************************
597 reply to a session setup command
598 ****************************************************************************/
599 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
600 int length,int bufsize)
602 int sess_vuid;
603 int smb_bufsize;
604 DATA_BLOB lm_resp;
605 DATA_BLOB nt_resp;
606 DATA_BLOB plaintext_password;
607 pstring user;
608 pstring sub_user; /* Sainitised username for substituion */
609 fstring domain;
610 fstring native_os;
611 fstring native_lanman;
612 static BOOL done_sesssetup = False;
613 extern BOOL global_encrypted_passwords_negotiated;
614 extern BOOL global_spnego_negotiated;
615 extern int Protocol;
616 extern userdom_struct current_user_info;
617 extern int max_send;
619 auth_usersupplied_info *user_info = NULL;
620 extern struct auth_context *negprot_global_auth_context;
621 auth_serversupplied_info *server_info = NULL;
623 NTSTATUS nt_status;
625 BOOL doencrypt = global_encrypted_passwords_negotiated;
627 START_PROFILE(SMBsesssetupX);
629 ZERO_STRUCT(lm_resp);
630 ZERO_STRUCT(nt_resp);
631 ZERO_STRUCT(plaintext_password);
633 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
635 /* a SPNEGO session setup has 12 command words, whereas a normal
636 NT1 session setup has 13. See the cifs spec. */
637 if (CVAL(inbuf, smb_wct) == 12 &&
638 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
639 if (!global_spnego_negotiated) {
640 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
641 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
644 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
647 smb_bufsize = SVAL(inbuf,smb_vwv2);
649 if (Protocol < PROTOCOL_NT1) {
650 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
651 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
652 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
655 if (doencrypt) {
656 lm_resp = data_blob(smb_buf(inbuf), passlen1);
657 } else {
658 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
659 /* Ensure null termination */
660 plaintext_password.data[passlen1] = 0;
663 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
664 *domain = 0;
666 } else {
667 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
668 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
669 enum remote_arch_types ra_type = get_remote_arch();
670 char *p = smb_buf(inbuf);
672 if(global_client_caps == 0)
673 global_client_caps = IVAL(inbuf,smb_vwv11);
675 /* client_caps is used as final determination if client is NT or Win95.
676 This is needed to return the correct error codes in some
677 circumstances.
680 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
681 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
682 set_remote_arch( RA_WIN95);
686 if (!doencrypt) {
687 /* both Win95 and WinNT stuff up the password lengths for
688 non-encrypting systems. Uggh.
690 if passlen1==24 its a win95 system, and its setting the
691 password length incorrectly. Luckily it still works with the
692 default code because Win95 will null terminate the password
693 anyway
695 if passlen1>0 and passlen2>0 then maybe its a NT box and its
696 setting passlen2 to some random value which really stuffs
697 things up. we need to fix that one. */
699 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
700 passlen2 = 0;
703 /* check for nasty tricks */
704 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
705 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
708 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
709 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
712 /* Save the lanman2 password and the NT md4 password. */
714 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
715 doencrypt = False;
718 if (doencrypt) {
719 lm_resp = data_blob(p, passlen1);
720 nt_resp = data_blob(p+passlen1, passlen2);
721 } else {
722 pstring pass;
723 srvstr_pull(inbuf, pass, smb_buf(inbuf),
724 sizeof(pass), passlen1, STR_TERMINATE);
725 plaintext_password = data_blob(pass, strlen(pass)+1);
728 p += passlen1 + passlen2;
729 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
730 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
731 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
732 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
733 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
734 domain,native_os,native_lanman));
737 /* don't allow for weird usernames or domains */
738 alpha_strcpy(user, user, ". _-$", sizeof(user));
739 alpha_strcpy(domain, domain, ". _-", sizeof(domain));
740 if (strstr(user, "..") || strstr(domain,"..")) {
741 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
744 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
746 if (*user) {
747 if (global_spnego_negotiated) {
749 /* This has to be here, becouse this is a perfectly valid behaviour for guest logons :-( */
751 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
752 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
754 pstrcpy(sub_user, user);
755 } else {
756 pstrcpy(sub_user, lp_guestaccount());
759 pstrcpy(current_user_info.smb_name,sub_user);
761 reload_services(True);
763 if (lp_security() == SEC_SHARE) {
764 /* in share level we should ignore any passwords */
766 data_blob_free(&lm_resp);
767 data_blob_free(&nt_resp);
768 data_blob_clear_free(&plaintext_password);
770 map_username(sub_user);
771 add_session_user(sub_user);
772 /* Then force it to null for the benfit of the code below */
773 *user = 0;
776 if (!*user) {
778 nt_status = check_guest_password(&server_info);
780 } else if (doencrypt) {
781 if (!make_user_info_for_reply_enc(&user_info,
782 user, domain,
783 lm_resp, nt_resp)) {
784 nt_status = NT_STATUS_NO_MEMORY;
785 } else {
786 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
787 user_info,
788 &server_info);
790 } else {
791 struct auth_context *plaintext_auth_context = NULL;
792 const uint8 *chal;
793 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
794 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
796 if (!make_user_info_for_reply(&user_info,
797 user, domain, chal,
798 plaintext_password)) {
799 nt_status = NT_STATUS_NO_MEMORY;
802 if (NT_STATUS_IS_OK(nt_status)) {
803 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
804 user_info,
805 &server_info);
807 (plaintext_auth_context->free)(&plaintext_auth_context);
812 free_user_info(&user_info);
814 data_blob_free(&lm_resp);
815 data_blob_free(&nt_resp);
816 data_blob_clear_free(&plaintext_password);
818 if (!NT_STATUS_IS_OK(nt_status)) {
819 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
822 if (!NT_STATUS_IS_OK(nt_status)) {
823 return ERROR_NT(nt_status_squash(nt_status));
826 /* it's ok - setup a reply */
827 if (Protocol < PROTOCOL_NT1) {
828 set_message(outbuf,3,0,True);
829 } else {
830 set_message(outbuf,3,0,True);
831 add_signature(outbuf);
832 /* perhaps grab OS version here?? */
835 if (server_info->guest) {
836 SSVAL(outbuf,smb_vwv2,1);
839 /* register the name and uid as being validated, so further connections
840 to a uid can get through without a password, on the same VC */
842 sess_vuid = register_vuid(server_info, sub_user);
844 free_server_info(&server_info);
846 if (sess_vuid == -1) {
847 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
851 SSVAL(outbuf,smb_uid,sess_vuid);
852 SSVAL(inbuf,smb_uid,sess_vuid);
854 if (!done_sesssetup)
855 max_send = MIN(max_send,smb_bufsize);
857 done_sesssetup = True;
859 END_PROFILE(SMBsesssetupX);
860 return chain_reply(inbuf,outbuf,length,bufsize);