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 if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
99 ERROR_NT(nt_status_squash(nt_status));
101 set_message(outbuf,4,0,True);
103 nt_status = nt_status_squash(nt_status);
104 SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
105 SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
106 SSVAL(outbuf, smb_vwv3, blob.length);
109 /* should we cap this? */
110 memcpy(p, blob.data, blob.length);
113 p += add_signature( outbuf, p );
115 set_message_end(outbuf,p);
119 return send_smb(smbd_server_fd(),outbuf);
122 /****************************************************************************
123 Do a 'guest' logon, getting back the
124 ****************************************************************************/
126 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
128 struct auth_context *auth_context;
129 auth_usersupplied_info *user_info = NULL;
132 unsigned char chal[8];
136 DEBUG(3,("Got anonymous request\n"));
138 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) {
142 if (!make_user_info_guest(&user_info)) {
143 (auth_context->free)(&auth_context);
144 return NT_STATUS_NO_MEMORY;
147 nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info);
148 (auth_context->free)(&auth_context);
149 free_user_info(&user_info);
155 /****************************************************************************
156 reply to a session setup spnego negotiate packet for kerberos
157 ****************************************************************************/
158 static int reply_spnego_kerberos(connection_struct *conn,
159 char *inbuf, char *outbuf,
160 int length, int bufsize,
165 char *client, *p, *domain;
166 fstring netbios_domain_name;
172 DATA_BLOB ap_rep, ap_rep_wrapped, response;
173 auth_serversupplied_info *server_info = NULL;
174 DATA_BLOB session_key = data_blob(NULL, 0);
176 DATA_BLOB nullblob = data_blob(NULL, 0);
177 fstring real_username;
178 BOOL map_domainuser_to_guest = False;
179 BOOL username_was_mapped;
180 PAC_LOGON_INFO *logon_info = NULL;
183 ZERO_STRUCT(pac_data);
185 ZERO_STRUCT(ap_rep_wrapped);
186 ZERO_STRUCT(response);
188 mem_ctx = talloc_init("reply_spnego_kerberos");
190 return ERROR_NT(nt_status_squash(NT_STATUS_NO_MEMORY));
192 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
193 talloc_destroy(mem_ctx);
194 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
197 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket, &client, &pac_data, &ap_rep, &session_key);
199 data_blob_free(&ticket);
201 if (!NT_STATUS_IS_OK(ret)) {
202 DEBUG(1,("Failed to verify incoming ticket!\n"));
203 talloc_destroy(mem_ctx);
204 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
207 DEBUG(3,("Ticket name is [%s]\n", client));
209 p = strchr_m(client, '@');
211 DEBUG(3,("Doesn't look like a valid principal\n"));
212 data_blob_free(&ap_rep);
213 data_blob_free(&session_key);
215 talloc_destroy(mem_ctx);
216 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
221 /* save the PAC data if we have it */
224 logon_info = get_logon_info_from_pac(pac_data);
226 netsamlogon_cache_store( client, &logon_info->info3 );
230 if (!strequal(p+1, lp_realm())) {
231 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
232 if (!lp_allow_trusted_domains()) {
233 data_blob_free(&ap_rep);
234 data_blob_free(&session_key);
236 talloc_destroy(mem_ctx);
237 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
241 /* this gives a fully qualified user name (ie. with full realm).
242 that leads to very long usernames, but what else can we do? */
246 if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) {
248 unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, -1);
249 domain = netbios_domain_name;
250 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
254 /* If we have winbind running, we can (and must) shorten the
255 username by using the short netbios name. Otherwise we will
256 have inconsistent user names. With Kerberos, we get the
257 fully qualified realm, with ntlmssp we get the short
258 name. And even w2k3 does use ntlmssp if you for example
259 connect to an ip address. */
261 struct winbindd_request wb_request;
262 struct winbindd_response wb_response;
263 NSS_STATUS wb_result;
265 ZERO_STRUCT(wb_request);
266 ZERO_STRUCT(wb_response);
268 DEBUG(10, ("Mapping [%s] to short name\n", domain));
270 fstrcpy(wb_request.domain_name, domain);
272 wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
273 &wb_request, &wb_response);
275 if (wb_result == NSS_STATUS_SUCCESS) {
277 fstrcpy(netbios_domain_name,
278 wb_response.data.domain_info.name);
279 domain = netbios_domain_name;
281 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
283 DEBUG(3, ("Could not find short name -- winbind "
288 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
290 /* lookup the passwd struct, create a new user if necessary */
292 username_was_mapped = map_username( user );
294 pw = smb_getpwnam( mem_ctx, user, real_username, True );
297 /* if a real user check pam account restrictions */
298 /* only really perfomed if "obey pam restriction" is true */
299 /* do this before an eventual mappign to guest occurs */
300 ret = smb_pam_accountcheck(pw->pw_name);
301 if ( !NT_STATUS_IS_OK(ret)) {
302 DEBUG(1, ("PAM account restriction prevents user login\n"));
303 data_blob_free(&ap_rep);
304 data_blob_free(&session_key);
305 TALLOC_FREE(mem_ctx);
306 return ERROR_NT(nt_status_squash(ret));
312 /* this was originally the behavior of Samba 2.2, if a user
313 did not have a local uid but has been authenticated, then
314 map them to a guest account */
316 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
317 map_domainuser_to_guest = True;
318 fstrcpy(user,lp_guestaccount());
319 pw = smb_getpwnam( mem_ctx, user, real_username, True );
322 /* extra sanity check that the guest account is valid */
325 DEBUG(1,("Username %s is invalid on this system\n", user));
327 data_blob_free(&ap_rep);
328 data_blob_free(&session_key);
329 TALLOC_FREE(mem_ctx);
330 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
334 /* setup the string used by %U */
336 sub_set_smb_name( real_username );
339 reload_services(True);
341 if ( map_domainuser_to_guest ) {
342 make_server_info_guest(&server_info);
343 } else if (logon_info) {
344 /* pass the unmapped username here since map_username()
345 will be called again from inside make_server_info_info3() */
347 ret = make_server_info_info3(mem_ctx, client, domain,
348 &server_info, &logon_info->info3);
349 if ( !NT_STATUS_IS_OK(ret) ) {
350 DEBUG(1,("make_server_info_info3 failed: %s!\n",
353 data_blob_free(&ap_rep);
354 data_blob_free(&session_key);
355 TALLOC_FREE(mem_ctx);
356 return ERROR_NT(nt_status_squash(ret));
360 ret = make_server_info_pw(&server_info, real_username, pw);
362 if ( !NT_STATUS_IS_OK(ret) ) {
363 DEBUG(1,("make_server_info_pw failed: %s!\n",
366 data_blob_free(&ap_rep);
367 data_blob_free(&session_key);
368 TALLOC_FREE(mem_ctx);
369 return ERROR_NT(nt_status_squash(ret));
372 /* make_server_info_pw does not set the domain. Without this
373 * we end up with the local netbios name in substitutions for
376 if (server_info->sam_account != NULL) {
377 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
381 server_info->was_mapped |= username_was_mapped;
383 /* we need to build the token for the user. make_server_info_guest()
386 if ( !server_info->ptok ) {
387 ret = create_local_token( server_info );
388 if ( !NT_STATUS_IS_OK(ret) ) {
390 data_blob_free(&ap_rep);
391 data_blob_free(&session_key);
392 TALLOC_FREE( mem_ctx );
393 TALLOC_FREE( server_info );
394 return ERROR_NT(nt_status_squash(ret));
398 /* register_vuid keeps the server info */
399 /* register_vuid takes ownership of session_key, no need to free after this.
400 A better interface would copy it.... */
401 sess_vuid = register_vuid(server_info, session_key, nullblob, client);
405 if (sess_vuid == UID_FIELD_INVALID ) {
406 ret = NT_STATUS_LOGON_FAILURE;
408 /* current_user_info is changed on new vuid */
409 reload_services( True );
411 set_message(outbuf,4,0,True);
412 SSVAL(outbuf, smb_vwv3, 0);
414 if (server_info->guest) {
415 SSVAL(outbuf,smb_vwv2,1);
418 SSVAL(outbuf, smb_uid, sess_vuid);
420 sessionsetup_start_signing_engine(server_info, inbuf);
423 /* wrap that up in a nice GSS-API wrapping */
424 if (NT_STATUS_IS_OK(ret)) {
425 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
427 ap_rep_wrapped = data_blob(NULL, 0);
429 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
430 reply_sesssetup_blob(conn, outbuf, response, ret);
432 data_blob_free(&ap_rep);
433 data_blob_free(&ap_rep_wrapped);
434 data_blob_free(&response);
435 TALLOC_FREE(mem_ctx);
437 return -1; /* already replied */
441 /****************************************************************************
442 Send a session setup reply, wrapped in SPNEGO.
443 Get vuid and check first.
444 End the NTLMSSP exchange context if we are OK/complete fail
445 This should be split into two functions, one to handle each
446 leg of the NTLM auth steps.
447 ***************************************************************************/
449 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
451 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
452 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
457 struct auth_serversupplied_info *server_info = NULL;
459 if (NT_STATUS_IS_OK(nt_status)) {
460 server_info = (*auth_ntlmssp_state)->server_info;
462 nt_status = do_map_to_guest(nt_status,
464 (*auth_ntlmssp_state)->ntlmssp_state->user,
465 (*auth_ntlmssp_state)->ntlmssp_state->domain);
468 if (NT_STATUS_IS_OK(nt_status)) {
470 DATA_BLOB nullblob = data_blob(NULL, 0);
471 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
473 /* register_vuid keeps the server info */
474 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
475 (*auth_ntlmssp_state)->server_info = NULL;
477 if (sess_vuid == UID_FIELD_INVALID ) {
478 nt_status = NT_STATUS_LOGON_FAILURE;
481 /* current_user_info is changed on new vuid */
482 reload_services( True );
484 set_message(outbuf,4,0,True);
485 SSVAL(outbuf, smb_vwv3, 0);
487 if (server_info->guest) {
488 SSVAL(outbuf,smb_vwv2,1);
491 SSVAL(outbuf,smb_uid,sess_vuid);
493 sessionsetup_start_signing_engine(server_info, inbuf);
498 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
500 response = *ntlmssp_blob;
503 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
505 data_blob_free(&response);
508 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
509 and the other end, that we are not finished yet. */
511 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
512 /* NB. This is *NOT* an error case. JRA */
513 auth_ntlmssp_end(auth_ntlmssp_state);
514 /* Kill the intermediate vuid */
515 invalidate_vuid(vuid);
521 /****************************************************************************
522 Reply to a session setup spnego negotiate packet.
523 ****************************************************************************/
525 static int reply_spnego_negotiate(connection_struct *conn,
529 int length, int bufsize,
531 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
533 char *OIDs[ASN1_MAX_OIDS];
538 BOOL got_kerberos_mechanism = False;
542 /* parse out the OIDs and the first sec blob */
543 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
544 /* Kill the intermediate vuid */
545 invalidate_vuid(vuid);
547 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
550 /* only look at the first OID for determining the mechToken --
551 accoirding to RFC2478, we should choose the one we want
552 and renegotiate, but i smell a client bug here..
554 Problem observed when connecting to a member (samba box)
555 of an AD domain as a user in a Samba domain. Samba member
556 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
557 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
558 NTLMSSP mechtoken. --jerry */
561 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
562 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
563 got_kerberos_mechanism = True;
567 for (i=0;OIDs[i];i++) {
568 DEBUG(3,("Got OID %s\n", OIDs[i]));
571 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
574 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
575 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
576 length, bufsize, &secblob);
577 data_blob_free(&secblob);
578 /* Kill the intermediate vuid */
579 invalidate_vuid(vuid);
585 if (*auth_ntlmssp_state) {
586 auth_ntlmssp_end(auth_ntlmssp_state);
589 nt_status = auth_ntlmssp_start(auth_ntlmssp_state);
590 if (!NT_STATUS_IS_OK(nt_status)) {
591 /* Kill the intermediate vuid */
592 invalidate_vuid(vuid);
594 return ERROR_NT(nt_status_squash(nt_status));
597 nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
600 data_blob_free(&secblob);
602 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
603 &chal, nt_status, True);
605 data_blob_free(&chal);
607 /* already replied */
611 /****************************************************************************
612 Reply to a session setup spnego auth packet.
613 ****************************************************************************/
615 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
617 int length, int bufsize,
619 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
621 DATA_BLOB auth, auth_reply;
622 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
624 if (!spnego_parse_auth(blob1, &auth)) {
626 file_save("auth.dat", blob1.data, blob1.length);
628 /* Kill the intermediate vuid */
629 invalidate_vuid(vuid);
631 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
634 if (!*auth_ntlmssp_state) {
635 /* Kill the intermediate vuid */
636 invalidate_vuid(vuid);
638 /* auth before negotiatiate? */
639 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
642 nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
645 data_blob_free(&auth);
647 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
649 &auth_reply, nt_status, True);
651 data_blob_free(&auth_reply);
653 /* and tell smbd that we have already replied to this packet */
657 /****************************************************************************
658 Reply to a session setup command.
659 conn POINTER CAN BE NULL HERE !
660 ****************************************************************************/
662 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
664 int length,int bufsize)
670 fstring native_os, native_lanman, primary_domain;
672 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
673 enum remote_arch_types ra_type = get_remote_arch();
674 int vuid = SVAL(inbuf,smb_uid);
675 user_struct *vuser = NULL;
677 DEBUG(3,("Doing spnego session setup\n"));
679 if (global_client_caps == 0) {
680 global_client_caps = IVAL(inbuf,smb_vwv10);
682 if (!(global_client_caps & CAP_STATUS32)) {
683 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
688 p = (uint8 *)smb_buf(inbuf);
690 if (data_blob_len == 0) {
691 /* an invalid request */
692 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
695 bufrem = smb_bufrem(inbuf, p);
696 /* pull the spnego blob */
697 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
700 file_save("negotiate.dat", blob1.data, blob1.length);
703 p2 = inbuf + smb_vwv13 + data_blob_len;
704 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
705 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
706 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
707 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
708 native_os, native_lanman, primary_domain));
710 if ( ra_type == RA_WIN2K ) {
711 /* Windows 2003 doesn't set the native lanman string,
712 but does set primary domain which is a bug I think */
714 if ( !strlen(native_lanman) )
715 ra_lanman_string( primary_domain );
717 ra_lanman_string( native_lanman );
720 vuser = get_partial_auth_user_struct(vuid);
722 vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);
723 if (vuid == UID_FIELD_INVALID ) {
724 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
727 vuser = get_partial_auth_user_struct(vuid);
731 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
734 SSVAL(outbuf,smb_uid,vuid);
736 if (blob1.data[0] == ASN1_APPLICATION(0)) {
737 /* its a negTokenTarg packet */
738 ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
739 &vuser->auth_ntlmssp_state);
740 data_blob_free(&blob1);
744 if (blob1.data[0] == ASN1_CONTEXT(1)) {
745 /* its a auth packet */
746 ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
747 &vuser->auth_ntlmssp_state);
748 data_blob_free(&blob1);
752 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
755 if (!vuser->auth_ntlmssp_state) {
756 nt_status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
757 if (!NT_STATUS_IS_OK(nt_status)) {
758 /* Kill the intermediate vuid */
759 invalidate_vuid(vuid);
761 return ERROR_NT(nt_status_squash(nt_status));
765 nt_status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
768 data_blob_free(&blob1);
770 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
771 &vuser->auth_ntlmssp_state,
772 &chal, nt_status, False);
773 data_blob_free(&chal);
777 /* what sort of packet is this? */
778 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
780 data_blob_free(&blob1);
782 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
785 /****************************************************************************
786 On new VC == 0, shutdown *all* old connections and users.
787 It seems that only NT4.x does this. At W2K and above (XP etc.).
788 a new session setup with VC==0 is ignored.
789 ****************************************************************************/
791 static int shutdown_other_smbds(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
794 struct sessionid *sessionid = (struct sessionid *)dbuf.dptr;
795 const char *ip = (const char *)p;
797 if (!process_exists(pid_to_procid(sessionid->pid))) {
801 if (sessionid->pid == sys_getpid()) {
805 if (strcmp(ip, sessionid->ip_addr) != 0) {
809 message_send_pid(pid_to_procid(sessionid->pid), MSG_SHUTDOWN,
814 static void setup_new_vc_session(void)
816 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
819 invalidate_all_vuids();
821 if (lp_reset_on_zero_vc()) {
822 session_traverse(shutdown_other_smbds, client_addr());
826 /****************************************************************************
827 Reply to a session setup command.
828 ****************************************************************************/
830 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
831 int length,int bufsize)
837 DATA_BLOB plaintext_password;
839 fstring sub_user; /* Sainitised username for substituion */
842 fstring native_lanman;
843 fstring primary_domain;
844 static BOOL done_sesssetup = False;
845 extern BOOL global_encrypted_passwords_negotiated;
846 extern BOOL global_spnego_negotiated;
847 extern enum protocol_types Protocol;
850 auth_usersupplied_info *user_info = NULL;
851 extern struct auth_context *negprot_global_auth_context;
852 auth_serversupplied_info *server_info = NULL;
856 BOOL doencrypt = global_encrypted_passwords_negotiated;
858 DATA_BLOB session_key;
860 START_PROFILE(SMBsesssetupX);
862 ZERO_STRUCT(lm_resp);
863 ZERO_STRUCT(nt_resp);
864 ZERO_STRUCT(plaintext_password);
866 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
868 /* a SPNEGO session setup has 12 command words, whereas a normal
869 NT1 session setup has 13. See the cifs spec. */
870 if (CVAL(inbuf, smb_wct) == 12 &&
871 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
872 if (!global_spnego_negotiated) {
873 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
874 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
877 if (SVAL(inbuf,smb_vwv4) == 0) {
878 setup_new_vc_session();
880 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
883 smb_bufsize = SVAL(inbuf,smb_vwv2);
885 if (Protocol < PROTOCOL_NT1) {
886 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
888 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
889 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
891 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
892 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
896 lm_resp = data_blob(smb_buf(inbuf), passlen1);
898 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
899 /* Ensure null termination */
900 plaintext_password.data[passlen1] = 0;
903 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
907 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
908 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
909 enum remote_arch_types ra_type = get_remote_arch();
910 char *p = smb_buf(inbuf);
911 char *save_p = smb_buf(inbuf);
915 if(global_client_caps == 0) {
916 global_client_caps = IVAL(inbuf,smb_vwv11);
918 if (!(global_client_caps & CAP_STATUS32)) {
919 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
922 /* client_caps is used as final determination if client is NT or Win95.
923 This is needed to return the correct error codes in some
927 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
928 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
929 set_remote_arch( RA_WIN95);
935 /* both Win95 and WinNT stuff up the password lengths for
936 non-encrypting systems. Uggh.
938 if passlen1==24 its a win95 system, and its setting the
939 password length incorrectly. Luckily it still works with the
940 default code because Win95 will null terminate the password
943 if passlen1>0 and passlen2>0 then maybe its a NT box and its
944 setting passlen2 to some random value which really stuffs
945 things up. we need to fix that one. */
947 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
951 /* check for nasty tricks */
952 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
953 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
956 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
957 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
960 /* Save the lanman2 password and the NT md4 password. */
962 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
967 lm_resp = data_blob(p, passlen1);
968 nt_resp = data_blob(p+passlen1, passlen2);
971 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
974 /* This was the previous fix. Not sure if it's still valid. JRA. */
975 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
976 /* NT4.0 stuffs up plaintext unicode password lengths... */
977 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
978 sizeof(pass), passlen1, STR_TERMINATE);
981 if (unic && (passlen2 == 0) && passlen1) {
982 /* Only a ascii plaintext password was sent. */
983 srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
984 passlen1, STR_TERMINATE|STR_ASCII);
986 srvstr_pull(inbuf, pass, smb_buf(inbuf),
987 sizeof(pass), unic ? passlen2 : passlen1,
990 plaintext_password = data_blob(pass, strlen(pass)+1);
993 p += passlen1 + passlen2;
994 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
995 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
996 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
997 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
999 /* not documented or decoded by Ethereal but there is one more string
1000 in the extra bytes which is the same as the PrimaryDomain when using
1001 extended security. Windows NT 4 and 2003 use this string to store
1002 the native lanman string. Windows 9x does not include a string here
1003 at all so we have to check if we have any extra bytes left */
1005 byte_count = SVAL(inbuf, smb_vwv13);
1006 if ( PTR_DIFF(p, save_p) < byte_count)
1007 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
1009 fstrcpy( primary_domain, "null" );
1011 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1012 domain, native_os, native_lanman, primary_domain));
1014 if ( ra_type == RA_WIN2K ) {
1015 if ( strlen(native_lanman) == 0 )
1016 ra_lanman_string( primary_domain );
1018 ra_lanman_string( native_lanman );
1023 if (SVAL(inbuf,smb_vwv4) == 0) {
1024 setup_new_vc_session();
1027 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
1030 if (global_spnego_negotiated) {
1032 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
1034 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
1035 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1037 fstrcpy(sub_user, user);
1039 fstrcpy(sub_user, lp_guestaccount());
1042 sub_set_smb_name(sub_user);
1044 reload_services(True);
1046 if (lp_security() == SEC_SHARE) {
1047 /* in share level we should ignore any passwords */
1049 data_blob_free(&lm_resp);
1050 data_blob_free(&nt_resp);
1051 data_blob_clear_free(&plaintext_password);
1053 map_username(sub_user);
1054 add_session_user(sub_user);
1055 /* Then force it to null for the benfit of the code below */
1061 nt_status = check_guest_password(&server_info);
1063 } else if (doencrypt) {
1064 if (!negprot_global_auth_context) {
1065 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
1066 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1068 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
1070 if (NT_STATUS_IS_OK(nt_status)) {
1071 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
1076 struct auth_context *plaintext_auth_context = NULL;
1079 nt_status = make_auth_context_subsystem(&plaintext_auth_context);
1081 if (NT_STATUS_IS_OK(nt_status)) {
1082 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
1084 if (!make_user_info_for_reply(&user_info,
1086 plaintext_password)) {
1087 nt_status = NT_STATUS_NO_MEMORY;
1090 if (NT_STATUS_IS_OK(nt_status)) {
1091 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
1095 (plaintext_auth_context->free)(&plaintext_auth_context);
1100 free_user_info(&user_info);
1102 if (!NT_STATUS_IS_OK(nt_status)) {
1103 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
1106 if (!NT_STATUS_IS_OK(nt_status)) {
1107 data_blob_free(&nt_resp);
1108 data_blob_free(&lm_resp);
1109 data_blob_clear_free(&plaintext_password);
1110 return ERROR_NT(nt_status_squash(nt_status));
1113 /* Ensure we can't possible take a code path leading to a null defref. */
1115 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1118 nt_status = create_local_token(server_info);
1119 if (!NT_STATUS_IS_OK(nt_status)) {
1120 DEBUG(10, ("create_local_token failed: %s\n",
1121 nt_errstr(nt_status)));
1122 data_blob_free(&nt_resp);
1123 data_blob_free(&lm_resp);
1124 data_blob_clear_free(&plaintext_password);
1125 return ERROR_NT(nt_status_squash(nt_status));
1128 if (server_info->user_session_key.data) {
1129 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
1131 session_key = data_blob(NULL, 0);
1134 data_blob_clear_free(&plaintext_password);
1136 /* it's ok - setup a reply */
1137 set_message(outbuf,3,0,True);
1138 if (Protocol >= PROTOCOL_NT1) {
1139 char *p = smb_buf( outbuf );
1140 p += add_signature( outbuf, p );
1141 set_message_end( outbuf, p );
1142 /* perhaps grab OS version here?? */
1145 if (server_info->guest) {
1146 SSVAL(outbuf,smb_vwv2,1);
1149 /* register the name and uid as being validated, so further connections
1150 to a uid can get through without a password, on the same VC */
1152 if (lp_security() == SEC_SHARE) {
1153 sess_vuid = UID_FIELD_INVALID;
1154 data_blob_free(&session_key);
1155 TALLOC_FREE(server_info);
1157 /* register_vuid keeps the server info */
1158 sess_vuid = register_vuid(server_info, session_key,
1159 nt_resp.data ? nt_resp : lm_resp,
1161 if (sess_vuid == UID_FIELD_INVALID) {
1162 data_blob_free(&nt_resp);
1163 data_blob_free(&lm_resp);
1164 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1167 /* current_user_info is changed on new vuid */
1168 reload_services( True );
1170 sessionsetup_start_signing_engine(server_info, inbuf);
1173 data_blob_free(&nt_resp);
1174 data_blob_free(&lm_resp);
1176 SSVAL(outbuf,smb_uid,sess_vuid);
1177 SSVAL(inbuf,smb_uid,sess_vuid);
1179 if (!done_sesssetup)
1180 max_send = MIN(max_send,smb_bufsize);
1182 done_sesssetup = True;
1184 END_PROFILE(SMBsesssetupX);
1185 return chain_reply(inbuf,outbuf,length,bufsize);