Make sure we don't clobber the stack when response consists of the empty
[Samba/gebeck_regimport.git] / source3 / smbd / sesssetup.c
blobc66ccfd8ebdeb6bb5d18629a4f02d034c36ea46a
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", SAMBA_VERSION_STRING);
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, *domain;
145 fstring netbios_domain_name;
146 const struct passwd *pw;
147 char *user;
148 int sess_vuid;
149 NTSTATUS ret;
150 DATA_BLOB auth_data;
151 DATA_BLOB ap_rep, ap_rep_wrapped, response;
152 auth_serversupplied_info *server_info = NULL;
153 DATA_BLOB session_key;
154 uint8 tok_id[2];
155 BOOL foreign = False;
156 DATA_BLOB nullblob = data_blob(NULL, 0);
158 ZERO_STRUCT(ticket);
159 ZERO_STRUCT(auth_data);
160 ZERO_STRUCT(ap_rep);
161 ZERO_STRUCT(ap_rep_wrapped);
162 ZERO_STRUCT(response);
164 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
165 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
168 ret = ads_verify_ticket(lp_realm(), &ticket, &client, &auth_data, &ap_rep, &session_key);
170 data_blob_free(&ticket);
172 if (!NT_STATUS_IS_OK(ret)) {
173 DEBUG(1,("Failed to verify incoming ticket!\n"));
174 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
177 data_blob_free(&auth_data);
179 DEBUG(3,("Ticket name is [%s]\n", client));
181 p = strchr_m(client, '@');
182 if (!p) {
183 DEBUG(3,("Doesn't look like a valid principal\n"));
184 data_blob_free(&ap_rep);
185 SAFE_FREE(client);
186 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
189 *p = 0;
190 if (!strequal(p+1, lp_realm())) {
191 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
192 if (!lp_allow_trusted_domains()) {
193 data_blob_free(&ap_rep);
194 SAFE_FREE(client);
195 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
197 foreign = True;
200 /* this gives a fully qualified user name (ie. with full realm).
201 that leads to very long usernames, but what else can we do? */
203 domain = p+1;
206 /* If we have winbind running, we can (and must) shorten the
207 username by using the short netbios name. Otherwise we will
208 have inconsistent user names. With Kerberos, we get the
209 fully qualified realm, with ntlmssp we get the short
210 name. And even w2k3 does use ntlmssp if you for example
211 connect to an ip address. */
213 struct winbindd_request wb_request;
214 struct winbindd_response wb_response;
215 NSS_STATUS wb_result;
217 ZERO_STRUCT(wb_request);
218 ZERO_STRUCT(wb_response);
220 DEBUG(10, ("Mapping [%s] to short name\n", domain));
222 fstrcpy(wb_request.domain_name, domain);
224 wb_result = winbindd_request(WINBINDD_DOMAIN_INFO,
225 &wb_request, &wb_response);
227 if (wb_result == NSS_STATUS_SUCCESS) {
229 fstrcpy(netbios_domain_name,
230 wb_response.data.domain_info.name);
231 domain = netbios_domain_name;
233 DEBUG(10, ("Mapped to [%s]\n", domain));
234 } else {
235 DEBUG(3, ("Could not find short name -- winbind "
236 "not running?\n"));
240 asprintf(&user, "%s%c%s", domain, *lp_winbind_separator(), client);
242 pw = smb_getpwnam( user );
244 if (!pw) {
245 DEBUG(1,("Username %s is invalid on this system\n",user));
246 SAFE_FREE(user);
247 SAFE_FREE(client);
248 data_blob_free(&ap_rep);
249 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
252 /* setup the string used by %U */
254 sub_set_smb_name(pw->pw_name);
255 reload_services(True);
257 if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info,pw))) {
258 DEBUG(1,("make_server_info_from_pw failed!\n"));
259 SAFE_FREE(user);
260 SAFE_FREE(client);
261 data_blob_free(&ap_rep);
262 return ERROR_NT(ret);
265 /* make_server_info_pw does not set the domain. Without this we end up
266 * with the local netbios name in substitutions for %D. */
268 if (server_info->sam_account != NULL) {
269 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
272 /* register_vuid keeps the server info */
273 sess_vuid = register_vuid(server_info, session_key, nullblob, client);
275 SAFE_FREE(user);
276 SAFE_FREE(client);
278 if (sess_vuid == -1) {
279 ret = NT_STATUS_LOGON_FAILURE;
280 } else {
281 set_message(outbuf,4,0,True);
282 SSVAL(outbuf, smb_vwv3, 0);
284 if (server_info->guest) {
285 SSVAL(outbuf,smb_vwv2,1);
288 SSVAL(outbuf, smb_uid, sess_vuid);
290 if (!server_info->guest && !srv_signing_started()) {
291 /* We need to start the signing engine
292 * here but a W2K client sends the old
293 * "BSRSPYL " signature instead of the
294 * correct one. Subsequent packets will
295 * be correct.
297 srv_check_sign_mac(inbuf, False);
301 /* wrap that up in a nice GSS-API wrapping */
302 if (NT_STATUS_IS_OK(ret)) {
303 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
304 } else {
305 ap_rep_wrapped = data_blob(NULL, 0);
307 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
308 reply_sesssetup_blob(conn, outbuf, response, ret);
310 data_blob_free(&ap_rep);
311 data_blob_free(&ap_rep_wrapped);
312 data_blob_free(&response);
314 return -1; /* already replied */
316 #endif
318 /****************************************************************************
319 Send a session setup reply, wrapped in SPNEGO.
320 Get vuid and check first.
321 End the NTLMSSP exchange context if we are OK/complete fail
322 ***************************************************************************/
324 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
325 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
326 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status)
328 BOOL ret;
329 DATA_BLOB response;
330 struct auth_serversupplied_info *server_info = NULL;
332 if (NT_STATUS_IS_OK(nt_status)) {
333 server_info = (*auth_ntlmssp_state)->server_info;
334 } else {
335 nt_status = do_map_to_guest(nt_status,
336 &server_info,
337 (*auth_ntlmssp_state)->ntlmssp_state->user,
338 (*auth_ntlmssp_state)->ntlmssp_state->domain);
341 if (NT_STATUS_IS_OK(nt_status)) {
342 int sess_vuid;
343 DATA_BLOB nullblob = data_blob(NULL, 0);
344 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
346 /* register_vuid keeps the server info */
347 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
348 (*auth_ntlmssp_state)->server_info = NULL;
350 if (sess_vuid == -1) {
351 nt_status = NT_STATUS_LOGON_FAILURE;
352 } else {
354 set_message(outbuf,4,0,True);
355 SSVAL(outbuf, smb_vwv3, 0);
357 if (server_info->guest) {
358 SSVAL(outbuf,smb_vwv2,1);
361 SSVAL(outbuf,smb_uid,sess_vuid);
363 if (!server_info->guest && !srv_signing_started()) {
364 /* We need to start the signing engine
365 * here but a W2K client sends the old
366 * "BSRSPYL " signature instead of the
367 * correct one. Subsequent packets will
368 * be correct.
371 srv_check_sign_mac(inbuf, False);
376 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
377 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
378 data_blob_free(&response);
380 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
381 and the other end, that we are not finished yet. */
383 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
384 auth_ntlmssp_end(auth_ntlmssp_state);
387 return ret;
390 /****************************************************************************
391 Reply to a session setup spnego negotiate packet.
392 ****************************************************************************/
394 static int reply_spnego_negotiate(connection_struct *conn,
395 char *inbuf,
396 char *outbuf,
397 int length, int bufsize,
398 DATA_BLOB blob1)
400 char *OIDs[ASN1_MAX_OIDS];
401 DATA_BLOB secblob;
402 int i;
403 DATA_BLOB chal;
404 BOOL got_kerberos = False;
405 NTSTATUS nt_status;
407 /* parse out the OIDs and the first sec blob */
408 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
409 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
412 /* only look at the first OID for determining the mechToken --
413 accoirding to RFC2478, we should choose the one we want
414 and renegotiate, but i smell a client bug here..
416 Problem observed when connecting to a member (samba box)
417 of an AD domain as a user in a Samba domain. Samba member
418 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
419 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
420 NTLMSSP mechtoken. --jerry */
422 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
423 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
424 got_kerberos = True;
427 for (i=0;OIDs[i];i++) {
428 DEBUG(3,("Got OID %s\n", OIDs[i]));
429 free(OIDs[i]);
431 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
433 #ifdef HAVE_KRB5
434 if (got_kerberos && (SEC_ADS == lp_security())) {
435 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
436 length, bufsize, &secblob);
437 data_blob_free(&secblob);
438 return ret;
440 #endif
442 if (global_ntlmssp_state) {
443 auth_ntlmssp_end(&global_ntlmssp_state);
446 nt_status = auth_ntlmssp_start(&global_ntlmssp_state);
447 if (!NT_STATUS_IS_OK(nt_status)) {
448 return ERROR_NT(nt_status);
451 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
452 secblob, &chal);
454 data_blob_free(&secblob);
456 reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
457 &chal, nt_status);
459 data_blob_free(&chal);
461 /* already replied */
462 return -1;
465 /****************************************************************************
466 Reply to a session setup spnego auth packet.
467 ****************************************************************************/
469 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
470 int length, int bufsize,
471 DATA_BLOB blob1)
473 DATA_BLOB auth, auth_reply;
474 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
476 if (!spnego_parse_auth(blob1, &auth)) {
477 #if 0
478 file_save("auth.dat", blob1.data, blob1.length);
479 #endif
480 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
483 if (!global_ntlmssp_state) {
484 /* auth before negotiatiate? */
485 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
488 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
489 auth, &auth_reply);
491 data_blob_free(&auth);
493 reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
494 &auth_reply, nt_status);
496 data_blob_free(&auth_reply);
498 /* and tell smbd that we have already replied to this packet */
499 return -1;
502 /****************************************************************************
503 Reply to a session setup command.
504 ****************************************************************************/
506 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
507 char *outbuf,
508 int length,int bufsize)
510 uint8 *p;
511 DATA_BLOB blob1;
512 int ret;
513 size_t bufrem;
514 fstring native_os, native_lanman, primary_domain;
515 char *p2;
516 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
517 enum remote_arch_types ra_type = get_remote_arch();
519 DEBUG(3,("Doing spnego session setup\n"));
521 if (global_client_caps == 0) {
522 global_client_caps = IVAL(inbuf,smb_vwv10);
524 if (!(global_client_caps & CAP_STATUS32)) {
525 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
530 p = (uint8 *)smb_buf(inbuf);
532 if (data_blob_len == 0) {
533 /* an invalid request */
534 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
537 bufrem = smb_bufrem(inbuf, p);
538 /* pull the spnego blob */
539 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
541 #if 0
542 file_save("negotiate.dat", blob1.data, blob1.length);
543 #endif
545 p2 = inbuf + smb_vwv13 + data_blob_len;
546 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
547 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
548 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
549 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
550 native_os, native_lanman, primary_domain));
552 if ( ra_type == RA_WIN2K ) {
553 /* Windows 2003 doesn't set the native lanman string,
554 but does set primary domain which is a bug I think */
556 if ( !strlen(native_lanman) )
557 ra_lanman_string( primary_domain );
558 else
559 ra_lanman_string( native_lanman );
562 if (blob1.data[0] == ASN1_APPLICATION(0)) {
563 /* its a negTokenTarg packet */
564 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
565 data_blob_free(&blob1);
566 return ret;
569 if (blob1.data[0] == ASN1_CONTEXT(1)) {
570 /* its a auth packet */
571 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
572 data_blob_free(&blob1);
573 return ret;
576 /* what sort of packet is this? */
577 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
579 data_blob_free(&blob1);
581 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
584 /****************************************************************************
585 On new VC == 0, shutdown *all* old connections and users.
586 It seems that only NT4.x does this. At W2K and above (XP etc.).
587 a new session setup with VC==0 is ignored.
588 ****************************************************************************/
590 static void setup_new_vc_session(void)
592 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
593 #if 0
594 conn_close_all();
595 invalidate_all_vuids();
596 #endif
599 /****************************************************************************
600 Reply to a session setup command.
601 ****************************************************************************/
603 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
604 int length,int bufsize)
606 int sess_vuid;
607 int smb_bufsize;
608 DATA_BLOB lm_resp;
609 DATA_BLOB nt_resp;
610 DATA_BLOB plaintext_password;
611 fstring user;
612 fstring sub_user; /* Sainitised username for substituion */
613 fstring domain;
614 fstring native_os;
615 fstring native_lanman;
616 fstring primary_domain;
617 static BOOL done_sesssetup = False;
618 extern BOOL global_encrypted_passwords_negotiated;
619 extern BOOL global_spnego_negotiated;
620 extern int Protocol;
621 extern int max_send;
623 auth_usersupplied_info *user_info = NULL;
624 extern struct auth_context *negprot_global_auth_context;
625 auth_serversupplied_info *server_info = NULL;
627 NTSTATUS nt_status;
629 BOOL doencrypt = global_encrypted_passwords_negotiated;
631 DATA_BLOB session_key;
633 START_PROFILE(SMBsesssetupX);
635 ZERO_STRUCT(lm_resp);
636 ZERO_STRUCT(nt_resp);
637 ZERO_STRUCT(plaintext_password);
639 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
641 /* a SPNEGO session setup has 12 command words, whereas a normal
642 NT1 session setup has 13. See the cifs spec. */
643 if (CVAL(inbuf, smb_wct) == 12 &&
644 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
645 if (!global_spnego_negotiated) {
646 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
647 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
650 if (SVAL(inbuf,smb_vwv4) == 0) {
651 setup_new_vc_session();
653 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
656 smb_bufsize = SVAL(inbuf,smb_vwv2);
658 if (Protocol < PROTOCOL_NT1) {
659 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
660 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
661 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
664 if (doencrypt) {
665 lm_resp = data_blob(smb_buf(inbuf), passlen1);
666 } else {
667 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
668 /* Ensure null termination */
669 plaintext_password.data[passlen1] = 0;
672 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
673 *domain = 0;
675 } else {
676 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
677 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
678 enum remote_arch_types ra_type = get_remote_arch();
679 char *p = smb_buf(inbuf);
680 char *save_p = smb_buf(inbuf);
681 uint16 byte_count;
684 if(global_client_caps == 0) {
685 global_client_caps = IVAL(inbuf,smb_vwv11);
687 if (!(global_client_caps & CAP_STATUS32)) {
688 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
691 /* client_caps is used as final determination if client is NT or Win95.
692 This is needed to return the correct error codes in some
693 circumstances.
696 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
697 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
698 set_remote_arch( RA_WIN95);
703 if (!doencrypt) {
704 /* both Win95 and WinNT stuff up the password lengths for
705 non-encrypting systems. Uggh.
707 if passlen1==24 its a win95 system, and its setting the
708 password length incorrectly. Luckily it still works with the
709 default code because Win95 will null terminate the password
710 anyway
712 if passlen1>0 and passlen2>0 then maybe its a NT box and its
713 setting passlen2 to some random value which really stuffs
714 things up. we need to fix that one. */
716 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
717 passlen2 = 0;
720 /* check for nasty tricks */
721 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
722 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
725 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
726 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
729 /* Save the lanman2 password and the NT md4 password. */
731 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
732 doencrypt = False;
735 if (doencrypt) {
736 lm_resp = data_blob(p, passlen1);
737 nt_resp = data_blob(p+passlen1, passlen2);
738 } else {
739 pstring pass;
740 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
742 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
743 /* NT4.0 stuffs up plaintext unicode password lengths... */
744 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
745 sizeof(pass), passlen1, STR_TERMINATE);
746 } else {
747 srvstr_pull(inbuf, pass, smb_buf(inbuf),
748 sizeof(pass), unic ? passlen2 : passlen1,
749 STR_TERMINATE);
751 plaintext_password = data_blob(pass, strlen(pass)+1);
754 p += passlen1 + passlen2;
755 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
756 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
757 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
758 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
760 /* not documented or decoded by Ethereal but there is one more string
761 in the extra bytes which is the same as the PrimaryDomain when using
762 extended security. Windows NT 4 and 2003 use this string to store
763 the native lanman string. Windows 9x does not include a string here
764 at all so we have to check if we have any extra bytes left */
766 byte_count = SVAL(inbuf, smb_vwv13);
767 if ( PTR_DIFF(p, save_p) < byte_count)
768 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
769 else
770 fstrcpy( primary_domain, "null" );
772 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
773 domain, native_os, native_lanman, primary_domain));
775 if ( ra_type == RA_WIN2K ) {
776 if ( strlen(native_lanman) == 0 )
777 ra_lanman_string( primary_domain );
778 else
779 ra_lanman_string( native_lanman );
784 if (SVAL(inbuf,smb_vwv4) == 0) {
785 setup_new_vc_session();
788 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
790 if (*user) {
791 if (global_spnego_negotiated) {
793 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
795 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
796 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
798 fstrcpy(sub_user, user);
800 /* setup the string used by %U */
801 sub_set_smb_name(user);
802 } else {
803 fstrcpy(sub_user, lp_guestaccount());
806 sub_set_smb_name(sub_user);
808 reload_services(True);
810 if (lp_security() == SEC_SHARE) {
811 /* in share level we should ignore any passwords */
813 data_blob_free(&lm_resp);
814 data_blob_free(&nt_resp);
815 data_blob_clear_free(&plaintext_password);
817 map_username(sub_user);
818 add_session_user(sub_user);
819 /* Then force it to null for the benfit of the code below */
820 *user = 0;
823 if (!*user) {
825 nt_status = check_guest_password(&server_info);
827 } else if (doencrypt) {
828 if (!negprot_global_auth_context) {
829 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
830 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
832 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
833 lm_resp, nt_resp);
834 if (NT_STATUS_IS_OK(nt_status)) {
835 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
836 user_info,
837 &server_info);
839 } else {
840 struct auth_context *plaintext_auth_context = NULL;
841 const uint8 *chal;
842 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
843 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
845 if (!make_user_info_for_reply(&user_info,
846 user, domain, chal,
847 plaintext_password)) {
848 nt_status = NT_STATUS_NO_MEMORY;
851 if (NT_STATUS_IS_OK(nt_status)) {
852 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
853 user_info,
854 &server_info);
856 (plaintext_auth_context->free)(&plaintext_auth_context);
861 free_user_info(&user_info);
863 if (!NT_STATUS_IS_OK(nt_status)) {
864 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
867 if (!NT_STATUS_IS_OK(nt_status)) {
868 data_blob_free(&nt_resp);
869 data_blob_free(&lm_resp);
870 data_blob_clear_free(&plaintext_password);
871 return ERROR_NT(nt_status_squash(nt_status));
874 if (server_info->nt_session_key.data) {
875 session_key = data_blob(server_info->nt_session_key.data, server_info->nt_session_key.length);
876 } else if (server_info->lm_session_key.length >= 8 && lm_resp.length == 24) {
877 session_key = data_blob(NULL, 16);
878 SMBsesskeygen_lmv1(server_info->lm_session_key.data, lm_resp.data,
879 session_key.data);
880 } else {
881 session_key = data_blob(NULL, 0);
884 data_blob_free(&lm_resp);
885 data_blob_clear_free(&plaintext_password);
887 /* it's ok - setup a reply */
888 set_message(outbuf,3,0,True);
889 if (Protocol >= PROTOCOL_NT1) {
890 char *p = smb_buf( outbuf );
891 p += add_signature( outbuf, p );
892 set_message_end( outbuf, p );
893 /* perhaps grab OS version here?? */
896 if (server_info->guest) {
897 SSVAL(outbuf,smb_vwv2,1);
900 /* register the name and uid as being validated, so further connections
901 to a uid can get through without a password, on the same VC */
903 /* register_vuid keeps the server info */
904 sess_vuid = register_vuid(server_info, session_key, nt_resp, sub_user);
905 data_blob_free(&nt_resp);
907 if (sess_vuid == -1) {
908 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
911 if (!server_info->guest && !srv_signing_started() && !srv_check_sign_mac(inbuf, True)) {
912 exit_server("reply_sesssetup_and_X: bad smb signature");
915 SSVAL(outbuf,smb_uid,sess_vuid);
916 SSVAL(inbuf,smb_uid,sess_vuid);
918 if (!done_sesssetup)
919 max_send = MIN(max_send,smb_bufsize);
921 done_sesssetup = True;
923 END_PROFILE(SMBsesssetupX);
924 return chain_reply(inbuf,outbuf,length,bufsize);