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 Start the signing engine if needed. Don't fail signing here.
74 ****************************************************************************/
76 static void sessionsetup_start_signing_engine(const auth_serversupplied_info *server_info, char *inbuf)
78 if (!server_info->guest && !srv_signing_started()) {
79 /* We need to start the signing engine
80 * here but a W2K client sends the old
81 * "BSRSPYL " signature instead of the
82 * correct one. Subsequent packets will
85 srv_check_sign_mac(inbuf, False);
89 /****************************************************************************
90 Send a security blob via a session setup reply.
91 ****************************************************************************/
93 static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
94 DATA_BLOB blob, NTSTATUS nt_status)
98 set_message(outbuf,4,0,True);
100 nt_status = nt_status_squash(nt_status);
101 SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
102 SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
103 SSVAL(outbuf, smb_vwv3, blob.length);
106 /* should we cap this? */
107 memcpy(p, blob.data, blob.length);
110 p += add_signature( outbuf, p );
112 set_message_end(outbuf,p);
115 return send_smb(smbd_server_fd(),outbuf);
118 /****************************************************************************
119 Do a 'guest' logon, getting back the
120 ****************************************************************************/
122 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
124 struct auth_context *auth_context;
125 auth_usersupplied_info *user_info = NULL;
128 unsigned char chal[8];
132 DEBUG(3,("Got anonymous request\n"));
134 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) {
138 if (!make_user_info_guest(&user_info)) {
139 (auth_context->free)(&auth_context);
140 return NT_STATUS_NO_MEMORY;
143 nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info);
144 (auth_context->free)(&auth_context);
145 free_user_info(&user_info);
151 /****************************************************************************
152 reply to a session setup spnego negotiate packet for kerberos
153 ****************************************************************************/
154 static int reply_spnego_kerberos(connection_struct *conn,
155 char *inbuf, char *outbuf,
156 int length, int bufsize,
161 char *client, *p, *domain;
162 fstring netbios_domain_name;
168 DATA_BLOB ap_rep, ap_rep_wrapped, response;
169 auth_serversupplied_info *server_info = NULL;
170 DATA_BLOB session_key = data_blob(NULL, 0);
172 DATA_BLOB nullblob = data_blob(NULL, 0);
173 fstring real_username;
174 BOOL map_domainuser_to_guest = False;
175 PAC_LOGON_INFO *logon_info = NULL;
178 ZERO_STRUCT(pac_data);
180 ZERO_STRUCT(ap_rep_wrapped);
181 ZERO_STRUCT(response);
183 mem_ctx = talloc_init("reply_spnego_kerberos");
185 return ERROR_NT(NT_STATUS_NO_MEMORY);
187 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
188 talloc_destroy(mem_ctx);
189 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
192 ret = ads_verify_ticket(mem_ctx, lp_realm(), &ticket, &client, &pac_data, &ap_rep, &session_key);
194 data_blob_free(&ticket);
196 if (!NT_STATUS_IS_OK(ret)) {
197 DEBUG(1,("Failed to verify incoming ticket!\n"));
198 talloc_destroy(mem_ctx);
199 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
202 DEBUG(3,("Ticket name is [%s]\n", client));
204 p = strchr_m(client, '@');
206 DEBUG(3,("Doesn't look like a valid principal\n"));
207 data_blob_free(&ap_rep);
208 data_blob_free(&session_key);
210 talloc_destroy(mem_ctx);
211 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
216 /* save the PAC data if we have it */
219 logon_info = get_logon_info_from_pac(pac_data);
220 netsamlogon_cache_store( client, &logon_info->info3 );
223 if (!strequal(p+1, lp_realm())) {
224 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
225 if (!lp_allow_trusted_domains()) {
226 data_blob_free(&ap_rep);
227 data_blob_free(&session_key);
229 talloc_destroy(mem_ctx);
230 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
234 /* this gives a fully qualified user name (ie. with full realm).
235 that leads to very long usernames, but what else can we do? */
239 if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) {
241 unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, -1);
242 domain = netbios_domain_name;
243 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
247 /* If we have winbind running, we can (and must) shorten the
248 username by using the short netbios name. Otherwise we will
249 have inconsistent user names. With Kerberos, we get the
250 fully qualified realm, with ntlmssp we get the short
251 name. And even w2k3 does use ntlmssp if you for example
252 connect to an ip address. */
254 struct winbindd_request wb_request;
255 struct winbindd_response wb_response;
256 NSS_STATUS wb_result;
258 ZERO_STRUCT(wb_request);
259 ZERO_STRUCT(wb_response);
261 DEBUG(10, ("Mapping [%s] to short name\n", domain));
263 fstrcpy(wb_request.domain_name, domain);
265 wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
266 &wb_request, &wb_response);
268 if (wb_result == NSS_STATUS_SUCCESS) {
270 fstrcpy(netbios_domain_name,
271 wb_response.data.domain_info.name);
272 domain = netbios_domain_name;
274 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
276 DEBUG(3, ("Could not find short name -- winbind "
281 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
283 /* lookup the passwd struct, create a new user if necessary */
285 map_username( user );
287 pw = smb_getpwnam( mem_ctx, user, real_username, True );
290 /* this was originally the behavior of Samba 2.2, if a user
291 did not have a local uid but has been authenticated, then
292 map them to a guest account */
294 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
295 map_domainuser_to_guest = True;
296 fstrcpy(user,lp_guestaccount());
297 pw = smb_getpwnam( mem_ctx, user, real_username, True );
300 /* extra sanity check that the guest account is valid */
303 DEBUG(1,("Username %s is invalid on this system\n", user));
305 data_blob_free(&ap_rep);
306 data_blob_free(&session_key);
307 talloc_destroy(mem_ctx);
308 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
312 /* setup the string used by %U */
314 sub_set_smb_name( real_username );
315 reload_services(True);
316 if ( map_domainuser_to_guest ) {
317 make_server_info_guest(&server_info);
318 } else if (logon_info) {
319 ret = make_server_info_pac(&server_info, real_username, pw, logon_info);
321 if ( !NT_STATUS_IS_OK(ret) ) {
322 DEBUG(1,("make_server_info_pac failed: %s!\n",
325 data_blob_free(&ap_rep);
326 data_blob_free(&session_key);
327 talloc_destroy(mem_ctx);
328 return ERROR_NT(ret);
332 ret = make_server_info_pw(&server_info, real_username, pw);
334 if ( !NT_STATUS_IS_OK(ret) ) {
335 DEBUG(1,("make_server_info_pw failed: %s!\n",
338 data_blob_free(&ap_rep);
339 data_blob_free(&session_key);
340 talloc_destroy(mem_ctx);
341 return ERROR_NT(ret);
344 /* make_server_info_pw does not set the domain. Without this
345 * we end up with the local netbios name in substitutions for
348 if (server_info->sam_account != NULL) {
349 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
353 /* register_vuid keeps the server info */
354 /* register_vuid takes ownership of session_key, no need to free after this.
355 A better interface would copy it.... */
356 sess_vuid = register_vuid(server_info, session_key, nullblob, client);
360 if (sess_vuid == -1) {
361 ret = NT_STATUS_LOGON_FAILURE;
363 /* current_user_info is changed on new vuid */
364 reload_services( True );
366 set_message(outbuf,4,0,True);
367 SSVAL(outbuf, smb_vwv3, 0);
369 if (server_info->guest) {
370 SSVAL(outbuf,smb_vwv2,1);
373 SSVAL(outbuf, smb_uid, sess_vuid);
375 sessionsetup_start_signing_engine(server_info, inbuf);
378 /* wrap that up in a nice GSS-API wrapping */
379 if (NT_STATUS_IS_OK(ret)) {
380 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
382 ap_rep_wrapped = data_blob(NULL, 0);
384 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
385 reply_sesssetup_blob(conn, outbuf, response, ret);
387 data_blob_free(&ap_rep);
388 data_blob_free(&ap_rep_wrapped);
389 data_blob_free(&response);
390 talloc_destroy(mem_ctx);
392 return -1; /* already replied */
396 /****************************************************************************
397 Send a session setup reply, wrapped in SPNEGO.
398 Get vuid and check first.
399 End the NTLMSSP exchange context if we are OK/complete fail
400 This should be split into two functions, one to handle each
401 leg of the NTLM auth steps.
402 ***************************************************************************/
404 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
406 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
407 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
412 struct auth_serversupplied_info *server_info = NULL;
414 if (NT_STATUS_IS_OK(nt_status)) {
415 server_info = (*auth_ntlmssp_state)->server_info;
417 nt_status = do_map_to_guest(nt_status,
419 (*auth_ntlmssp_state)->ntlmssp_state->user,
420 (*auth_ntlmssp_state)->ntlmssp_state->domain);
423 if (NT_STATUS_IS_OK(nt_status)) {
425 DATA_BLOB nullblob = data_blob(NULL, 0);
426 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
428 /* register_vuid keeps the server info */
429 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
430 (*auth_ntlmssp_state)->server_info = NULL;
432 if (sess_vuid == -1) {
433 nt_status = NT_STATUS_LOGON_FAILURE;
436 /* current_user_info is changed on new vuid */
437 reload_services( True );
439 set_message(outbuf,4,0,True);
440 SSVAL(outbuf, smb_vwv3, 0);
442 if (server_info->guest) {
443 SSVAL(outbuf,smb_vwv2,1);
446 SSVAL(outbuf,smb_uid,sess_vuid);
448 sessionsetup_start_signing_engine(server_info, inbuf);
453 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
455 response = *ntlmssp_blob;
458 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
460 data_blob_free(&response);
463 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
464 and the other end, that we are not finished yet. */
466 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
467 /* NB. This is *NOT* an error case. JRA */
468 auth_ntlmssp_end(auth_ntlmssp_state);
469 /* Kill the intermediate vuid */
470 invalidate_vuid(vuid);
476 /****************************************************************************
477 Reply to a session setup spnego negotiate packet.
478 ****************************************************************************/
480 static int reply_spnego_negotiate(connection_struct *conn,
484 int length, int bufsize,
486 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
488 char *OIDs[ASN1_MAX_OIDS];
493 BOOL got_kerberos_mechanism = False;
497 /* parse out the OIDs and the first sec blob */
498 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
499 /* Kill the intermediate vuid */
500 invalidate_vuid(vuid);
502 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
505 /* only look at the first OID for determining the mechToken --
506 accoirding to RFC2478, we should choose the one we want
507 and renegotiate, but i smell a client bug here..
509 Problem observed when connecting to a member (samba box)
510 of an AD domain as a user in a Samba domain. Samba member
511 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
512 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
513 NTLMSSP mechtoken. --jerry */
516 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
517 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
518 got_kerberos_mechanism = True;
522 for (i=0;OIDs[i];i++) {
523 DEBUG(3,("Got OID %s\n", OIDs[i]));
526 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
529 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
530 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
531 length, bufsize, &secblob);
532 data_blob_free(&secblob);
533 /* Kill the intermediate vuid */
534 invalidate_vuid(vuid);
540 if (*auth_ntlmssp_state) {
541 auth_ntlmssp_end(auth_ntlmssp_state);
544 nt_status = auth_ntlmssp_start(auth_ntlmssp_state);
545 if (!NT_STATUS_IS_OK(nt_status)) {
546 /* Kill the intermediate vuid */
547 invalidate_vuid(vuid);
549 return ERROR_NT(nt_status);
552 nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
555 data_blob_free(&secblob);
557 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
558 &chal, nt_status, True);
560 data_blob_free(&chal);
562 /* already replied */
566 /****************************************************************************
567 Reply to a session setup spnego auth packet.
568 ****************************************************************************/
570 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
572 int length, int bufsize,
574 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
576 DATA_BLOB auth, auth_reply;
577 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
579 if (!spnego_parse_auth(blob1, &auth)) {
581 file_save("auth.dat", blob1.data, blob1.length);
583 /* Kill the intermediate vuid */
584 invalidate_vuid(vuid);
586 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
589 if (!*auth_ntlmssp_state) {
590 /* Kill the intermediate vuid */
591 invalidate_vuid(vuid);
593 /* auth before negotiatiate? */
594 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
597 nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
600 data_blob_free(&auth);
602 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
604 &auth_reply, nt_status, True);
606 data_blob_free(&auth_reply);
608 /* and tell smbd that we have already replied to this packet */
612 /****************************************************************************
613 Reply to a session setup command.
614 ****************************************************************************/
616 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
618 int length,int bufsize)
624 fstring native_os, native_lanman, primary_domain;
626 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
627 enum remote_arch_types ra_type = get_remote_arch();
628 int vuid = SVAL(inbuf,smb_uid);
629 user_struct *vuser = NULL;
631 DEBUG(3,("Doing spnego session setup\n"));
633 if (global_client_caps == 0) {
634 global_client_caps = IVAL(inbuf,smb_vwv10);
636 if (!(global_client_caps & CAP_STATUS32)) {
637 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
642 p = (uint8 *)smb_buf(inbuf);
644 if (data_blob_len == 0) {
645 /* an invalid request */
646 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
649 bufrem = smb_bufrem(inbuf, p);
650 /* pull the spnego blob */
651 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
654 file_save("negotiate.dat", blob1.data, blob1.length);
657 p2 = inbuf + smb_vwv13 + data_blob_len;
658 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
659 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
660 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
661 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
662 native_os, native_lanman, primary_domain));
664 if ( ra_type == RA_WIN2K ) {
665 /* Windows 2003 doesn't set the native lanman string,
666 but does set primary domain which is a bug I think */
668 if ( !strlen(native_lanman) )
669 ra_lanman_string( primary_domain );
671 ra_lanman_string( native_lanman );
674 vuser = get_partial_auth_user_struct(vuid);
676 vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);
678 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
681 vuser = get_partial_auth_user_struct(vuid);
685 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
688 SSVAL(outbuf,smb_uid,vuid);
690 if (blob1.data[0] == ASN1_APPLICATION(0)) {
691 /* its a negTokenTarg packet */
692 ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
693 &vuser->auth_ntlmssp_state);
694 data_blob_free(&blob1);
698 if (blob1.data[0] == ASN1_CONTEXT(1)) {
699 /* its a auth packet */
700 ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
701 &vuser->auth_ntlmssp_state);
702 data_blob_free(&blob1);
706 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
709 if (!vuser->auth_ntlmssp_state) {
710 nt_status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
711 if (!NT_STATUS_IS_OK(nt_status)) {
712 /* Kill the intermediate vuid */
713 invalidate_vuid(vuid);
715 return ERROR_NT(nt_status);
719 nt_status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
722 data_blob_free(&blob1);
724 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
725 &vuser->auth_ntlmssp_state,
726 &chal, nt_status, False);
727 data_blob_free(&chal);
731 /* what sort of packet is this? */
732 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
734 data_blob_free(&blob1);
736 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
739 /****************************************************************************
740 On new VC == 0, shutdown *all* old connections and users.
741 It seems that only NT4.x does this. At W2K and above (XP etc.).
742 a new session setup with VC==0 is ignored.
743 ****************************************************************************/
745 static int shutdown_other_smbds(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
748 struct sessionid *sessionid = (struct sessionid *)dbuf.dptr;
749 const char *ip = (const char *)p;
751 if (!process_exists(pid_to_procid(sessionid->pid))) {
755 if (sessionid->pid == sys_getpid()) {
759 if (strcmp(ip, sessionid->ip_addr) != 0) {
763 message_send_pid(pid_to_procid(sessionid->pid), MSG_SHUTDOWN,
768 static void setup_new_vc_session(void)
770 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
773 invalidate_all_vuids();
775 if (lp_reset_on_zero_vc()) {
776 session_traverse(shutdown_other_smbds, client_addr());
780 /****************************************************************************
781 Reply to a session setup command.
782 ****************************************************************************/
784 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
785 int length,int bufsize)
791 DATA_BLOB plaintext_password;
793 fstring sub_user; /* Sainitised username for substituion */
796 fstring native_lanman;
797 fstring primary_domain;
798 static BOOL done_sesssetup = False;
799 extern BOOL global_encrypted_passwords_negotiated;
800 extern BOOL global_spnego_negotiated;
801 extern enum protocol_types Protocol;
804 auth_usersupplied_info *user_info = NULL;
805 extern struct auth_context *negprot_global_auth_context;
806 auth_serversupplied_info *server_info = NULL;
810 BOOL doencrypt = global_encrypted_passwords_negotiated;
812 DATA_BLOB session_key;
814 START_PROFILE(SMBsesssetupX);
816 ZERO_STRUCT(lm_resp);
817 ZERO_STRUCT(nt_resp);
818 ZERO_STRUCT(plaintext_password);
820 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
822 /* a SPNEGO session setup has 12 command words, whereas a normal
823 NT1 session setup has 13. See the cifs spec. */
824 if (CVAL(inbuf, smb_wct) == 12 &&
825 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
826 if (!global_spnego_negotiated) {
827 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
828 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
831 if (SVAL(inbuf,smb_vwv4) == 0) {
832 setup_new_vc_session();
834 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
837 smb_bufsize = SVAL(inbuf,smb_vwv2);
839 if (Protocol < PROTOCOL_NT1) {
840 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
842 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
843 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
845 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
846 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
850 lm_resp = data_blob(smb_buf(inbuf), passlen1);
852 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
853 /* Ensure null termination */
854 plaintext_password.data[passlen1] = 0;
857 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
861 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
862 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
863 enum remote_arch_types ra_type = get_remote_arch();
864 char *p = smb_buf(inbuf);
865 char *save_p = smb_buf(inbuf);
869 if(global_client_caps == 0) {
870 global_client_caps = IVAL(inbuf,smb_vwv11);
872 if (!(global_client_caps & CAP_STATUS32)) {
873 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
876 /* client_caps is used as final determination if client is NT or Win95.
877 This is needed to return the correct error codes in some
881 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
882 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
883 set_remote_arch( RA_WIN95);
889 /* both Win95 and WinNT stuff up the password lengths for
890 non-encrypting systems. Uggh.
892 if passlen1==24 its a win95 system, and its setting the
893 password length incorrectly. Luckily it still works with the
894 default code because Win95 will null terminate the password
897 if passlen1>0 and passlen2>0 then maybe its a NT box and its
898 setting passlen2 to some random value which really stuffs
899 things up. we need to fix that one. */
901 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
905 /* check for nasty tricks */
906 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
907 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
910 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
911 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
914 /* Save the lanman2 password and the NT md4 password. */
916 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
921 lm_resp = data_blob(p, passlen1);
922 nt_resp = data_blob(p+passlen1, passlen2);
925 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
928 /* This was the previous fix. Not sure if it's still valid. JRA. */
929 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
930 /* NT4.0 stuffs up plaintext unicode password lengths... */
931 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
932 sizeof(pass), passlen1, STR_TERMINATE);
935 if (unic && (passlen2 == 0) && passlen1) {
936 /* Only a ascii plaintext password was sent. */
937 srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
938 passlen1, STR_TERMINATE|STR_ASCII);
940 srvstr_pull(inbuf, pass, smb_buf(inbuf),
941 sizeof(pass), unic ? passlen2 : passlen1,
944 plaintext_password = data_blob(pass, strlen(pass)+1);
947 p += passlen1 + passlen2;
948 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
949 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
950 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
951 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
953 /* not documented or decoded by Ethereal but there is one more string
954 in the extra bytes which is the same as the PrimaryDomain when using
955 extended security. Windows NT 4 and 2003 use this string to store
956 the native lanman string. Windows 9x does not include a string here
957 at all so we have to check if we have any extra bytes left */
959 byte_count = SVAL(inbuf, smb_vwv13);
960 if ( PTR_DIFF(p, save_p) < byte_count)
961 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
963 fstrcpy( primary_domain, "null" );
965 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
966 domain, native_os, native_lanman, primary_domain));
968 if ( ra_type == RA_WIN2K ) {
969 if ( strlen(native_lanman) == 0 )
970 ra_lanman_string( primary_domain );
972 ra_lanman_string( native_lanman );
977 if (SVAL(inbuf,smb_vwv4) == 0) {
978 setup_new_vc_session();
981 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
984 if (global_spnego_negotiated) {
986 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
988 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
989 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
991 fstrcpy(sub_user, user);
993 fstrcpy(sub_user, lp_guestaccount());
996 sub_set_smb_name(sub_user);
998 reload_services(True);
1000 if (lp_security() == SEC_SHARE) {
1001 /* in share level we should ignore any passwords */
1003 data_blob_free(&lm_resp);
1004 data_blob_free(&nt_resp);
1005 data_blob_clear_free(&plaintext_password);
1007 map_username(sub_user);
1008 add_session_user(sub_user);
1009 /* Then force it to null for the benfit of the code below */
1015 nt_status = check_guest_password(&server_info);
1017 } else if (doencrypt) {
1018 if (!negprot_global_auth_context) {
1019 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
1020 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
1022 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
1024 if (NT_STATUS_IS_OK(nt_status)) {
1025 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
1030 struct auth_context *plaintext_auth_context = NULL;
1032 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
1033 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
1035 if (!make_user_info_for_reply(&user_info,
1037 plaintext_password)) {
1038 nt_status = NT_STATUS_NO_MEMORY;
1041 if (NT_STATUS_IS_OK(nt_status)) {
1042 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
1046 (plaintext_auth_context->free)(&plaintext_auth_context);
1051 free_user_info(&user_info);
1053 if (!NT_STATUS_IS_OK(nt_status)) {
1054 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
1057 if (!NT_STATUS_IS_OK(nt_status)) {
1058 data_blob_free(&nt_resp);
1059 data_blob_free(&lm_resp);
1060 data_blob_clear_free(&plaintext_password);
1061 return ERROR_NT(nt_status_squash(nt_status));
1064 nt_status = create_local_token(server_info);
1065 if (!NT_STATUS_IS_OK(nt_status)) {
1066 DEBUG(10, ("create_local_token failed: %s\n",
1067 nt_errstr(nt_status)));
1068 data_blob_free(&nt_resp);
1069 data_blob_free(&lm_resp);
1070 data_blob_clear_free(&plaintext_password);
1071 return ERROR_NT(nt_status_squash(nt_status));
1074 if (server_info->user_session_key.data) {
1075 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
1077 session_key = data_blob(NULL, 0);
1080 data_blob_clear_free(&plaintext_password);
1082 /* it's ok - setup a reply */
1083 set_message(outbuf,3,0,True);
1084 if (Protocol >= PROTOCOL_NT1) {
1085 char *p = smb_buf( outbuf );
1086 p += add_signature( outbuf, p );
1087 set_message_end( outbuf, p );
1088 /* perhaps grab OS version here?? */
1091 if (server_info->guest) {
1092 SSVAL(outbuf,smb_vwv2,1);
1095 /* register the name and uid as being validated, so further connections
1096 to a uid can get through without a password, on the same VC */
1098 /* register_vuid keeps the server info */
1099 sess_vuid = register_vuid(server_info, session_key, nt_resp.data ? nt_resp : lm_resp, sub_user);
1100 data_blob_free(&nt_resp);
1101 data_blob_free(&lm_resp);
1103 if (sess_vuid == -1) {
1104 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
1107 /* current_user_info is changed on new vuid */
1108 reload_services( True );
1110 sessionsetup_start_signing_engine(server_info, inbuf);
1112 SSVAL(outbuf,smb_uid,sess_vuid);
1113 SSVAL(inbuf,smb_uid,sess_vuid);
1115 if (!done_sesssetup)
1116 max_send = MIN(max_send,smb_bufsize);
1118 done_sesssetup = True;
1120 END_PROFILE(SMBsesssetupX);
1121 return chain_reply(inbuf,outbuf,length,bufsize);