missed one on BUG 1195; make sure to set the private * to NULL
[Samba/gebeck_regimport.git] / source3 / smbd / sesssetup.c
blob244db6d2c140739a2868b23bc1671ae0c0caad86
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) {
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);
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) {
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.
380 srv_check_sign_mac(inbuf);
385 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
386 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
387 data_blob_free(&response);
389 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
390 and the other end, that we are not finished yet. */
392 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
393 auth_ntlmssp_end(auth_ntlmssp_state);
396 return ret;
399 /****************************************************************************
400 Reply to a session setup spnego negotiate packet.
401 ****************************************************************************/
403 static int reply_spnego_negotiate(connection_struct *conn,
404 char *inbuf,
405 char *outbuf,
406 int length, int bufsize,
407 DATA_BLOB blob1)
409 char *OIDs[ASN1_MAX_OIDS];
410 DATA_BLOB secblob;
411 int i;
412 DATA_BLOB chal;
413 BOOL got_kerberos = False;
414 NTSTATUS nt_status;
416 /* parse out the OIDs and the first sec blob */
417 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
418 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
421 /* only look at the first OID for determining the mechToken --
422 accoirding to RFC2478, we should choose the one we want
423 and renegotiate, but i smell a client bug here..
425 Problem observed when connecting to a member (samba box)
426 of an AD domain as a user in a Samba domain. Samba member
427 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
428 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
429 NTLMSSP mechtoken. --jerry */
431 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
432 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
433 got_kerberos = True;
436 for (i=0;OIDs[i];i++) {
437 DEBUG(3,("Got OID %s\n", OIDs[i]));
438 free(OIDs[i]);
440 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
442 #ifdef HAVE_KRB5
443 if (got_kerberos && (SEC_ADS == lp_security())) {
444 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
445 length, bufsize, &secblob);
446 data_blob_free(&secblob);
447 return ret;
449 #endif
451 if (global_ntlmssp_state) {
452 auth_ntlmssp_end(&global_ntlmssp_state);
455 nt_status = auth_ntlmssp_start(&global_ntlmssp_state);
456 if (!NT_STATUS_IS_OK(nt_status)) {
457 return ERROR_NT(nt_status);
460 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
461 secblob, &chal);
463 data_blob_free(&secblob);
465 reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
466 &chal, nt_status);
468 data_blob_free(&chal);
470 /* already replied */
471 return -1;
474 /****************************************************************************
475 Reply to a session setup spnego auth packet.
476 ****************************************************************************/
478 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
479 int length, int bufsize,
480 DATA_BLOB blob1)
482 DATA_BLOB auth, auth_reply;
483 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
485 if (!spnego_parse_auth(blob1, &auth)) {
486 #if 0
487 file_save("auth.dat", blob1.data, blob1.length);
488 #endif
489 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
492 if (!global_ntlmssp_state) {
493 /* auth before negotiatiate? */
494 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
497 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
498 auth, &auth_reply);
500 data_blob_free(&auth);
502 reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
503 &auth_reply, nt_status);
505 data_blob_free(&auth_reply);
507 /* and tell smbd that we have already replied to this packet */
508 return -1;
511 /****************************************************************************
512 Reply to a session setup command.
513 ****************************************************************************/
515 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
516 char *outbuf,
517 int length,int bufsize)
519 uint8 *p;
520 DATA_BLOB blob1;
521 int ret;
522 size_t bufrem;
523 fstring native_os, native_lanman, primary_domain;
524 char *p2;
525 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
526 enum remote_arch_types ra_type = get_remote_arch();
528 DEBUG(3,("Doing spnego session setup\n"));
530 if (global_client_caps == 0) {
531 global_client_caps = IVAL(inbuf,smb_vwv10);
533 if (!(global_client_caps & CAP_STATUS32)) {
534 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
539 p = (uint8 *)smb_buf(inbuf);
541 if (data_blob_len == 0) {
542 /* an invalid request */
543 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
546 bufrem = smb_bufrem(inbuf, p);
547 /* pull the spnego blob */
548 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
550 #if 0
551 file_save("negotiate.dat", blob1.data, blob1.length);
552 #endif
554 p2 = inbuf + smb_vwv13 + data_blob_len;
555 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
556 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
557 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
558 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
559 native_os, native_lanman, primary_domain));
561 if ( ra_type == RA_WIN2K ) {
562 /* Windows 2003 doesn't set the native lanman string,
563 but does set primary domain which is a bug I think */
565 if ( !strlen(native_lanman) )
566 ra_lanman_string( primary_domain );
567 else
568 ra_lanman_string( native_lanman );
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);
593 /****************************************************************************
594 On new VC == 0, shutdown *all* old connections and users.
595 It seems that only NT4.x does this. At W2K and above (XP etc.).
596 a new session setup with VC==0 is ignored.
597 ****************************************************************************/
599 static void setup_new_vc_session(void)
601 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
602 #if 0
603 conn_close_all();
604 invalidate_all_vuids();
605 #endif
608 /****************************************************************************
609 Reply to a session setup command.
610 ****************************************************************************/
612 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
613 int length,int bufsize)
615 int sess_vuid;
616 int smb_bufsize;
617 DATA_BLOB lm_resp;
618 DATA_BLOB nt_resp;
619 DATA_BLOB plaintext_password;
620 fstring user;
621 fstring sub_user; /* Sainitised username for substituion */
622 fstring domain;
623 fstring native_os;
624 fstring native_lanman;
625 fstring primary_domain;
626 static BOOL done_sesssetup = False;
627 extern BOOL global_encrypted_passwords_negotiated;
628 extern BOOL global_spnego_negotiated;
629 extern int Protocol;
630 extern int max_send;
632 auth_usersupplied_info *user_info = NULL;
633 extern struct auth_context *negprot_global_auth_context;
634 auth_serversupplied_info *server_info = NULL;
636 NTSTATUS nt_status;
638 BOOL doencrypt = global_encrypted_passwords_negotiated;
640 DATA_BLOB session_key;
642 START_PROFILE(SMBsesssetupX);
644 ZERO_STRUCT(lm_resp);
645 ZERO_STRUCT(nt_resp);
646 ZERO_STRUCT(plaintext_password);
648 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
650 /* a SPNEGO session setup has 12 command words, whereas a normal
651 NT1 session setup has 13. See the cifs spec. */
652 if (CVAL(inbuf, smb_wct) == 12 &&
653 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
654 if (!global_spnego_negotiated) {
655 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
656 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
659 if (SVAL(inbuf,smb_vwv4) == 0) {
660 setup_new_vc_session();
662 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
665 smb_bufsize = SVAL(inbuf,smb_vwv2);
667 if (Protocol < PROTOCOL_NT1) {
668 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
669 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
670 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
673 if (doencrypt) {
674 lm_resp = data_blob(smb_buf(inbuf), passlen1);
675 } else {
676 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
677 /* Ensure null termination */
678 plaintext_password.data[passlen1] = 0;
681 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
682 *domain = 0;
684 } else {
685 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
686 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
687 enum remote_arch_types ra_type = get_remote_arch();
688 char *p = smb_buf(inbuf);
689 char *save_p = smb_buf(inbuf);
690 uint16 byte_count;
693 if(global_client_caps == 0) {
694 global_client_caps = IVAL(inbuf,smb_vwv11);
696 if (!(global_client_caps & CAP_STATUS32)) {
697 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
700 /* client_caps is used as final determination if client is NT or Win95.
701 This is needed to return the correct error codes in some
702 circumstances.
705 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
706 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
707 set_remote_arch( RA_WIN95);
712 if (!doencrypt) {
713 /* both Win95 and WinNT stuff up the password lengths for
714 non-encrypting systems. Uggh.
716 if passlen1==24 its a win95 system, and its setting the
717 password length incorrectly. Luckily it still works with the
718 default code because Win95 will null terminate the password
719 anyway
721 if passlen1>0 and passlen2>0 then maybe its a NT box and its
722 setting passlen2 to some random value which really stuffs
723 things up. we need to fix that one. */
725 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
726 passlen2 = 0;
729 /* check for nasty tricks */
730 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
731 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
734 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
735 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
738 /* Save the lanman2 password and the NT md4 password. */
740 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
741 doencrypt = False;
744 if (doencrypt) {
745 lm_resp = data_blob(p, passlen1);
746 nt_resp = data_blob(p+passlen1, passlen2);
747 } else {
748 pstring pass;
749 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
751 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
752 /* NT4.0 stuffs up plaintext unicode password lengths... */
753 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
754 sizeof(pass), passlen1, STR_TERMINATE);
755 } else {
756 srvstr_pull(inbuf, pass, smb_buf(inbuf),
757 sizeof(pass), unic ? passlen2 : passlen1,
758 STR_TERMINATE);
760 plaintext_password = data_blob(pass, strlen(pass)+1);
763 p += passlen1 + passlen2;
764 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
765 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
766 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
767 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
769 /* not documented or decoded by Ethereal but there is one more string
770 in the extra bytes which is the same as the PrimaryDomain when using
771 extended security. Windows NT 4 and 2003 use this string to store
772 the native lanman string. Windows 9x does not include a string here
773 at all so we have to check if we have any extra bytes left */
775 byte_count = SVAL(inbuf, smb_vwv13);
776 if ( PTR_DIFF(p, save_p) < byte_count)
777 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
778 else
779 fstrcpy( primary_domain, "null" );
781 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
782 domain, native_os, native_lanman, primary_domain));
784 if ( ra_type == RA_WIN2K ) {
785 if ( strlen(native_lanman) == 0 )
786 ra_lanman_string( primary_domain );
787 else
788 ra_lanman_string( native_lanman );
793 if (SVAL(inbuf,smb_vwv4) == 0) {
794 setup_new_vc_session();
797 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
799 if (*user) {
800 if (global_spnego_negotiated) {
802 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
804 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
805 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
807 fstrcpy(sub_user, user);
809 /* setup the string used by %U */
810 sub_set_smb_name(user);
811 } else {
812 fstrcpy(sub_user, lp_guestaccount());
815 sub_set_smb_name(sub_user);
817 reload_services(True);
819 if (lp_security() == SEC_SHARE) {
820 /* in share level we should ignore any passwords */
822 data_blob_free(&lm_resp);
823 data_blob_free(&nt_resp);
824 data_blob_clear_free(&plaintext_password);
826 map_username(sub_user);
827 add_session_user(sub_user);
828 /* Then force it to null for the benfit of the code below */
829 *user = 0;
832 if (!*user) {
834 nt_status = check_guest_password(&server_info);
836 } else if (doencrypt) {
837 if (!negprot_global_auth_context) {
838 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
839 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
841 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
842 lm_resp, nt_resp);
843 if (NT_STATUS_IS_OK(nt_status)) {
844 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
845 user_info,
846 &server_info);
848 } else {
849 struct auth_context *plaintext_auth_context = NULL;
850 const uint8 *chal;
851 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
852 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
854 if (!make_user_info_for_reply(&user_info,
855 user, domain, chal,
856 plaintext_password)) {
857 nt_status = NT_STATUS_NO_MEMORY;
860 if (NT_STATUS_IS_OK(nt_status)) {
861 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
862 user_info,
863 &server_info);
865 (plaintext_auth_context->free)(&plaintext_auth_context);
870 free_user_info(&user_info);
872 if (!NT_STATUS_IS_OK(nt_status)) {
873 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
876 if (!NT_STATUS_IS_OK(nt_status)) {
877 data_blob_free(&nt_resp);
878 data_blob_free(&lm_resp);
879 data_blob_clear_free(&plaintext_password);
880 return ERROR_NT(nt_status_squash(nt_status));
883 if (server_info->nt_session_key.data) {
884 session_key = data_blob(server_info->nt_session_key.data, server_info->nt_session_key.length);
885 } else if (server_info->lm_session_key.length >= 8 && lm_resp.length == 24) {
886 session_key = data_blob(NULL, 16);
887 SMBsesskeygen_lmv1(server_info->lm_session_key.data, lm_resp.data,
888 session_key.data);
889 } else {
890 session_key = data_blob(NULL, 0);
893 data_blob_free(&lm_resp);
894 data_blob_clear_free(&plaintext_password);
896 /* it's ok - setup a reply */
897 set_message(outbuf,3,0,True);
898 if (Protocol >= PROTOCOL_NT1) {
899 char *p = smb_buf( outbuf );
900 p += add_signature( outbuf, p );
901 set_message_end( outbuf, p );
902 /* perhaps grab OS version here?? */
905 if (server_info->guest) {
906 SSVAL(outbuf,smb_vwv2,1);
909 /* register the name and uid as being validated, so further connections
910 to a uid can get through without a password, on the same VC */
912 /* register_vuid keeps the server info */
913 sess_vuid = register_vuid(server_info, session_key, nt_resp, sub_user);
914 data_blob_free(&nt_resp);
916 if (sess_vuid == -1) {
917 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
920 /* current_user_info is changed on new vuid */
921 reload_services( True );
923 if (!server_info->guest && !srv_check_sign_mac(inbuf)) {
924 exit_server("reply_sesssetup_and_X: bad smb signature");
927 SSVAL(outbuf,smb_uid,sess_vuid);
928 SSVAL(inbuf,smb_uid,sess_vuid);
930 if (!done_sesssetup)
931 max_send = MIN(max_send,smb_bufsize);
933 done_sesssetup = True;
935 END_PROFILE(SMBsesssetupX);
936 return chain_reply(inbuf,outbuf,length,bufsize);