2 Unix SMB/CIFS implementation.
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.
26 uint32 global_client_caps = 0;
29 on a logon error possibly map the error to success if "map to guest"
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",
40 status = make_server_info_guest(server_info);
44 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
45 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
46 DEBUG(3,("Registered username %s for guest access\n",user));
47 status = make_server_info_guest(server_info);
54 /****************************************************************************
55 Add the standard 'Samba' signature to the end of the session setup.
56 ****************************************************************************/
58 static int add_signature(char *outbuf, char *p)
63 fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
65 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
66 p += srvstr_push(outbuf, p, lanman, -1, STR_TERMINATE);
67 p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
69 return PTR_DIFF(p, start);
72 /****************************************************************************
73 Send a security blob via a session setup reply.
74 ****************************************************************************/
76 static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
77 DATA_BLOB blob, NTSTATUS nt_status)
81 set_message(outbuf,4,0,True);
83 nt_status = nt_status_squash(nt_status);
84 SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
85 SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
86 SSVAL(outbuf, smb_vwv3, blob.length);
89 /* should we cap this? */
90 memcpy(p, blob.data, blob.length);
93 p += add_signature( outbuf, p );
95 set_message_end(outbuf,p);
98 return send_smb(smbd_server_fd(),outbuf);
101 /****************************************************************************
102 Do a 'guest' logon, getting back the
103 ****************************************************************************/
105 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
107 struct auth_context *auth_context;
108 auth_usersupplied_info *user_info = NULL;
111 unsigned char chal[8];
115 DEBUG(3,("Got anonymous request\n"));
117 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) {
121 if (!make_user_info_guest(&user_info)) {
122 (auth_context->free)(&auth_context);
123 return NT_STATUS_NO_MEMORY;
126 nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info);
127 (auth_context->free)(&auth_context);
128 free_user_info(&user_info);
134 /****************************************************************************
135 reply to a session setup spnego negotiate packet for kerberos
136 ****************************************************************************/
137 static int reply_spnego_kerberos(connection_struct *conn,
138 char *inbuf, char *outbuf,
139 int length, int bufsize,
144 char *client, *p, *domain;
145 fstring netbios_domain_name;
151 DATA_BLOB ap_rep, ap_rep_wrapped, response;
152 auth_serversupplied_info *server_info = NULL;
153 DATA_BLOB session_key = data_blob(NULL, 0);
155 DATA_BLOB nullblob = data_blob(NULL, 0);
156 fstring real_username;
157 BOOL map_domainuser_to_guest = False;
158 PAC_LOGON_INFO *logon_info = NULL;
162 ZERO_STRUCT(pac_data);
164 ZERO_STRUCT(ap_rep_wrapped);
165 ZERO_STRUCT(response);
167 mem_ctx = talloc_init("reply_spnego_kerberos");
169 return ERROR_NT(NT_STATUS_NO_MEMORY);
171 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
172 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
175 ret = ads_verify_ticket(mem_ctx, lp_realm(), &ticket, &client, &pac_data, &ap_rep, &session_key);
177 data_blob_free(&ticket);
179 if (!NT_STATUS_IS_OK(ret)) {
180 DEBUG(1,("Failed to verify incoming ticket!\n"));
181 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
186 /* get the logon_info */
187 for (i=0; i < pac_data->num_buffers; i++) {
189 if (pac_data->pac_buffer[i].type != PAC_TYPE_LOGON_INFO)
192 logon_info = pac_data->pac_buffer[i].ctr->pac.logon_info;
197 DEBUG(3,("Ticket name is [%s]\n", client));
199 p = strchr_m(client, '@');
201 DEBUG(3,("Doesn't look like a valid principal\n"));
202 data_blob_free(&ap_rep);
203 data_blob_free(&session_key);
205 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
209 if (!strequal(p+1, lp_realm())) {
210 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
211 if (!lp_allow_trusted_domains()) {
212 data_blob_free(&ap_rep);
213 data_blob_free(&session_key);
215 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
219 /* this gives a fully qualified user name (ie. with full realm).
220 that leads to very long usernames, but what else can we do? */
224 if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) {
226 unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, -1);
227 domain = netbios_domain_name;
228 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
232 /* If we have winbind running, we can (and must) shorten the
233 username by using the short netbios name. Otherwise we will
234 have inconsistent user names. With Kerberos, we get the
235 fully qualified realm, with ntlmssp we get the short
236 name. And even w2k3 does use ntlmssp if you for example
237 connect to an ip address. */
239 struct winbindd_request wb_request;
240 struct winbindd_response wb_response;
241 NSS_STATUS wb_result;
243 ZERO_STRUCT(wb_request);
244 ZERO_STRUCT(wb_response);
246 DEBUG(10, ("Mapping [%s] to short name\n", domain));
248 fstrcpy(wb_request.domain_name, domain);
250 wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
251 &wb_request, &wb_response);
253 if (wb_result == NSS_STATUS_SUCCESS) {
255 fstrcpy(netbios_domain_name,
256 wb_response.data.domain_info.name);
257 domain = netbios_domain_name;
259 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
261 DEBUG(3, ("Could not find short name -- winbind "
266 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
268 /* lookup the passwd struct, create a new user if necessary */
270 map_username( user );
272 pw = smb_getpwnam( user, real_username, True );
275 /* this was originally the behavior of Samba 2.2, if a user
276 did not have a local uid but has been authenticated, then
277 map them to a guest account */
279 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
280 map_domainuser_to_guest = True;
281 fstrcpy(user,lp_guestaccount());
282 pw = smb_getpwnam( user, real_username, True );
285 /* extra sanity check that the guest account is valid */
288 DEBUG(1,("Username %s is invalid on this system\n", user));
290 data_blob_free(&ap_rep);
291 data_blob_free(&session_key);
292 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
296 /* setup the string used by %U */
298 sub_set_smb_name( real_username );
299 reload_services(True);
300 if ( map_domainuser_to_guest ) {
301 make_server_info_guest(&server_info);
302 } else if (logon_info) {
303 ret = make_server_info_pac(&server_info, real_username, pw, logon_info);
305 if ( !NT_STATUS_IS_OK(ret) ) {
306 DEBUG(1,("make_server_info_pac failed!\n"));
308 data_blob_free(&ap_rep);
309 data_blob_free(&session_key);
311 return ERROR_NT(ret);
315 ret = make_server_info_pw(&server_info, real_username, pw);
317 if ( !NT_STATUS_IS_OK(ret) ) {
318 DEBUG(1,("make_server_info_from_pw failed!\n"));
320 data_blob_free(&ap_rep);
321 data_blob_free(&session_key);
323 return ERROR_NT(ret);
326 /* make_server_info_pw does not set the domain. Without this we end up
327 * with the local netbios name in substitutions for %D. */
329 if (server_info->sam_account != NULL) {
330 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
337 /* register_vuid keeps the server info */
338 /* register_vuid takes ownership of session_key, no need to free after this.
339 A better interface would copy it.... */
340 sess_vuid = register_vuid(server_info, session_key, nullblob, client);
344 if (sess_vuid == -1) {
345 ret = NT_STATUS_LOGON_FAILURE;
347 /* current_user_info is changed on new vuid */
348 reload_services( True );
350 set_message(outbuf,4,0,True);
351 SSVAL(outbuf, smb_vwv3, 0);
353 if (server_info->guest) {
354 SSVAL(outbuf,smb_vwv2,1);
357 SSVAL(outbuf, smb_uid, sess_vuid);
359 if (!server_info->guest && !srv_signing_started()) {
360 /* We need to start the signing engine
361 * here but a W2K client sends the old
362 * "BSRSPYL " signature instead of the
363 * correct one. Subsequent packets will
366 srv_check_sign_mac(inbuf, False);
370 /* wrap that up in a nice GSS-API wrapping */
371 if (NT_STATUS_IS_OK(ret)) {
372 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
374 ap_rep_wrapped = data_blob(NULL, 0);
376 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
377 reply_sesssetup_blob(conn, outbuf, response, ret);
379 data_blob_free(&ap_rep);
380 data_blob_free(&ap_rep_wrapped);
381 data_blob_free(&response);
382 talloc_destroy(mem_ctx);
384 return -1; /* already replied */
388 /****************************************************************************
389 Send a session setup reply, wrapped in SPNEGO.
390 Get vuid and check first.
391 End the NTLMSSP exchange context if we are OK/complete fail
392 This should be split into two functions, one to handle each
393 leg of the NTLM auth steps.
394 ***************************************************************************/
396 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
398 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
399 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
404 struct auth_serversupplied_info *server_info = NULL;
406 if (NT_STATUS_IS_OK(nt_status)) {
407 server_info = (*auth_ntlmssp_state)->server_info;
409 nt_status = do_map_to_guest(nt_status,
411 (*auth_ntlmssp_state)->ntlmssp_state->user,
412 (*auth_ntlmssp_state)->ntlmssp_state->domain);
415 if (NT_STATUS_IS_OK(nt_status)) {
417 DATA_BLOB nullblob = data_blob(NULL, 0);
418 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
420 /* register_vuid keeps the server info */
421 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
422 (*auth_ntlmssp_state)->server_info = NULL;
424 if (sess_vuid == -1) {
425 nt_status = NT_STATUS_LOGON_FAILURE;
428 /* current_user_info is changed on new vuid */
429 reload_services( True );
431 set_message(outbuf,4,0,True);
432 SSVAL(outbuf, smb_vwv3, 0);
434 if (server_info->guest) {
435 SSVAL(outbuf,smb_vwv2,1);
438 SSVAL(outbuf,smb_uid,sess_vuid);
440 if (!server_info->guest && !srv_signing_started()) {
441 /* We need to start the signing engine
442 * here but a W2K client sends the old
443 * "BSRSPYL " signature instead of the
444 * correct one. Subsequent packets will
448 srv_check_sign_mac(inbuf, False);
454 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
456 response = *ntlmssp_blob;
459 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
461 data_blob_free(&response);
464 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
465 and the other end, that we are not finished yet. */
467 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
468 /* NB. This is *NOT* an error case. JRA */
469 auth_ntlmssp_end(auth_ntlmssp_state);
470 /* Kill the intermediate vuid */
471 invalidate_vuid(vuid);
477 /****************************************************************************
478 Reply to a session setup spnego negotiate packet.
479 ****************************************************************************/
481 static int reply_spnego_negotiate(connection_struct *conn,
485 int length, int bufsize,
487 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
489 char *OIDs[ASN1_MAX_OIDS];
494 BOOL got_kerberos_mechanism = False;
498 /* parse out the OIDs and the first sec blob */
499 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
500 /* Kill the intermediate vuid */
501 invalidate_vuid(vuid);
503 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
506 /* only look at the first OID for determining the mechToken --
507 accoirding to RFC2478, we should choose the one we want
508 and renegotiate, but i smell a client bug here..
510 Problem observed when connecting to a member (samba box)
511 of an AD domain as a user in a Samba domain. Samba member
512 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
513 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
514 NTLMSSP mechtoken. --jerry */
517 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
518 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
519 got_kerberos_mechanism = True;
523 for (i=0;OIDs[i];i++) {
524 DEBUG(3,("Got OID %s\n", OIDs[i]));
527 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
530 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
531 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
532 length, bufsize, &secblob);
533 data_blob_free(&secblob);
534 /* Kill the intermediate vuid */
535 invalidate_vuid(vuid);
541 if (*auth_ntlmssp_state) {
542 auth_ntlmssp_end(auth_ntlmssp_state);
545 nt_status = auth_ntlmssp_start(auth_ntlmssp_state);
546 if (!NT_STATUS_IS_OK(nt_status)) {
547 /* Kill the intermediate vuid */
548 invalidate_vuid(vuid);
550 return ERROR_NT(nt_status);
553 nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
556 data_blob_free(&secblob);
558 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
559 &chal, nt_status, True);
561 data_blob_free(&chal);
563 /* already replied */
567 /****************************************************************************
568 Reply to a session setup spnego auth packet.
569 ****************************************************************************/
571 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
573 int length, int bufsize,
575 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
577 DATA_BLOB auth, auth_reply;
578 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
580 if (!spnego_parse_auth(blob1, &auth)) {
582 file_save("auth.dat", blob1.data, blob1.length);
584 /* Kill the intermediate vuid */
585 invalidate_vuid(vuid);
587 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
590 if (!*auth_ntlmssp_state) {
591 /* Kill the intermediate vuid */
592 invalidate_vuid(vuid);
594 /* auth before negotiatiate? */
595 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
598 nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
601 data_blob_free(&auth);
603 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
605 &auth_reply, nt_status, True);
607 data_blob_free(&auth_reply);
609 /* and tell smbd that we have already replied to this packet */
613 /****************************************************************************
614 Reply to a session setup command.
615 ****************************************************************************/
617 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
619 int length,int bufsize)
625 fstring native_os, native_lanman, primary_domain;
627 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
628 enum remote_arch_types ra_type = get_remote_arch();
629 int vuid = SVAL(inbuf,smb_uid);
630 user_struct *vuser = NULL;
632 DEBUG(3,("Doing spnego session setup\n"));
634 if (global_client_caps == 0) {
635 global_client_caps = IVAL(inbuf,smb_vwv10);
637 if (!(global_client_caps & CAP_STATUS32)) {
638 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
643 p = (uint8 *)smb_buf(inbuf);
645 if (data_blob_len == 0) {
646 /* an invalid request */
647 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
650 bufrem = smb_bufrem(inbuf, p);
651 /* pull the spnego blob */
652 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
655 file_save("negotiate.dat", blob1.data, blob1.length);
658 p2 = inbuf + smb_vwv13 + data_blob_len;
659 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
660 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
661 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
662 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
663 native_os, native_lanman, primary_domain));
665 if ( ra_type == RA_WIN2K ) {
666 /* Windows 2003 doesn't set the native lanman string,
667 but does set primary domain which is a bug I think */
669 if ( !strlen(native_lanman) )
670 ra_lanman_string( primary_domain );
672 ra_lanman_string( native_lanman );
675 vuser = get_partial_auth_user_struct(vuid);
677 vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);
679 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
682 vuser = get_partial_auth_user_struct(vuid);
686 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
689 SSVAL(outbuf,smb_uid,vuid);
691 if (blob1.data[0] == ASN1_APPLICATION(0)) {
692 /* its a negTokenTarg packet */
693 ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
694 &vuser->auth_ntlmssp_state);
695 data_blob_free(&blob1);
699 if (blob1.data[0] == ASN1_CONTEXT(1)) {
700 /* its a auth packet */
701 ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
702 &vuser->auth_ntlmssp_state);
703 data_blob_free(&blob1);
707 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
710 if (!vuser->auth_ntlmssp_state) {
711 nt_status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
712 if (!NT_STATUS_IS_OK(nt_status)) {
713 /* Kill the intermediate vuid */
714 invalidate_vuid(vuid);
716 return ERROR_NT(nt_status);
720 nt_status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
723 data_blob_free(&blob1);
725 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
726 &vuser->auth_ntlmssp_state,
727 &chal, nt_status, False);
728 data_blob_free(&chal);
732 /* what sort of packet is this? */
733 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
735 data_blob_free(&blob1);
737 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
740 /****************************************************************************
741 On new VC == 0, shutdown *all* old connections and users.
742 It seems that only NT4.x does this. At W2K and above (XP etc.).
743 a new session setup with VC==0 is ignored.
744 ****************************************************************************/
746 static void setup_new_vc_session(void)
748 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
751 invalidate_all_vuids();
755 /****************************************************************************
756 Reply to a session setup command.
757 ****************************************************************************/
759 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
760 int length,int bufsize)
766 DATA_BLOB plaintext_password;
768 fstring sub_user; /* Sainitised username for substituion */
771 fstring native_lanman;
772 fstring primary_domain;
773 static BOOL done_sesssetup = False;
774 extern BOOL global_encrypted_passwords_negotiated;
775 extern BOOL global_spnego_negotiated;
776 extern enum protocol_types Protocol;
779 auth_usersupplied_info *user_info = NULL;
780 extern struct auth_context *negprot_global_auth_context;
781 auth_serversupplied_info *server_info = NULL;
785 BOOL doencrypt = global_encrypted_passwords_negotiated;
787 DATA_BLOB session_key;
789 START_PROFILE(SMBsesssetupX);
791 ZERO_STRUCT(lm_resp);
792 ZERO_STRUCT(nt_resp);
793 ZERO_STRUCT(plaintext_password);
795 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
797 /* a SPNEGO session setup has 12 command words, whereas a normal
798 NT1 session setup has 13. See the cifs spec. */
799 if (CVAL(inbuf, smb_wct) == 12 &&
800 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
801 if (!global_spnego_negotiated) {
802 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
803 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
806 if (SVAL(inbuf,smb_vwv4) == 0) {
807 setup_new_vc_session();
809 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
812 smb_bufsize = SVAL(inbuf,smb_vwv2);
814 if (Protocol < PROTOCOL_NT1) {
815 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
817 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
818 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
820 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
821 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
825 lm_resp = data_blob(smb_buf(inbuf), passlen1);
827 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
828 /* Ensure null termination */
829 plaintext_password.data[passlen1] = 0;
832 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
836 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
837 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
838 enum remote_arch_types ra_type = get_remote_arch();
839 char *p = smb_buf(inbuf);
840 char *save_p = smb_buf(inbuf);
844 if(global_client_caps == 0) {
845 global_client_caps = IVAL(inbuf,smb_vwv11);
847 if (!(global_client_caps & CAP_STATUS32)) {
848 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
851 /* client_caps is used as final determination if client is NT or Win95.
852 This is needed to return the correct error codes in some
856 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
857 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
858 set_remote_arch( RA_WIN95);
864 /* both Win95 and WinNT stuff up the password lengths for
865 non-encrypting systems. Uggh.
867 if passlen1==24 its a win95 system, and its setting the
868 password length incorrectly. Luckily it still works with the
869 default code because Win95 will null terminate the password
872 if passlen1>0 and passlen2>0 then maybe its a NT box and its
873 setting passlen2 to some random value which really stuffs
874 things up. we need to fix that one. */
876 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
880 /* check for nasty tricks */
881 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
882 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
885 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
886 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
889 /* Save the lanman2 password and the NT md4 password. */
891 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
896 lm_resp = data_blob(p, passlen1);
897 nt_resp = data_blob(p+passlen1, passlen2);
900 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
903 /* This was the previous fix. Not sure if it's still valid. JRA. */
904 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
905 /* NT4.0 stuffs up plaintext unicode password lengths... */
906 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
907 sizeof(pass), passlen1, STR_TERMINATE);
910 if (unic && (passlen2 == 0) && passlen1) {
911 /* Only a ascii plaintext password was sent. */
912 srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
913 passlen1, STR_TERMINATE|STR_ASCII);
915 srvstr_pull(inbuf, pass, smb_buf(inbuf),
916 sizeof(pass), unic ? passlen2 : passlen1,
919 plaintext_password = data_blob(pass, strlen(pass)+1);
922 p += passlen1 + passlen2;
923 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
924 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
925 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
926 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
928 /* not documented or decoded by Ethereal but there is one more string
929 in the extra bytes which is the same as the PrimaryDomain when using
930 extended security. Windows NT 4 and 2003 use this string to store
931 the native lanman string. Windows 9x does not include a string here
932 at all so we have to check if we have any extra bytes left */
934 byte_count = SVAL(inbuf, smb_vwv13);
935 if ( PTR_DIFF(p, save_p) < byte_count)
936 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
938 fstrcpy( primary_domain, "null" );
940 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
941 domain, native_os, native_lanman, primary_domain));
943 if ( ra_type == RA_WIN2K ) {
944 if ( strlen(native_lanman) == 0 )
945 ra_lanman_string( primary_domain );
947 ra_lanman_string( native_lanman );
952 if (SVAL(inbuf,smb_vwv4) == 0) {
953 setup_new_vc_session();
956 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
959 if (global_spnego_negotiated) {
961 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
963 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
964 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
966 fstrcpy(sub_user, user);
968 /* setup the string used by %U */
969 sub_set_smb_name(user);
971 fstrcpy(sub_user, lp_guestaccount());
974 sub_set_smb_name(sub_user);
976 reload_services(True);
978 if (lp_security() == SEC_SHARE) {
979 /* in share level we should ignore any passwords */
981 data_blob_free(&lm_resp);
982 data_blob_free(&nt_resp);
983 data_blob_clear_free(&plaintext_password);
985 map_username(sub_user);
986 add_session_user(sub_user);
987 /* Then force it to null for the benfit of the code below */
993 nt_status = check_guest_password(&server_info);
995 } else if (doencrypt) {
996 if (!negprot_global_auth_context) {
997 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
998 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
1000 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
1002 if (NT_STATUS_IS_OK(nt_status)) {
1003 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
1008 struct auth_context *plaintext_auth_context = NULL;
1010 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
1011 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
1013 if (!make_user_info_for_reply(&user_info,
1015 plaintext_password)) {
1016 nt_status = NT_STATUS_NO_MEMORY;
1019 if (NT_STATUS_IS_OK(nt_status)) {
1020 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
1024 (plaintext_auth_context->free)(&plaintext_auth_context);
1029 free_user_info(&user_info);
1031 if (!NT_STATUS_IS_OK(nt_status)) {
1032 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
1035 if (!NT_STATUS_IS_OK(nt_status)) {
1036 data_blob_free(&nt_resp);
1037 data_blob_free(&lm_resp);
1038 data_blob_clear_free(&plaintext_password);
1039 return ERROR_NT(nt_status_squash(nt_status));
1042 if (server_info->user_session_key.data) {
1043 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
1045 session_key = data_blob(NULL, 0);
1048 data_blob_clear_free(&plaintext_password);
1050 /* it's ok - setup a reply */
1051 set_message(outbuf,3,0,True);
1052 if (Protocol >= PROTOCOL_NT1) {
1053 char *p = smb_buf( outbuf );
1054 p += add_signature( outbuf, p );
1055 set_message_end( outbuf, p );
1056 /* perhaps grab OS version here?? */
1059 if (server_info->guest) {
1060 SSVAL(outbuf,smb_vwv2,1);
1063 /* register the name and uid as being validated, so further connections
1064 to a uid can get through without a password, on the same VC */
1066 /* register_vuid keeps the server info */
1067 sess_vuid = register_vuid(server_info, session_key, nt_resp.data ? nt_resp : lm_resp, sub_user);
1068 data_blob_free(&nt_resp);
1069 data_blob_free(&lm_resp);
1071 if (sess_vuid == -1) {
1072 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
1075 /* current_user_info is changed on new vuid */
1076 reload_services( True );
1078 if (!server_info->guest && !srv_signing_started() && !srv_check_sign_mac(inbuf, True)) {
1079 exit_server("reply_sesssetup_and_X: bad smb signature");
1082 SSVAL(outbuf,smb_uid,sess_vuid);
1083 SSVAL(inbuf,smb_uid,sess_vuid);
1085 if (!done_sesssetup)
1086 max_send = MIN(max_send,smb_bufsize);
1088 done_sesssetup = True;
1090 END_PROFILE(SMBsesssetupX);
1091 return chain_reply(inbuf,outbuf,length,bufsize);