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 PAC_LOGON_INFO *logon_info = NULL;
182 ZERO_STRUCT(pac_data);
184 ZERO_STRUCT(ap_rep_wrapped);
185 ZERO_STRUCT(response);
187 mem_ctx = talloc_init("reply_spnego_kerberos");
189 return ERROR_NT(nt_status_squash(NT_STATUS_NO_MEMORY));
191 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
192 talloc_destroy(mem_ctx);
193 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
196 ret = ads_verify_ticket(mem_ctx, lp_realm(), &ticket, &client, &pac_data, &ap_rep, &session_key);
198 data_blob_free(&ticket);
200 if (!NT_STATUS_IS_OK(ret)) {
201 DEBUG(1,("Failed to verify incoming ticket!\n"));
202 talloc_destroy(mem_ctx);
203 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
206 DEBUG(3,("Ticket name is [%s]\n", client));
208 p = strchr_m(client, '@');
210 DEBUG(3,("Doesn't look like a valid principal\n"));
211 data_blob_free(&ap_rep);
212 data_blob_free(&session_key);
214 talloc_destroy(mem_ctx);
215 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
220 /* save the PAC data if we have it */
223 logon_info = get_logon_info_from_pac(pac_data);
225 netsamlogon_cache_store( client, &logon_info->info3 );
229 if (!strequal(p+1, lp_realm())) {
230 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
231 if (!lp_allow_trusted_domains()) {
232 data_blob_free(&ap_rep);
233 data_blob_free(&session_key);
235 talloc_destroy(mem_ctx);
236 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
240 /* this gives a fully qualified user name (ie. with full realm).
241 that leads to very long usernames, but what else can we do? */
245 if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) {
247 unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, -1);
248 domain = netbios_domain_name;
249 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
253 /* If we have winbind running, we can (and must) shorten the
254 username by using the short netbios name. Otherwise we will
255 have inconsistent user names. With Kerberos, we get the
256 fully qualified realm, with ntlmssp we get the short
257 name. And even w2k3 does use ntlmssp if you for example
258 connect to an ip address. */
260 struct winbindd_request wb_request;
261 struct winbindd_response wb_response;
262 NSS_STATUS wb_result;
264 ZERO_STRUCT(wb_request);
265 ZERO_STRUCT(wb_response);
267 DEBUG(10, ("Mapping [%s] to short name\n", domain));
269 fstrcpy(wb_request.domain_name, domain);
271 wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
272 &wb_request, &wb_response);
274 if (wb_result == NSS_STATUS_SUCCESS) {
276 fstrcpy(netbios_domain_name,
277 wb_response.data.domain_info.name);
278 domain = netbios_domain_name;
280 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
282 DEBUG(3, ("Could not find short name -- winbind "
287 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
289 /* lookup the passwd struct, create a new user if necessary */
291 map_username( user );
293 pw = smb_getpwnam( mem_ctx, user, real_username, True );
296 /* this was originally the behavior of Samba 2.2, if a user
297 did not have a local uid but has been authenticated, then
298 map them to a guest account */
300 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
301 map_domainuser_to_guest = True;
302 fstrcpy(user,lp_guestaccount());
303 pw = smb_getpwnam( mem_ctx, user, real_username, True );
306 /* extra sanity check that the guest account is valid */
309 DEBUG(1,("Username %s is invalid on this system\n", user));
311 data_blob_free(&ap_rep);
312 data_blob_free(&session_key);
313 talloc_destroy(mem_ctx);
314 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
318 /* setup the string used by %U */
320 sub_set_smb_name( real_username );
321 reload_services(True);
322 if ( map_domainuser_to_guest ) {
323 make_server_info_guest(&server_info);
324 } else if (logon_info) {
325 ret = make_server_info_info3(mem_ctx, real_username, real_username, domain,
326 &server_info, &logon_info->info3);
327 if ( !NT_STATUS_IS_OK(ret) ) {
328 DEBUG(1,("make_server_info_info3 failed: %s!\n",
331 data_blob_free(&ap_rep);
332 data_blob_free(&session_key);
333 talloc_destroy(mem_ctx);
334 return ERROR_NT(nt_status_squash(ret));
338 ret = make_server_info_pw(&server_info, real_username, pw);
340 if ( !NT_STATUS_IS_OK(ret) ) {
341 DEBUG(1,("make_server_info_pw failed: %s!\n",
344 data_blob_free(&ap_rep);
345 data_blob_free(&session_key);
346 talloc_destroy(mem_ctx);
347 return ERROR_NT(nt_status_squash(ret));
350 /* make_server_info_pw does not set the domain. Without this
351 * we end up with the local netbios name in substitutions for
354 if (server_info->sam_account != NULL) {
355 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
359 /* we need to build the token for the user. make_server_info_guest()
362 if ( !server_info->ptok ) {
363 ret = create_local_token( server_info );
364 if ( !NT_STATUS_IS_OK(ret) ) {
366 data_blob_free(&ap_rep);
367 data_blob_free(&session_key);
368 TALLOC_FREE( mem_ctx );
369 TALLOC_FREE( server_info );
370 return ERROR_NT(nt_status_squash(ret));
374 /* register_vuid keeps the server info */
375 /* register_vuid takes ownership of session_key, no need to free after this.
376 A better interface would copy it.... */
377 sess_vuid = register_vuid(server_info, session_key, nullblob, client);
381 if (sess_vuid == UID_FIELD_INVALID ) {
382 ret = NT_STATUS_LOGON_FAILURE;
384 /* current_user_info is changed on new vuid */
385 reload_services( True );
387 set_message(outbuf,4,0,True);
388 SSVAL(outbuf, smb_vwv3, 0);
390 if (server_info->guest) {
391 SSVAL(outbuf,smb_vwv2,1);
394 SSVAL(outbuf, smb_uid, sess_vuid);
396 sessionsetup_start_signing_engine(server_info, inbuf);
399 /* wrap that up in a nice GSS-API wrapping */
400 if (NT_STATUS_IS_OK(ret)) {
401 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
403 ap_rep_wrapped = data_blob(NULL, 0);
405 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
406 reply_sesssetup_blob(conn, outbuf, response, ret);
408 data_blob_free(&ap_rep);
409 data_blob_free(&ap_rep_wrapped);
410 data_blob_free(&response);
411 talloc_destroy(mem_ctx);
413 return -1; /* already replied */
417 /****************************************************************************
418 Send a session setup reply, wrapped in SPNEGO.
419 Get vuid and check first.
420 End the NTLMSSP exchange context if we are OK/complete fail
421 This should be split into two functions, one to handle each
422 leg of the NTLM auth steps.
423 ***************************************************************************/
425 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
427 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
428 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
433 struct auth_serversupplied_info *server_info = NULL;
435 if (NT_STATUS_IS_OK(nt_status)) {
436 server_info = (*auth_ntlmssp_state)->server_info;
438 nt_status = do_map_to_guest(nt_status,
440 (*auth_ntlmssp_state)->ntlmssp_state->user,
441 (*auth_ntlmssp_state)->ntlmssp_state->domain);
444 if (NT_STATUS_IS_OK(nt_status)) {
446 DATA_BLOB nullblob = data_blob(NULL, 0);
447 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
449 /* register_vuid keeps the server info */
450 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
451 (*auth_ntlmssp_state)->server_info = NULL;
453 if (sess_vuid == UID_FIELD_INVALID ) {
454 nt_status = NT_STATUS_LOGON_FAILURE;
457 /* current_user_info is changed on new vuid */
458 reload_services( True );
460 set_message(outbuf,4,0,True);
461 SSVAL(outbuf, smb_vwv3, 0);
463 if (server_info->guest) {
464 SSVAL(outbuf,smb_vwv2,1);
467 SSVAL(outbuf,smb_uid,sess_vuid);
469 sessionsetup_start_signing_engine(server_info, inbuf);
474 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
476 response = *ntlmssp_blob;
479 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
481 data_blob_free(&response);
484 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
485 and the other end, that we are not finished yet. */
487 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
488 /* NB. This is *NOT* an error case. JRA */
489 auth_ntlmssp_end(auth_ntlmssp_state);
490 /* Kill the intermediate vuid */
491 invalidate_vuid(vuid);
497 /****************************************************************************
498 Reply to a session setup spnego negotiate packet.
499 ****************************************************************************/
501 static int reply_spnego_negotiate(connection_struct *conn,
505 int length, int bufsize,
507 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
509 char *OIDs[ASN1_MAX_OIDS];
514 BOOL got_kerberos_mechanism = False;
518 /* parse out the OIDs and the first sec blob */
519 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
520 /* Kill the intermediate vuid */
521 invalidate_vuid(vuid);
523 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
526 /* only look at the first OID for determining the mechToken --
527 accoirding to RFC2478, we should choose the one we want
528 and renegotiate, but i smell a client bug here..
530 Problem observed when connecting to a member (samba box)
531 of an AD domain as a user in a Samba domain. Samba member
532 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
533 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
534 NTLMSSP mechtoken. --jerry */
537 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
538 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
539 got_kerberos_mechanism = True;
543 for (i=0;OIDs[i];i++) {
544 DEBUG(3,("Got OID %s\n", OIDs[i]));
547 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
550 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
551 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
552 length, bufsize, &secblob);
553 data_blob_free(&secblob);
554 /* Kill the intermediate vuid */
555 invalidate_vuid(vuid);
561 if (*auth_ntlmssp_state) {
562 auth_ntlmssp_end(auth_ntlmssp_state);
565 nt_status = auth_ntlmssp_start(auth_ntlmssp_state);
566 if (!NT_STATUS_IS_OK(nt_status)) {
567 /* Kill the intermediate vuid */
568 invalidate_vuid(vuid);
570 return ERROR_NT(nt_status_squash(nt_status));
573 nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
576 data_blob_free(&secblob);
578 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
579 &chal, nt_status, True);
581 data_blob_free(&chal);
583 /* already replied */
587 /****************************************************************************
588 Reply to a session setup spnego auth packet.
589 ****************************************************************************/
591 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
593 int length, int bufsize,
595 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
597 DATA_BLOB auth, auth_reply;
598 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
600 if (!spnego_parse_auth(blob1, &auth)) {
602 file_save("auth.dat", blob1.data, blob1.length);
604 /* Kill the intermediate vuid */
605 invalidate_vuid(vuid);
607 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
610 if (!*auth_ntlmssp_state) {
611 /* Kill the intermediate vuid */
612 invalidate_vuid(vuid);
614 /* auth before negotiatiate? */
615 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
618 nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
621 data_blob_free(&auth);
623 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
625 &auth_reply, nt_status, True);
627 data_blob_free(&auth_reply);
629 /* and tell smbd that we have already replied to this packet */
633 /****************************************************************************
634 Reply to a session setup command.
635 ****************************************************************************/
637 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
639 int length,int bufsize)
645 fstring native_os, native_lanman, primary_domain;
647 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
648 enum remote_arch_types ra_type = get_remote_arch();
649 int vuid = SVAL(inbuf,smb_uid);
650 user_struct *vuser = NULL;
652 DEBUG(3,("Doing spnego session setup\n"));
654 if (global_client_caps == 0) {
655 global_client_caps = IVAL(inbuf,smb_vwv10);
657 if (!(global_client_caps & CAP_STATUS32)) {
658 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
663 p = (uint8 *)smb_buf(inbuf);
665 if (data_blob_len == 0) {
666 /* an invalid request */
667 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
670 bufrem = smb_bufrem(inbuf, p);
671 /* pull the spnego blob */
672 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
675 file_save("negotiate.dat", blob1.data, blob1.length);
678 p2 = inbuf + smb_vwv13 + data_blob_len;
679 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
680 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
681 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
682 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
683 native_os, native_lanman, primary_domain));
685 if ( ra_type == RA_WIN2K ) {
686 /* Windows 2003 doesn't set the native lanman string,
687 but does set primary domain which is a bug I think */
689 if ( !strlen(native_lanman) )
690 ra_lanman_string( primary_domain );
692 ra_lanman_string( native_lanman );
695 vuser = get_partial_auth_user_struct(vuid);
697 vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);
698 if (vuid == UID_FIELD_INVALID ) {
699 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
702 vuser = get_partial_auth_user_struct(vuid);
706 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
709 SSVAL(outbuf,smb_uid,vuid);
711 if (blob1.data[0] == ASN1_APPLICATION(0)) {
712 /* its a negTokenTarg packet */
713 ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
714 &vuser->auth_ntlmssp_state);
715 data_blob_free(&blob1);
719 if (blob1.data[0] == ASN1_CONTEXT(1)) {
720 /* its a auth packet */
721 ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
722 &vuser->auth_ntlmssp_state);
723 data_blob_free(&blob1);
727 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
730 if (!vuser->auth_ntlmssp_state) {
731 nt_status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
732 if (!NT_STATUS_IS_OK(nt_status)) {
733 /* Kill the intermediate vuid */
734 invalidate_vuid(vuid);
736 return ERROR_NT(nt_status_squash(nt_status));
740 nt_status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
743 data_blob_free(&blob1);
745 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
746 &vuser->auth_ntlmssp_state,
747 &chal, nt_status, False);
748 data_blob_free(&chal);
752 /* what sort of packet is this? */
753 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
755 data_blob_free(&blob1);
757 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
760 /****************************************************************************
761 On new VC == 0, shutdown *all* old connections and users.
762 It seems that only NT4.x does this. At W2K and above (XP etc.).
763 a new session setup with VC==0 is ignored.
764 ****************************************************************************/
766 static int shutdown_other_smbds(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
769 struct sessionid *sessionid = (struct sessionid *)dbuf.dptr;
770 const char *ip = (const char *)p;
772 if (!process_exists(pid_to_procid(sessionid->pid))) {
776 if (sessionid->pid == sys_getpid()) {
780 if (strcmp(ip, sessionid->ip_addr) != 0) {
784 message_send_pid(pid_to_procid(sessionid->pid), MSG_SHUTDOWN,
789 static void setup_new_vc_session(void)
791 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
794 invalidate_all_vuids();
796 if (lp_reset_on_zero_vc()) {
797 session_traverse(shutdown_other_smbds, client_addr());
801 /****************************************************************************
802 Reply to a session setup command.
803 ****************************************************************************/
805 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
806 int length,int bufsize)
812 DATA_BLOB plaintext_password;
814 fstring sub_user; /* Sainitised username for substituion */
817 fstring native_lanman;
818 fstring primary_domain;
819 static BOOL done_sesssetup = False;
820 extern BOOL global_encrypted_passwords_negotiated;
821 extern BOOL global_spnego_negotiated;
822 extern enum protocol_types Protocol;
825 auth_usersupplied_info *user_info = NULL;
826 extern struct auth_context *negprot_global_auth_context;
827 auth_serversupplied_info *server_info = NULL;
831 BOOL doencrypt = global_encrypted_passwords_negotiated;
833 DATA_BLOB session_key;
835 START_PROFILE(SMBsesssetupX);
837 ZERO_STRUCT(lm_resp);
838 ZERO_STRUCT(nt_resp);
839 ZERO_STRUCT(plaintext_password);
841 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
843 /* a SPNEGO session setup has 12 command words, whereas a normal
844 NT1 session setup has 13. See the cifs spec. */
845 if (CVAL(inbuf, smb_wct) == 12 &&
846 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
847 if (!global_spnego_negotiated) {
848 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
849 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
852 if (SVAL(inbuf,smb_vwv4) == 0) {
853 setup_new_vc_session();
855 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
858 smb_bufsize = SVAL(inbuf,smb_vwv2);
860 if (Protocol < PROTOCOL_NT1) {
861 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
863 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
864 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
866 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
867 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
871 lm_resp = data_blob(smb_buf(inbuf), passlen1);
873 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
874 /* Ensure null termination */
875 plaintext_password.data[passlen1] = 0;
878 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
882 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
883 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
884 enum remote_arch_types ra_type = get_remote_arch();
885 char *p = smb_buf(inbuf);
886 char *save_p = smb_buf(inbuf);
890 if(global_client_caps == 0) {
891 global_client_caps = IVAL(inbuf,smb_vwv11);
893 if (!(global_client_caps & CAP_STATUS32)) {
894 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
897 /* client_caps is used as final determination if client is NT or Win95.
898 This is needed to return the correct error codes in some
902 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
903 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
904 set_remote_arch( RA_WIN95);
910 /* both Win95 and WinNT stuff up the password lengths for
911 non-encrypting systems. Uggh.
913 if passlen1==24 its a win95 system, and its setting the
914 password length incorrectly. Luckily it still works with the
915 default code because Win95 will null terminate the password
918 if passlen1>0 and passlen2>0 then maybe its a NT box and its
919 setting passlen2 to some random value which really stuffs
920 things up. we need to fix that one. */
922 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
926 /* check for nasty tricks */
927 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
928 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
931 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
932 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
935 /* Save the lanman2 password and the NT md4 password. */
937 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
942 lm_resp = data_blob(p, passlen1);
943 nt_resp = data_blob(p+passlen1, passlen2);
946 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
949 /* This was the previous fix. Not sure if it's still valid. JRA. */
950 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
951 /* NT4.0 stuffs up plaintext unicode password lengths... */
952 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
953 sizeof(pass), passlen1, STR_TERMINATE);
956 if (unic && (passlen2 == 0) && passlen1) {
957 /* Only a ascii plaintext password was sent. */
958 srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
959 passlen1, STR_TERMINATE|STR_ASCII);
961 srvstr_pull(inbuf, pass, smb_buf(inbuf),
962 sizeof(pass), unic ? passlen2 : passlen1,
965 plaintext_password = data_blob(pass, strlen(pass)+1);
968 p += passlen1 + passlen2;
969 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
970 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
971 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
972 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
974 /* not documented or decoded by Ethereal but there is one more string
975 in the extra bytes which is the same as the PrimaryDomain when using
976 extended security. Windows NT 4 and 2003 use this string to store
977 the native lanman string. Windows 9x does not include a string here
978 at all so we have to check if we have any extra bytes left */
980 byte_count = SVAL(inbuf, smb_vwv13);
981 if ( PTR_DIFF(p, save_p) < byte_count)
982 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
984 fstrcpy( primary_domain, "null" );
986 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
987 domain, native_os, native_lanman, primary_domain));
989 if ( ra_type == RA_WIN2K ) {
990 if ( strlen(native_lanman) == 0 )
991 ra_lanman_string( primary_domain );
993 ra_lanman_string( native_lanman );
998 if (SVAL(inbuf,smb_vwv4) == 0) {
999 setup_new_vc_session();
1002 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
1005 if (global_spnego_negotiated) {
1007 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
1009 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
1010 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1012 fstrcpy(sub_user, user);
1014 fstrcpy(sub_user, lp_guestaccount());
1017 sub_set_smb_name(sub_user);
1019 reload_services(True);
1021 if (lp_security() == SEC_SHARE) {
1022 /* in share level we should ignore any passwords */
1024 data_blob_free(&lm_resp);
1025 data_blob_free(&nt_resp);
1026 data_blob_clear_free(&plaintext_password);
1028 map_username(sub_user);
1029 add_session_user(sub_user);
1030 /* Then force it to null for the benfit of the code below */
1036 nt_status = check_guest_password(&server_info);
1038 } else if (doencrypt) {
1039 if (!negprot_global_auth_context) {
1040 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
1041 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1043 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
1045 if (NT_STATUS_IS_OK(nt_status)) {
1046 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
1051 struct auth_context *plaintext_auth_context = NULL;
1054 nt_status = make_auth_context_subsystem(&plaintext_auth_context);
1056 if (NT_STATUS_IS_OK(nt_status)) {
1057 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
1059 if (!make_user_info_for_reply(&user_info,
1061 plaintext_password)) {
1062 nt_status = NT_STATUS_NO_MEMORY;
1065 if (NT_STATUS_IS_OK(nt_status)) {
1066 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
1070 (plaintext_auth_context->free)(&plaintext_auth_context);
1075 free_user_info(&user_info);
1077 if (!NT_STATUS_IS_OK(nt_status)) {
1078 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
1081 if (!NT_STATUS_IS_OK(nt_status)) {
1082 data_blob_free(&nt_resp);
1083 data_blob_free(&lm_resp);
1084 data_blob_clear_free(&plaintext_password);
1085 return ERROR_NT(nt_status_squash(nt_status));
1088 /* Ensure we can't possible take a code path leading to a null defref. */
1090 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1093 nt_status = create_local_token(server_info);
1094 if (!NT_STATUS_IS_OK(nt_status)) {
1095 DEBUG(10, ("create_local_token failed: %s\n",
1096 nt_errstr(nt_status)));
1097 data_blob_free(&nt_resp);
1098 data_blob_free(&lm_resp);
1099 data_blob_clear_free(&plaintext_password);
1100 return ERROR_NT(nt_status_squash(nt_status));
1103 if (server_info->user_session_key.data) {
1104 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
1106 session_key = data_blob(NULL, 0);
1109 data_blob_clear_free(&plaintext_password);
1111 /* it's ok - setup a reply */
1112 set_message(outbuf,3,0,True);
1113 if (Protocol >= PROTOCOL_NT1) {
1114 char *p = smb_buf( outbuf );
1115 p += add_signature( outbuf, p );
1116 set_message_end( outbuf, p );
1117 /* perhaps grab OS version here?? */
1120 if (server_info->guest) {
1121 SSVAL(outbuf,smb_vwv2,1);
1124 /* register the name and uid as being validated, so further connections
1125 to a uid can get through without a password, on the same VC */
1127 /* register_vuid keeps the server info */
1128 sess_vuid = register_vuid(server_info, session_key, nt_resp.data ? nt_resp : lm_resp, sub_user);
1129 data_blob_free(&nt_resp);
1130 data_blob_free(&lm_resp);
1132 if (sess_vuid == UID_FIELD_INVALID) {
1133 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1136 /* current_user_info is changed on new vuid */
1137 reload_services( True );
1139 sessionsetup_start_signing_engine(server_info, inbuf);
1141 SSVAL(outbuf,smb_uid,sess_vuid);
1142 SSVAL(inbuf,smb_uid,sess_vuid);
1144 if (!done_sesssetup)
1145 max_send = MIN(max_send,smb_bufsize);
1147 done_sesssetup = True;
1149 END_PROFILE(SMBsesssetupX);
1150 return chain_reply(inbuf,outbuf,length,bufsize);