r15: syncing for 3.0.3pre2
[Samba.git] / source / smbd / sesssetup.c
blobb8777be6971c44d175ed455798d980e945ae4b82
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 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);
157 fstring real_username;
159 ZERO_STRUCT(ticket);
160 ZERO_STRUCT(auth_data);
161 ZERO_STRUCT(ap_rep);
162 ZERO_STRUCT(ap_rep_wrapped);
163 ZERO_STRUCT(response);
165 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
166 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
169 ret = ads_verify_ticket(lp_realm(), &ticket, &client, &auth_data, &ap_rep, &session_key);
171 data_blob_free(&ticket);
173 if (!NT_STATUS_IS_OK(ret)) {
174 DEBUG(1,("Failed to verify incoming ticket!\n"));
175 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
178 data_blob_free(&auth_data);
180 DEBUG(3,("Ticket name is [%s]\n", client));
182 p = strchr_m(client, '@');
183 if (!p) {
184 DEBUG(3,("Doesn't look like a valid principal\n"));
185 data_blob_free(&ap_rep);
186 SAFE_FREE(client);
187 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
190 *p = 0;
191 if (!strequal(p+1, lp_realm())) {
192 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
193 if (!lp_allow_trusted_domains()) {
194 data_blob_free(&ap_rep);
195 SAFE_FREE(client);
196 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
198 foreign = True;
201 /* this gives a fully qualified user name (ie. with full realm).
202 that leads to very long usernames, but what else can we do? */
204 domain = p+1;
207 /* If we have winbind running, we can (and must) shorten the
208 username by using the short netbios name. Otherwise we will
209 have inconsistent user names. With Kerberos, we get the
210 fully qualified realm, with ntlmssp we get the short
211 name. And even w2k3 does use ntlmssp if you for example
212 connect to an ip address. */
214 struct winbindd_request wb_request;
215 struct winbindd_response wb_response;
216 NSS_STATUS wb_result;
218 ZERO_STRUCT(wb_request);
219 ZERO_STRUCT(wb_response);
221 DEBUG(10, ("Mapping [%s] to short name\n", domain));
223 fstrcpy(wb_request.domain_name, domain);
225 wb_result = winbindd_request(WINBINDD_DOMAIN_INFO,
226 &wb_request, &wb_response);
228 if (wb_result == NSS_STATUS_SUCCESS) {
230 fstrcpy(netbios_domain_name,
231 wb_response.data.domain_info.name);
232 domain = netbios_domain_name;
234 DEBUG(10, ("Mapped to [%s]\n", domain));
235 } else {
236 DEBUG(3, ("Could not find short name -- winbind "
237 "not running?\n"));
241 asprintf(&user, "%s%c%s", domain, *lp_winbind_separator(), client);
243 /* lookup the passwd struct, create a new user if necessary */
245 pw = smb_getpwnam( user, real_username, True );
247 if (!pw) {
248 DEBUG(1,("Username %s is invalid on this system\n",user));
249 SAFE_FREE(user);
250 SAFE_FREE(client);
251 data_blob_free(&ap_rep);
252 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
255 /* setup the string used by %U */
257 sub_set_smb_name( real_username );
258 reload_services(True);
260 if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info, real_username, pw)))
262 DEBUG(1,("make_server_info_from_pw failed!\n"));
263 SAFE_FREE(user);
264 SAFE_FREE(client);
265 data_blob_free(&ap_rep);
266 return ERROR_NT(ret);
269 /* make_server_info_pw does not set the domain. Without this we end up
270 * with the local netbios name in substitutions for %D. */
272 if (server_info->sam_account != NULL) {
273 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
276 /* register_vuid keeps the server info */
277 sess_vuid = register_vuid(server_info, session_key, nullblob, client);
279 SAFE_FREE(user);
280 SAFE_FREE(client);
282 if (sess_vuid == -1) {
283 ret = NT_STATUS_LOGON_FAILURE;
284 } else {
285 /* current_user_info is changed on new vuid */
286 reload_services( True );
288 set_message(outbuf,4,0,True);
289 SSVAL(outbuf, smb_vwv3, 0);
291 if (server_info->guest) {
292 SSVAL(outbuf,smb_vwv2,1);
295 SSVAL(outbuf, smb_uid, sess_vuid);
297 if (!server_info->guest && !srv_signing_started()) {
298 /* We need to start the signing engine
299 * here but a W2K client sends the old
300 * "BSRSPYL " signature instead of the
301 * correct one. Subsequent packets will
302 * be correct.
304 srv_check_sign_mac(inbuf, False);
308 /* wrap that up in a nice GSS-API wrapping */
309 if (NT_STATUS_IS_OK(ret)) {
310 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
311 } else {
312 ap_rep_wrapped = data_blob(NULL, 0);
314 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
315 reply_sesssetup_blob(conn, outbuf, response, ret);
317 data_blob_free(&ap_rep);
318 data_blob_free(&ap_rep_wrapped);
319 data_blob_free(&response);
321 return -1; /* already replied */
323 #endif
325 /****************************************************************************
326 Send a session setup reply, wrapped in SPNEGO.
327 Get vuid and check first.
328 End the NTLMSSP exchange context if we are OK/complete fail
329 ***************************************************************************/
331 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
332 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
333 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status)
335 BOOL ret;
336 DATA_BLOB response;
337 struct auth_serversupplied_info *server_info = NULL;
339 if (NT_STATUS_IS_OK(nt_status)) {
340 server_info = (*auth_ntlmssp_state)->server_info;
341 } else {
342 nt_status = do_map_to_guest(nt_status,
343 &server_info,
344 (*auth_ntlmssp_state)->ntlmssp_state->user,
345 (*auth_ntlmssp_state)->ntlmssp_state->domain);
348 if (NT_STATUS_IS_OK(nt_status)) {
349 int sess_vuid;
350 DATA_BLOB nullblob = data_blob(NULL, 0);
351 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
353 /* register_vuid keeps the server info */
354 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
355 (*auth_ntlmssp_state)->server_info = NULL;
357 if (sess_vuid == -1) {
358 nt_status = NT_STATUS_LOGON_FAILURE;
359 } else {
361 /* current_user_info is changed on new vuid */
362 reload_services( True );
364 set_message(outbuf,4,0,True);
365 SSVAL(outbuf, smb_vwv3, 0);
367 if (server_info->guest) {
368 SSVAL(outbuf,smb_vwv2,1);
371 SSVAL(outbuf,smb_uid,sess_vuid);
373 if (!server_info->guest && !srv_signing_started()) {
374 /* We need to start the signing engine
375 * here but a W2K client sends the old
376 * "BSRSPYL " signature instead of the
377 * correct one. Subsequent packets will
378 * be correct.
381 srv_check_sign_mac(inbuf, False);
386 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
387 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
388 data_blob_free(&response);
390 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
391 and the other end, that we are not finished yet. */
393 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
394 auth_ntlmssp_end(auth_ntlmssp_state);
397 return ret;
400 /****************************************************************************
401 Reply to a session setup spnego negotiate packet.
402 ****************************************************************************/
404 static int reply_spnego_negotiate(connection_struct *conn,
405 char *inbuf,
406 char *outbuf,
407 int length, int bufsize,
408 DATA_BLOB blob1)
410 char *OIDs[ASN1_MAX_OIDS];
411 DATA_BLOB secblob;
412 int i;
413 DATA_BLOB chal;
414 BOOL got_kerberos = False;
415 NTSTATUS nt_status;
417 /* parse out the OIDs and the first sec blob */
418 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
419 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
422 /* only look at the first OID for determining the mechToken --
423 accoirding to RFC2478, we should choose the one we want
424 and renegotiate, but i smell a client bug here..
426 Problem observed when connecting to a member (samba box)
427 of an AD domain as a user in a Samba domain. Samba member
428 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
429 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
430 NTLMSSP mechtoken. --jerry */
432 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
433 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
434 got_kerberos = True;
437 for (i=0;OIDs[i];i++) {
438 DEBUG(3,("Got OID %s\n", OIDs[i]));
439 free(OIDs[i]);
441 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
443 #ifdef HAVE_KRB5
444 if (got_kerberos && (SEC_ADS == lp_security())) {
445 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
446 length, bufsize, &secblob);
447 data_blob_free(&secblob);
448 return ret;
450 #endif
452 if (global_ntlmssp_state) {
453 auth_ntlmssp_end(&global_ntlmssp_state);
456 nt_status = auth_ntlmssp_start(&global_ntlmssp_state);
457 if (!NT_STATUS_IS_OK(nt_status)) {
458 return ERROR_NT(nt_status);
461 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
462 secblob, &chal);
464 data_blob_free(&secblob);
466 reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
467 &chal, nt_status);
469 data_blob_free(&chal);
471 /* already replied */
472 return -1;
475 /****************************************************************************
476 Reply to a session setup spnego auth packet.
477 ****************************************************************************/
479 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
480 int length, int bufsize,
481 DATA_BLOB blob1)
483 DATA_BLOB auth, auth_reply;
484 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
486 if (!spnego_parse_auth(blob1, &auth)) {
487 #if 0
488 file_save("auth.dat", blob1.data, blob1.length);
489 #endif
490 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
493 if (!global_ntlmssp_state) {
494 /* auth before negotiatiate? */
495 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
498 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
499 auth, &auth_reply);
501 data_blob_free(&auth);
503 reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
504 &auth_reply, nt_status);
506 data_blob_free(&auth_reply);
508 /* and tell smbd that we have already replied to this packet */
509 return -1;
512 /****************************************************************************
513 Reply to a session setup command.
514 ****************************************************************************/
516 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
517 char *outbuf,
518 int length,int bufsize)
520 uint8 *p;
521 DATA_BLOB blob1;
522 int ret;
523 size_t bufrem;
524 fstring native_os, native_lanman, primary_domain;
525 char *p2;
526 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
527 enum remote_arch_types ra_type = get_remote_arch();
529 DEBUG(3,("Doing spnego session setup\n"));
531 if (global_client_caps == 0) {
532 global_client_caps = IVAL(inbuf,smb_vwv10);
534 if (!(global_client_caps & CAP_STATUS32)) {
535 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
540 p = (uint8 *)smb_buf(inbuf);
542 if (data_blob_len == 0) {
543 /* an invalid request */
544 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
547 bufrem = smb_bufrem(inbuf, p);
548 /* pull the spnego blob */
549 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
551 #if 0
552 file_save("negotiate.dat", blob1.data, blob1.length);
553 #endif
555 p2 = inbuf + smb_vwv13 + data_blob_len;
556 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
557 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
558 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
559 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
560 native_os, native_lanman, primary_domain));
562 if ( ra_type == RA_WIN2K ) {
563 /* Windows 2003 doesn't set the native lanman string,
564 but does set primary domain which is a bug I think */
566 if ( !strlen(native_lanman) )
567 ra_lanman_string( primary_domain );
568 else
569 ra_lanman_string( native_lanman );
572 if (blob1.data[0] == ASN1_APPLICATION(0)) {
573 /* its a negTokenTarg packet */
574 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
575 data_blob_free(&blob1);
576 return ret;
579 if (blob1.data[0] == ASN1_CONTEXT(1)) {
580 /* its a auth packet */
581 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
582 data_blob_free(&blob1);
583 return ret;
586 /* what sort of packet is this? */
587 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
589 data_blob_free(&blob1);
591 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
594 /****************************************************************************
595 On new VC == 0, shutdown *all* old connections and users.
596 It seems that only NT4.x does this. At W2K and above (XP etc.).
597 a new session setup with VC==0 is ignored.
598 ****************************************************************************/
600 static void setup_new_vc_session(void)
602 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
603 #if 0
604 conn_close_all();
605 invalidate_all_vuids();
606 #endif
609 /****************************************************************************
610 Reply to a session setup command.
611 ****************************************************************************/
613 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
614 int length,int bufsize)
616 int sess_vuid;
617 int smb_bufsize;
618 DATA_BLOB lm_resp;
619 DATA_BLOB nt_resp;
620 DATA_BLOB plaintext_password;
621 fstring user;
622 fstring sub_user; /* Sainitised username for substituion */
623 fstring domain;
624 fstring native_os;
625 fstring native_lanman;
626 fstring primary_domain;
627 static BOOL done_sesssetup = False;
628 extern BOOL global_encrypted_passwords_negotiated;
629 extern BOOL global_spnego_negotiated;
630 extern int Protocol;
631 extern int max_send;
633 auth_usersupplied_info *user_info = NULL;
634 extern struct auth_context *negprot_global_auth_context;
635 auth_serversupplied_info *server_info = NULL;
637 NTSTATUS nt_status;
639 BOOL doencrypt = global_encrypted_passwords_negotiated;
641 DATA_BLOB session_key;
643 START_PROFILE(SMBsesssetupX);
645 ZERO_STRUCT(lm_resp);
646 ZERO_STRUCT(nt_resp);
647 ZERO_STRUCT(plaintext_password);
649 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
651 /* a SPNEGO session setup has 12 command words, whereas a normal
652 NT1 session setup has 13. See the cifs spec. */
653 if (CVAL(inbuf, smb_wct) == 12 &&
654 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
655 if (!global_spnego_negotiated) {
656 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
657 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
660 if (SVAL(inbuf,smb_vwv4) == 0) {
661 setup_new_vc_session();
663 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
666 smb_bufsize = SVAL(inbuf,smb_vwv2);
668 if (Protocol < PROTOCOL_NT1) {
669 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
670 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
671 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
674 if (doencrypt) {
675 lm_resp = data_blob(smb_buf(inbuf), passlen1);
676 } else {
677 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
678 /* Ensure null termination */
679 plaintext_password.data[passlen1] = 0;
682 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
683 *domain = 0;
685 } else {
686 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
687 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
688 enum remote_arch_types ra_type = get_remote_arch();
689 char *p = smb_buf(inbuf);
690 char *save_p = smb_buf(inbuf);
691 uint16 byte_count;
694 if(global_client_caps == 0) {
695 global_client_caps = IVAL(inbuf,smb_vwv11);
697 if (!(global_client_caps & CAP_STATUS32)) {
698 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
701 /* client_caps is used as final determination if client is NT or Win95.
702 This is needed to return the correct error codes in some
703 circumstances.
706 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
707 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
708 set_remote_arch( RA_WIN95);
713 if (!doencrypt) {
714 /* both Win95 and WinNT stuff up the password lengths for
715 non-encrypting systems. Uggh.
717 if passlen1==24 its a win95 system, and its setting the
718 password length incorrectly. Luckily it still works with the
719 default code because Win95 will null terminate the password
720 anyway
722 if passlen1>0 and passlen2>0 then maybe its a NT box and its
723 setting passlen2 to some random value which really stuffs
724 things up. we need to fix that one. */
726 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
727 passlen2 = 0;
730 /* check for nasty tricks */
731 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
732 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
735 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
736 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
739 /* Save the lanman2 password and the NT md4 password. */
741 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
742 doencrypt = False;
745 if (doencrypt) {
746 lm_resp = data_blob(p, passlen1);
747 nt_resp = data_blob(p+passlen1, passlen2);
748 } else {
749 pstring pass;
750 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
752 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
753 /* NT4.0 stuffs up plaintext unicode password lengths... */
754 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
755 sizeof(pass), passlen1, STR_TERMINATE);
756 } else {
757 srvstr_pull(inbuf, pass, smb_buf(inbuf),
758 sizeof(pass), unic ? passlen2 : passlen1,
759 STR_TERMINATE);
761 plaintext_password = data_blob(pass, strlen(pass)+1);
764 p += passlen1 + passlen2;
765 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
766 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
767 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
768 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
770 /* not documented or decoded by Ethereal but there is one more string
771 in the extra bytes which is the same as the PrimaryDomain when using
772 extended security. Windows NT 4 and 2003 use this string to store
773 the native lanman string. Windows 9x does not include a string here
774 at all so we have to check if we have any extra bytes left */
776 byte_count = SVAL(inbuf, smb_vwv13);
777 if ( PTR_DIFF(p, save_p) < byte_count)
778 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
779 else
780 fstrcpy( primary_domain, "null" );
782 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
783 domain, native_os, native_lanman, primary_domain));
785 if ( ra_type == RA_WIN2K ) {
786 if ( strlen(native_lanman) == 0 )
787 ra_lanman_string( primary_domain );
788 else
789 ra_lanman_string( native_lanman );
794 if (SVAL(inbuf,smb_vwv4) == 0) {
795 setup_new_vc_session();
798 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
800 if (*user) {
801 if (global_spnego_negotiated) {
803 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
805 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
806 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
808 fstrcpy(sub_user, user);
810 /* setup the string used by %U */
811 sub_set_smb_name(user);
812 } else {
813 fstrcpy(sub_user, lp_guestaccount());
816 sub_set_smb_name(sub_user);
818 reload_services(True);
820 if (lp_security() == SEC_SHARE) {
821 /* in share level we should ignore any passwords */
823 data_blob_free(&lm_resp);
824 data_blob_free(&nt_resp);
825 data_blob_clear_free(&plaintext_password);
827 map_username(sub_user);
828 add_session_user(sub_user);
829 /* Then force it to null for the benfit of the code below */
830 *user = 0;
833 if (!*user) {
835 nt_status = check_guest_password(&server_info);
837 } else if (doencrypt) {
838 if (!negprot_global_auth_context) {
839 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
840 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
842 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
843 lm_resp, nt_resp);
844 if (NT_STATUS_IS_OK(nt_status)) {
845 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
846 user_info,
847 &server_info);
849 } else {
850 struct auth_context *plaintext_auth_context = NULL;
851 const uint8 *chal;
852 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
853 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
855 if (!make_user_info_for_reply(&user_info,
856 user, domain, chal,
857 plaintext_password)) {
858 nt_status = NT_STATUS_NO_MEMORY;
861 if (NT_STATUS_IS_OK(nt_status)) {
862 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
863 user_info,
864 &server_info);
866 (plaintext_auth_context->free)(&plaintext_auth_context);
871 free_user_info(&user_info);
873 if (!NT_STATUS_IS_OK(nt_status)) {
874 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
877 if (!NT_STATUS_IS_OK(nt_status)) {
878 data_blob_free(&nt_resp);
879 data_blob_free(&lm_resp);
880 data_blob_clear_free(&plaintext_password);
881 return ERROR_NT(nt_status_squash(nt_status));
884 if (server_info->nt_session_key.data) {
885 session_key = data_blob(server_info->nt_session_key.data, server_info->nt_session_key.length);
886 } else if (server_info->lm_session_key.length >= 8 && lm_resp.length == 24) {
887 session_key = data_blob(NULL, 16);
888 SMBsesskeygen_lmv1(server_info->lm_session_key.data, lm_resp.data,
889 session_key.data);
890 } else {
891 session_key = data_blob(NULL, 0);
894 data_blob_free(&lm_resp);
895 data_blob_clear_free(&plaintext_password);
897 /* it's ok - setup a reply */
898 set_message(outbuf,3,0,True);
899 if (Protocol >= PROTOCOL_NT1) {
900 char *p = smb_buf( outbuf );
901 p += add_signature( outbuf, p );
902 set_message_end( outbuf, p );
903 /* perhaps grab OS version here?? */
906 if (server_info->guest) {
907 SSVAL(outbuf,smb_vwv2,1);
910 /* register the name and uid as being validated, so further connections
911 to a uid can get through without a password, on the same VC */
913 /* register_vuid keeps the server info */
914 sess_vuid = register_vuid(server_info, session_key, nt_resp, sub_user);
915 data_blob_free(&nt_resp);
917 if (sess_vuid == -1) {
918 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
921 /* current_user_info is changed on new vuid */
922 reload_services( True );
924 if (!server_info->guest && !srv_signing_started() && !srv_check_sign_mac(inbuf, True)) {
925 exit_server("reply_sesssetup_and_X: bad smb signature");
928 SSVAL(outbuf,smb_uid,sess_vuid);
929 SSVAL(inbuf,smb_uid,sess_vuid);
931 if (!done_sesssetup)
932 max_send = MIN(max_send,smb_bufsize);
934 done_sesssetup = True;
936 END_PROFILE(SMBsesssetupX);
937 return chain_reply(inbuf,outbuf,length,bufsize);