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_destroy(mem_ctx);
307 return ERROR_NT(nt_status_squash(ret));
313 /* this was originally the behavior of Samba 2.2, if a user
314 did not have a local uid but has been authenticated, then
315 map them to a guest account */
317 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
318 map_domainuser_to_guest = True;
319 fstrcpy(user,lp_guestaccount());
320 pw = smb_getpwnam( mem_ctx, user, real_username, True );
323 /* extra sanity check that the guest account is valid */
326 DEBUG(1,("Username %s is invalid on this system\n", user));
328 data_blob_free(&ap_rep);
329 data_blob_free(&session_key);
330 talloc_destroy(mem_ctx);
331 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
335 /* setup the string used by %U */
337 sub_set_smb_name( real_username );
338 reload_services(True);
340 if ( map_domainuser_to_guest ) {
341 make_server_info_guest(&server_info);
342 } else if (logon_info) {
343 /* pass the unmapped username here since map_username()
344 will be called again from inside make_server_info_info3() */
346 ret = make_server_info_info3(mem_ctx, client, domain,
347 &server_info, &logon_info->info3);
348 if ( !NT_STATUS_IS_OK(ret) ) {
349 DEBUG(1,("make_server_info_info3 failed: %s!\n",
352 data_blob_free(&ap_rep);
353 data_blob_free(&session_key);
354 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);
370 return ERROR_NT(nt_status_squash(ret));
373 /* make_server_info_pw does not set the domain. Without this
374 * we end up with the local netbios name in substitutions for
377 if (server_info->sam_account != NULL) {
378 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
382 server_info->was_mapped |= username_was_mapped;
384 /* we need to build the token for the user. make_server_info_guest()
387 if ( !server_info->ptok ) {
388 ret = create_local_token( server_info );
389 if ( !NT_STATUS_IS_OK(ret) ) {
391 data_blob_free(&ap_rep);
392 data_blob_free(&session_key);
394 TALLOC_FREE( mem_ctx );
395 TALLOC_FREE( server_info );
396 return ERROR_NT(nt_status_squash(ret));
400 /* register_vuid keeps the server info */
401 /* register_vuid takes ownership of session_key, no need to free after this.
402 A better interface would copy it.... */
403 sess_vuid = register_vuid(server_info, session_key, nullblob, client);
407 if (sess_vuid == UID_FIELD_INVALID ) {
408 ret = NT_STATUS_LOGON_FAILURE;
410 /* current_user_info is changed on new vuid */
411 reload_services( True );
413 set_message(outbuf,4,0,True);
414 SSVAL(outbuf, smb_vwv3, 0);
416 if (server_info->guest) {
417 SSVAL(outbuf,smb_vwv2,1);
420 SSVAL(outbuf, smb_uid, sess_vuid);
422 sessionsetup_start_signing_engine(server_info, inbuf);
425 /* wrap that up in a nice GSS-API wrapping */
426 if (NT_STATUS_IS_OK(ret)) {
427 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
429 ap_rep_wrapped = data_blob(NULL, 0);
431 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
432 reply_sesssetup_blob(conn, outbuf, response, ret);
434 data_blob_free(&ap_rep);
435 data_blob_free(&ap_rep_wrapped);
436 data_blob_free(&response);
437 TALLOC_FREE(mem_ctx);
440 return -1; /* already replied */
444 /****************************************************************************
445 Send a session setup reply, wrapped in SPNEGO.
446 Get vuid and check first.
447 End the NTLMSSP exchange context if we are OK/complete fail
448 This should be split into two functions, one to handle each
449 leg of the NTLM auth steps.
450 ***************************************************************************/
452 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
454 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
455 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
460 struct auth_serversupplied_info *server_info = NULL;
462 if (NT_STATUS_IS_OK(nt_status)) {
463 server_info = (*auth_ntlmssp_state)->server_info;
465 nt_status = do_map_to_guest(nt_status,
467 (*auth_ntlmssp_state)->ntlmssp_state->user,
468 (*auth_ntlmssp_state)->ntlmssp_state->domain);
471 if (NT_STATUS_IS_OK(nt_status)) {
473 DATA_BLOB nullblob = data_blob(NULL, 0);
474 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
476 /* register_vuid keeps the server info */
477 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
478 (*auth_ntlmssp_state)->server_info = NULL;
480 if (sess_vuid == UID_FIELD_INVALID ) {
481 nt_status = NT_STATUS_LOGON_FAILURE;
484 /* current_user_info is changed on new vuid */
485 reload_services( True );
487 set_message(outbuf,4,0,True);
488 SSVAL(outbuf, smb_vwv3, 0);
490 if (server_info->guest) {
491 SSVAL(outbuf,smb_vwv2,1);
494 SSVAL(outbuf,smb_uid,sess_vuid);
496 sessionsetup_start_signing_engine(server_info, inbuf);
501 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
503 response = *ntlmssp_blob;
506 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
508 data_blob_free(&response);
511 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
512 and the other end, that we are not finished yet. */
514 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
515 /* NB. This is *NOT* an error case. JRA */
516 auth_ntlmssp_end(auth_ntlmssp_state);
517 /* Kill the intermediate vuid */
518 invalidate_vuid(vuid);
524 /****************************************************************************
525 Reply to a session setup spnego negotiate packet.
526 ****************************************************************************/
528 static int reply_spnego_negotiate(connection_struct *conn,
532 int length, int bufsize,
534 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
536 char *OIDs[ASN1_MAX_OIDS];
541 BOOL got_kerberos_mechanism = False;
545 /* parse out the OIDs and the first sec blob */
546 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
547 /* Kill the intermediate vuid */
548 invalidate_vuid(vuid);
550 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
553 /* only look at the first OID for determining the mechToken --
554 accoirding to RFC2478, we should choose the one we want
555 and renegotiate, but i smell a client bug here..
557 Problem observed when connecting to a member (samba box)
558 of an AD domain as a user in a Samba domain. Samba member
559 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
560 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
561 NTLMSSP mechtoken. --jerry */
564 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
565 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
566 got_kerberos_mechanism = True;
570 for (i=0;OIDs[i];i++) {
571 DEBUG(3,("Got OID %s\n", OIDs[i]));
574 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
577 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
578 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
579 length, bufsize, &secblob);
580 data_blob_free(&secblob);
581 /* Kill the intermediate vuid */
582 invalidate_vuid(vuid);
588 if (*auth_ntlmssp_state) {
589 auth_ntlmssp_end(auth_ntlmssp_state);
592 nt_status = auth_ntlmssp_start(auth_ntlmssp_state);
593 if (!NT_STATUS_IS_OK(nt_status)) {
594 /* Kill the intermediate vuid */
595 invalidate_vuid(vuid);
597 return ERROR_NT(nt_status_squash(nt_status));
600 nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
603 data_blob_free(&secblob);
605 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
606 &chal, nt_status, True);
608 data_blob_free(&chal);
610 /* already replied */
614 /****************************************************************************
615 Reply to a session setup spnego auth packet.
616 ****************************************************************************/
618 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
620 int length, int bufsize,
622 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
624 DATA_BLOB auth, auth_reply;
625 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
627 if (!spnego_parse_auth(blob1, &auth)) {
629 file_save("auth.dat", blob1.data, blob1.length);
631 /* Kill the intermediate vuid */
632 invalidate_vuid(vuid);
634 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
637 if (!*auth_ntlmssp_state) {
638 /* Kill the intermediate vuid */
639 invalidate_vuid(vuid);
641 /* auth before negotiatiate? */
642 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
645 nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
648 data_blob_free(&auth);
650 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
652 &auth_reply, nt_status, True);
654 data_blob_free(&auth_reply);
656 /* and tell smbd that we have already replied to this packet */
660 /****************************************************************************
661 Reply to a session setup command.
662 conn POINTER CAN BE NULL HERE !
663 ****************************************************************************/
665 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
667 int length,int bufsize)
673 fstring native_os, native_lanman, primary_domain;
675 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
676 enum remote_arch_types ra_type = get_remote_arch();
677 int vuid = SVAL(inbuf,smb_uid);
678 user_struct *vuser = NULL;
680 DEBUG(3,("Doing spnego session setup\n"));
682 if (global_client_caps == 0) {
683 global_client_caps = IVAL(inbuf,smb_vwv10);
685 if (!(global_client_caps & CAP_STATUS32)) {
686 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
691 p = (uint8 *)smb_buf(inbuf);
693 if (data_blob_len == 0) {
694 /* an invalid request */
695 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
698 bufrem = smb_bufrem(inbuf, p);
699 /* pull the spnego blob */
700 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
703 file_save("negotiate.dat", blob1.data, blob1.length);
706 p2 = inbuf + smb_vwv13 + data_blob_len;
707 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
708 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
709 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
710 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
711 native_os, native_lanman, primary_domain));
713 if ( ra_type == RA_WIN2K ) {
714 /* Windows 2003 doesn't set the native lanman string,
715 but does set primary domain which is a bug I think */
717 if ( !strlen(native_lanman) )
718 ra_lanman_string( primary_domain );
720 ra_lanman_string( native_lanman );
723 vuser = get_partial_auth_user_struct(vuid);
725 vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);
726 if (vuid == UID_FIELD_INVALID ) {
727 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
730 vuser = get_partial_auth_user_struct(vuid);
734 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
737 SSVAL(outbuf,smb_uid,vuid);
739 if (blob1.data[0] == ASN1_APPLICATION(0)) {
740 /* its a negTokenTarg packet */
741 ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
742 &vuser->auth_ntlmssp_state);
743 data_blob_free(&blob1);
747 if (blob1.data[0] == ASN1_CONTEXT(1)) {
748 /* its a auth packet */
749 ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
750 &vuser->auth_ntlmssp_state);
751 data_blob_free(&blob1);
755 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
758 if (!vuser->auth_ntlmssp_state) {
759 nt_status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
760 if (!NT_STATUS_IS_OK(nt_status)) {
761 /* Kill the intermediate vuid */
762 invalidate_vuid(vuid);
764 return ERROR_NT(nt_status_squash(nt_status));
768 nt_status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
771 data_blob_free(&blob1);
773 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
774 &vuser->auth_ntlmssp_state,
775 &chal, nt_status, False);
776 data_blob_free(&chal);
780 /* what sort of packet is this? */
781 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
783 data_blob_free(&blob1);
785 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
788 /****************************************************************************
789 On new VC == 0, shutdown *all* old connections and users.
790 It seems that only NT4.x does this. At W2K and above (XP etc.).
791 a new session setup with VC==0 is ignored.
792 ****************************************************************************/
794 static int shutdown_other_smbds(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
797 struct sessionid *sessionid = (struct sessionid *)dbuf.dptr;
798 const char *ip = (const char *)p;
800 if (!process_exists(pid_to_procid(sessionid->pid))) {
804 if (sessionid->pid == sys_getpid()) {
808 if (strcmp(ip, sessionid->ip_addr) != 0) {
812 message_send_pid(pid_to_procid(sessionid->pid), MSG_SHUTDOWN,
817 static void setup_new_vc_session(void)
819 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
822 invalidate_all_vuids();
824 if (lp_reset_on_zero_vc()) {
825 session_traverse(shutdown_other_smbds, client_addr());
829 /****************************************************************************
830 Reply to a session setup command.
831 ****************************************************************************/
833 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
834 int length,int bufsize)
840 DATA_BLOB plaintext_password;
842 fstring sub_user; /* Sainitised username for substituion */
845 fstring native_lanman;
846 fstring primary_domain;
847 static BOOL done_sesssetup = False;
848 extern BOOL global_encrypted_passwords_negotiated;
849 extern BOOL global_spnego_negotiated;
850 extern enum protocol_types Protocol;
853 auth_usersupplied_info *user_info = NULL;
854 extern struct auth_context *negprot_global_auth_context;
855 auth_serversupplied_info *server_info = NULL;
859 BOOL doencrypt = global_encrypted_passwords_negotiated;
861 DATA_BLOB session_key;
863 START_PROFILE(SMBsesssetupX);
865 ZERO_STRUCT(lm_resp);
866 ZERO_STRUCT(nt_resp);
867 ZERO_STRUCT(plaintext_password);
869 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
871 /* a SPNEGO session setup has 12 command words, whereas a normal
872 NT1 session setup has 13. See the cifs spec. */
873 if (CVAL(inbuf, smb_wct) == 12 &&
874 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
875 if (!global_spnego_negotiated) {
876 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
877 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
880 if (SVAL(inbuf,smb_vwv4) == 0) {
881 setup_new_vc_session();
883 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
886 smb_bufsize = SVAL(inbuf,smb_vwv2);
888 if (Protocol < PROTOCOL_NT1) {
889 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
891 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
892 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
894 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
895 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
899 lm_resp = data_blob(smb_buf(inbuf), passlen1);
901 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
902 /* Ensure null termination */
903 plaintext_password.data[passlen1] = 0;
906 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
910 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
911 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
912 enum remote_arch_types ra_type = get_remote_arch();
913 char *p = smb_buf(inbuf);
914 char *save_p = smb_buf(inbuf);
918 if(global_client_caps == 0) {
919 global_client_caps = IVAL(inbuf,smb_vwv11);
921 if (!(global_client_caps & CAP_STATUS32)) {
922 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
925 /* client_caps is used as final determination if client is NT or Win95.
926 This is needed to return the correct error codes in some
930 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
931 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
932 set_remote_arch( RA_WIN95);
938 /* both Win95 and WinNT stuff up the password lengths for
939 non-encrypting systems. Uggh.
941 if passlen1==24 its a win95 system, and its setting the
942 password length incorrectly. Luckily it still works with the
943 default code because Win95 will null terminate the password
946 if passlen1>0 and passlen2>0 then maybe its a NT box and its
947 setting passlen2 to some random value which really stuffs
948 things up. we need to fix that one. */
950 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
954 /* check for nasty tricks */
955 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
956 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
959 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
960 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
963 /* Save the lanman2 password and the NT md4 password. */
965 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
970 lm_resp = data_blob(p, passlen1);
971 nt_resp = data_blob(p+passlen1, passlen2);
974 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
977 /* This was the previous fix. Not sure if it's still valid. JRA. */
978 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
979 /* NT4.0 stuffs up plaintext unicode password lengths... */
980 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
981 sizeof(pass), passlen1, STR_TERMINATE);
984 if (unic && (passlen2 == 0) && passlen1) {
985 /* Only a ascii plaintext password was sent. */
986 srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
987 passlen1, STR_TERMINATE|STR_ASCII);
989 srvstr_pull(inbuf, pass, smb_buf(inbuf),
990 sizeof(pass), unic ? passlen2 : passlen1,
993 plaintext_password = data_blob(pass, strlen(pass)+1);
996 p += passlen1 + passlen2;
997 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
998 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
999 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
1000 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
1002 /* not documented or decoded by Ethereal but there is one more string
1003 in the extra bytes which is the same as the PrimaryDomain when using
1004 extended security. Windows NT 4 and 2003 use this string to store
1005 the native lanman string. Windows 9x does not include a string here
1006 at all so we have to check if we have any extra bytes left */
1008 byte_count = SVAL(inbuf, smb_vwv13);
1009 if ( PTR_DIFF(p, save_p) < byte_count)
1010 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
1012 fstrcpy( primary_domain, "null" );
1014 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1015 domain, native_os, native_lanman, primary_domain));
1017 if ( ra_type == RA_WIN2K ) {
1018 if ( strlen(native_lanman) == 0 )
1019 ra_lanman_string( primary_domain );
1021 ra_lanman_string( native_lanman );
1026 if (SVAL(inbuf,smb_vwv4) == 0) {
1027 setup_new_vc_session();
1030 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
1033 if (global_spnego_negotiated) {
1035 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
1037 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
1038 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1040 fstrcpy(sub_user, user);
1042 fstrcpy(sub_user, lp_guestaccount());
1045 sub_set_smb_name(sub_user);
1047 reload_services(True);
1049 if (lp_security() == SEC_SHARE) {
1050 /* in share level we should ignore any passwords */
1052 data_blob_free(&lm_resp);
1053 data_blob_free(&nt_resp);
1054 data_blob_clear_free(&plaintext_password);
1056 map_username(sub_user);
1057 add_session_user(sub_user);
1058 /* Then force it to null for the benfit of the code below */
1064 nt_status = check_guest_password(&server_info);
1066 } else if (doencrypt) {
1067 if (!negprot_global_auth_context) {
1068 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
1069 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1071 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
1073 if (NT_STATUS_IS_OK(nt_status)) {
1074 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
1079 struct auth_context *plaintext_auth_context = NULL;
1082 nt_status = make_auth_context_subsystem(&plaintext_auth_context);
1084 if (NT_STATUS_IS_OK(nt_status)) {
1085 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
1087 if (!make_user_info_for_reply(&user_info,
1089 plaintext_password)) {
1090 nt_status = NT_STATUS_NO_MEMORY;
1093 if (NT_STATUS_IS_OK(nt_status)) {
1094 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
1098 (plaintext_auth_context->free)(&plaintext_auth_context);
1103 free_user_info(&user_info);
1105 if (!NT_STATUS_IS_OK(nt_status)) {
1106 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
1109 if (!NT_STATUS_IS_OK(nt_status)) {
1110 data_blob_free(&nt_resp);
1111 data_blob_free(&lm_resp);
1112 data_blob_clear_free(&plaintext_password);
1113 return ERROR_NT(nt_status_squash(nt_status));
1116 /* Ensure we can't possible take a code path leading to a null defref. */
1118 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1121 nt_status = create_local_token(server_info);
1122 if (!NT_STATUS_IS_OK(nt_status)) {
1123 DEBUG(10, ("create_local_token failed: %s\n",
1124 nt_errstr(nt_status)));
1125 data_blob_free(&nt_resp);
1126 data_blob_free(&lm_resp);
1127 data_blob_clear_free(&plaintext_password);
1128 return ERROR_NT(nt_status_squash(nt_status));
1131 if (server_info->user_session_key.data) {
1132 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
1134 session_key = data_blob(NULL, 0);
1137 data_blob_clear_free(&plaintext_password);
1139 /* it's ok - setup a reply */
1140 set_message(outbuf,3,0,True);
1141 if (Protocol >= PROTOCOL_NT1) {
1142 char *p = smb_buf( outbuf );
1143 p += add_signature( outbuf, p );
1144 set_message_end( outbuf, p );
1145 /* perhaps grab OS version here?? */
1148 if (server_info->guest) {
1149 SSVAL(outbuf,smb_vwv2,1);
1152 /* register the name and uid as being validated, so further connections
1153 to a uid can get through without a password, on the same VC */
1155 if (lp_security() == SEC_SHARE) {
1156 sess_vuid = UID_FIELD_INVALID;
1157 data_blob_free(&session_key);
1158 TALLOC_FREE(server_info);
1160 /* register_vuid keeps the server info */
1161 sess_vuid = register_vuid(server_info, session_key,
1162 nt_resp.data ? nt_resp : lm_resp,
1164 if (sess_vuid == UID_FIELD_INVALID) {
1165 data_blob_free(&nt_resp);
1166 data_blob_free(&lm_resp);
1167 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1170 /* current_user_info is changed on new vuid */
1171 reload_services( True );
1173 sessionsetup_start_signing_engine(server_info, inbuf);
1176 data_blob_free(&nt_resp);
1177 data_blob_free(&lm_resp);
1179 SSVAL(outbuf,smb_uid,sess_vuid);
1180 SSVAL(inbuf,smb_uid,sess_vuid);
1182 if (!done_sesssetup)
1183 max_send = MIN(max_send,smb_bufsize);
1185 done_sesssetup = True;
1187 END_PROFILE(SMBsesssetupX);
1188 return chain_reply(inbuf,outbuf,length,bufsize);