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 /* this was originally the behavior of Samba 2.2, if a user
298 did not have a local uid but has been authenticated, then
299 map them to a guest account */
301 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
302 map_domainuser_to_guest = True;
303 fstrcpy(user,lp_guestaccount());
304 pw = smb_getpwnam( mem_ctx, user, real_username, True );
307 /* extra sanity check that the guest account is valid */
310 DEBUG(1,("Username %s is invalid on this system\n", user));
312 data_blob_free(&ap_rep);
313 data_blob_free(&session_key);
314 talloc_destroy(mem_ctx);
315 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
319 /* setup the string used by %U */
321 sub_set_smb_name( real_username );
322 reload_services(True);
323 if ( map_domainuser_to_guest ) {
324 make_server_info_guest(&server_info);
325 } else if (logon_info) {
326 ret = make_server_info_info3(mem_ctx, real_username, domain,
327 &server_info, &logon_info->info3);
328 if ( !NT_STATUS_IS_OK(ret) ) {
329 DEBUG(1,("make_server_info_info3 failed: %s!\n",
332 data_blob_free(&ap_rep);
333 data_blob_free(&session_key);
334 talloc_destroy(mem_ctx);
335 return ERROR_NT(nt_status_squash(ret));
339 ret = make_server_info_pw(&server_info, real_username, pw);
341 if ( !NT_STATUS_IS_OK(ret) ) {
342 DEBUG(1,("make_server_info_pw failed: %s!\n",
345 data_blob_free(&ap_rep);
346 data_blob_free(&session_key);
347 talloc_destroy(mem_ctx);
348 return ERROR_NT(nt_status_squash(ret));
351 /* make_server_info_pw does not set the domain. Without this
352 * we end up with the local netbios name in substitutions for
355 if (server_info->sam_account != NULL) {
356 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
360 server_info->was_mapped |= username_was_mapped;
362 /* we need to build the token for the user. make_server_info_guest()
365 if ( !server_info->ptok ) {
366 ret = create_local_token( server_info );
367 if ( !NT_STATUS_IS_OK(ret) ) {
369 data_blob_free(&ap_rep);
370 data_blob_free(&session_key);
371 TALLOC_FREE( mem_ctx );
372 TALLOC_FREE( server_info );
373 return ERROR_NT(nt_status_squash(ret));
377 /* register_vuid keeps the server info */
378 /* register_vuid takes ownership of session_key, no need to free after this.
379 A better interface would copy it.... */
380 sess_vuid = register_vuid(server_info, session_key, nullblob, client);
384 if (sess_vuid == UID_FIELD_INVALID ) {
385 ret = NT_STATUS_LOGON_FAILURE;
387 /* current_user_info is changed on new vuid */
388 reload_services( True );
390 set_message(outbuf,4,0,True);
391 SSVAL(outbuf, smb_vwv3, 0);
393 if (server_info->guest) {
394 SSVAL(outbuf,smb_vwv2,1);
397 SSVAL(outbuf, smb_uid, sess_vuid);
399 sessionsetup_start_signing_engine(server_info, inbuf);
402 /* wrap that up in a nice GSS-API wrapping */
403 if (NT_STATUS_IS_OK(ret)) {
404 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
406 ap_rep_wrapped = data_blob(NULL, 0);
408 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
409 reply_sesssetup_blob(conn, outbuf, response, ret);
411 data_blob_free(&ap_rep);
412 data_blob_free(&ap_rep_wrapped);
413 data_blob_free(&response);
414 talloc_destroy(mem_ctx);
416 return -1; /* already replied */
420 /****************************************************************************
421 Send a session setup reply, wrapped in SPNEGO.
422 Get vuid and check first.
423 End the NTLMSSP exchange context if we are OK/complete fail
424 This should be split into two functions, one to handle each
425 leg of the NTLM auth steps.
426 ***************************************************************************/
428 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
430 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
431 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
436 struct auth_serversupplied_info *server_info = NULL;
438 if (NT_STATUS_IS_OK(nt_status)) {
439 server_info = (*auth_ntlmssp_state)->server_info;
441 nt_status = do_map_to_guest(nt_status,
443 (*auth_ntlmssp_state)->ntlmssp_state->user,
444 (*auth_ntlmssp_state)->ntlmssp_state->domain);
447 if (NT_STATUS_IS_OK(nt_status)) {
449 DATA_BLOB nullblob = data_blob(NULL, 0);
450 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
452 /* register_vuid keeps the server info */
453 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
454 (*auth_ntlmssp_state)->server_info = NULL;
456 if (sess_vuid == UID_FIELD_INVALID ) {
457 nt_status = NT_STATUS_LOGON_FAILURE;
460 /* current_user_info is changed on new vuid */
461 reload_services( True );
463 set_message(outbuf,4,0,True);
464 SSVAL(outbuf, smb_vwv3, 0);
466 if (server_info->guest) {
467 SSVAL(outbuf,smb_vwv2,1);
470 SSVAL(outbuf,smb_uid,sess_vuid);
472 sessionsetup_start_signing_engine(server_info, inbuf);
477 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
479 response = *ntlmssp_blob;
482 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
484 data_blob_free(&response);
487 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
488 and the other end, that we are not finished yet. */
490 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
491 /* NB. This is *NOT* an error case. JRA */
492 auth_ntlmssp_end(auth_ntlmssp_state);
493 /* Kill the intermediate vuid */
494 invalidate_vuid(vuid);
500 /****************************************************************************
501 Reply to a session setup spnego negotiate packet.
502 ****************************************************************************/
504 static int reply_spnego_negotiate(connection_struct *conn,
508 int length, int bufsize,
510 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
512 char *OIDs[ASN1_MAX_OIDS];
517 BOOL got_kerberos_mechanism = False;
521 /* parse out the OIDs and the first sec blob */
522 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
523 /* Kill the intermediate vuid */
524 invalidate_vuid(vuid);
526 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
529 /* only look at the first OID for determining the mechToken --
530 accoirding to RFC2478, we should choose the one we want
531 and renegotiate, but i smell a client bug here..
533 Problem observed when connecting to a member (samba box)
534 of an AD domain as a user in a Samba domain. Samba member
535 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
536 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
537 NTLMSSP mechtoken. --jerry */
540 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
541 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
542 got_kerberos_mechanism = True;
546 for (i=0;OIDs[i];i++) {
547 DEBUG(3,("Got OID %s\n", OIDs[i]));
550 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
553 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
554 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
555 length, bufsize, &secblob);
556 data_blob_free(&secblob);
557 /* Kill the intermediate vuid */
558 invalidate_vuid(vuid);
564 if (*auth_ntlmssp_state) {
565 auth_ntlmssp_end(auth_ntlmssp_state);
568 nt_status = auth_ntlmssp_start(auth_ntlmssp_state);
569 if (!NT_STATUS_IS_OK(nt_status)) {
570 /* Kill the intermediate vuid */
571 invalidate_vuid(vuid);
573 return ERROR_NT(nt_status_squash(nt_status));
576 nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
579 data_blob_free(&secblob);
581 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
582 &chal, nt_status, True);
584 data_blob_free(&chal);
586 /* already replied */
590 /****************************************************************************
591 Reply to a session setup spnego auth packet.
592 ****************************************************************************/
594 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
596 int length, int bufsize,
598 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
600 DATA_BLOB auth, auth_reply;
601 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
603 if (!spnego_parse_auth(blob1, &auth)) {
605 file_save("auth.dat", blob1.data, blob1.length);
607 /* Kill the intermediate vuid */
608 invalidate_vuid(vuid);
610 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
613 if (!*auth_ntlmssp_state) {
614 /* Kill the intermediate vuid */
615 invalidate_vuid(vuid);
617 /* auth before negotiatiate? */
618 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
621 nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
624 data_blob_free(&auth);
626 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
628 &auth_reply, nt_status, True);
630 data_blob_free(&auth_reply);
632 /* and tell smbd that we have already replied to this packet */
636 /****************************************************************************
637 Reply to a session setup command.
638 ****************************************************************************/
640 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
642 int length,int bufsize)
648 fstring native_os, native_lanman, primary_domain;
650 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
651 enum remote_arch_types ra_type = get_remote_arch();
652 int vuid = SVAL(inbuf,smb_uid);
653 user_struct *vuser = NULL;
655 DEBUG(3,("Doing spnego session setup\n"));
657 if (global_client_caps == 0) {
658 global_client_caps = IVAL(inbuf,smb_vwv10);
660 if (!(global_client_caps & CAP_STATUS32)) {
661 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
666 p = (uint8 *)smb_buf(inbuf);
668 if (data_blob_len == 0) {
669 /* an invalid request */
670 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
673 bufrem = smb_bufrem(inbuf, p);
674 /* pull the spnego blob */
675 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
678 file_save("negotiate.dat", blob1.data, blob1.length);
681 p2 = inbuf + smb_vwv13 + data_blob_len;
682 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
683 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
684 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
685 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
686 native_os, native_lanman, primary_domain));
688 if ( ra_type == RA_WIN2K ) {
689 /* Windows 2003 doesn't set the native lanman string,
690 but does set primary domain which is a bug I think */
692 if ( !strlen(native_lanman) )
693 ra_lanman_string( primary_domain );
695 ra_lanman_string( native_lanman );
698 vuser = get_partial_auth_user_struct(vuid);
700 vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);
701 if (vuid == UID_FIELD_INVALID ) {
702 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
705 vuser = get_partial_auth_user_struct(vuid);
709 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
712 SSVAL(outbuf,smb_uid,vuid);
714 if (blob1.data[0] == ASN1_APPLICATION(0)) {
715 /* its a negTokenTarg packet */
716 ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
717 &vuser->auth_ntlmssp_state);
718 data_blob_free(&blob1);
722 if (blob1.data[0] == ASN1_CONTEXT(1)) {
723 /* its a auth packet */
724 ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
725 &vuser->auth_ntlmssp_state);
726 data_blob_free(&blob1);
730 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
733 if (!vuser->auth_ntlmssp_state) {
734 nt_status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
735 if (!NT_STATUS_IS_OK(nt_status)) {
736 /* Kill the intermediate vuid */
737 invalidate_vuid(vuid);
739 return ERROR_NT(nt_status_squash(nt_status));
743 nt_status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
746 data_blob_free(&blob1);
748 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
749 &vuser->auth_ntlmssp_state,
750 &chal, nt_status, False);
751 data_blob_free(&chal);
755 /* what sort of packet is this? */
756 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
758 data_blob_free(&blob1);
760 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
763 /****************************************************************************
764 On new VC == 0, shutdown *all* old connections and users.
765 It seems that only NT4.x does this. At W2K and above (XP etc.).
766 a new session setup with VC==0 is ignored.
767 ****************************************************************************/
769 static int shutdown_other_smbds(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
772 struct sessionid *sessionid = (struct sessionid *)dbuf.dptr;
773 const char *ip = (const char *)p;
775 if (!process_exists(pid_to_procid(sessionid->pid))) {
779 if (sessionid->pid == sys_getpid()) {
783 if (strcmp(ip, sessionid->ip_addr) != 0) {
787 message_send_pid(pid_to_procid(sessionid->pid), MSG_SHUTDOWN,
792 static void setup_new_vc_session(void)
794 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
797 invalidate_all_vuids();
799 if (lp_reset_on_zero_vc()) {
800 session_traverse(shutdown_other_smbds, client_addr());
804 /****************************************************************************
805 Reply to a session setup command.
806 ****************************************************************************/
808 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
809 int length,int bufsize)
815 DATA_BLOB plaintext_password;
817 fstring sub_user; /* Sainitised username for substituion */
820 fstring native_lanman;
821 fstring primary_domain;
822 static BOOL done_sesssetup = False;
823 extern BOOL global_encrypted_passwords_negotiated;
824 extern BOOL global_spnego_negotiated;
825 extern enum protocol_types Protocol;
828 auth_usersupplied_info *user_info = NULL;
829 extern struct auth_context *negprot_global_auth_context;
830 auth_serversupplied_info *server_info = NULL;
834 BOOL doencrypt = global_encrypted_passwords_negotiated;
836 DATA_BLOB session_key;
838 START_PROFILE(SMBsesssetupX);
840 ZERO_STRUCT(lm_resp);
841 ZERO_STRUCT(nt_resp);
842 ZERO_STRUCT(plaintext_password);
844 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
846 /* a SPNEGO session setup has 12 command words, whereas a normal
847 NT1 session setup has 13. See the cifs spec. */
848 if (CVAL(inbuf, smb_wct) == 12 &&
849 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
850 if (!global_spnego_negotiated) {
851 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
852 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
855 if (SVAL(inbuf,smb_vwv4) == 0) {
856 setup_new_vc_session();
858 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
861 smb_bufsize = SVAL(inbuf,smb_vwv2);
863 if (Protocol < PROTOCOL_NT1) {
864 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
866 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
867 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
869 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
870 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
874 lm_resp = data_blob(smb_buf(inbuf), passlen1);
876 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
877 /* Ensure null termination */
878 plaintext_password.data[passlen1] = 0;
881 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
885 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
886 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
887 enum remote_arch_types ra_type = get_remote_arch();
888 char *p = smb_buf(inbuf);
889 char *save_p = smb_buf(inbuf);
893 if(global_client_caps == 0) {
894 global_client_caps = IVAL(inbuf,smb_vwv11);
896 if (!(global_client_caps & CAP_STATUS32)) {
897 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
900 /* client_caps is used as final determination if client is NT or Win95.
901 This is needed to return the correct error codes in some
905 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
906 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
907 set_remote_arch( RA_WIN95);
913 /* both Win95 and WinNT stuff up the password lengths for
914 non-encrypting systems. Uggh.
916 if passlen1==24 its a win95 system, and its setting the
917 password length incorrectly. Luckily it still works with the
918 default code because Win95 will null terminate the password
921 if passlen1>0 and passlen2>0 then maybe its a NT box and its
922 setting passlen2 to some random value which really stuffs
923 things up. we need to fix that one. */
925 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
929 /* check for nasty tricks */
930 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
931 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
934 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
935 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
938 /* Save the lanman2 password and the NT md4 password. */
940 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
945 lm_resp = data_blob(p, passlen1);
946 nt_resp = data_blob(p+passlen1, passlen2);
949 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
952 /* This was the previous fix. Not sure if it's still valid. JRA. */
953 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
954 /* NT4.0 stuffs up plaintext unicode password lengths... */
955 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
956 sizeof(pass), passlen1, STR_TERMINATE);
959 if (unic && (passlen2 == 0) && passlen1) {
960 /* Only a ascii plaintext password was sent. */
961 srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
962 passlen1, STR_TERMINATE|STR_ASCII);
964 srvstr_pull(inbuf, pass, smb_buf(inbuf),
965 sizeof(pass), unic ? passlen2 : passlen1,
968 plaintext_password = data_blob(pass, strlen(pass)+1);
971 p += passlen1 + passlen2;
972 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
973 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
974 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
975 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
977 /* not documented or decoded by Ethereal but there is one more string
978 in the extra bytes which is the same as the PrimaryDomain when using
979 extended security. Windows NT 4 and 2003 use this string to store
980 the native lanman string. Windows 9x does not include a string here
981 at all so we have to check if we have any extra bytes left */
983 byte_count = SVAL(inbuf, smb_vwv13);
984 if ( PTR_DIFF(p, save_p) < byte_count)
985 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
987 fstrcpy( primary_domain, "null" );
989 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
990 domain, native_os, native_lanman, primary_domain));
992 if ( ra_type == RA_WIN2K ) {
993 if ( strlen(native_lanman) == 0 )
994 ra_lanman_string( primary_domain );
996 ra_lanman_string( native_lanman );
1001 if (SVAL(inbuf,smb_vwv4) == 0) {
1002 setup_new_vc_session();
1005 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
1008 if (global_spnego_negotiated) {
1010 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
1012 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
1013 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1015 fstrcpy(sub_user, user);
1017 fstrcpy(sub_user, lp_guestaccount());
1020 sub_set_smb_name(sub_user);
1022 reload_services(True);
1024 if (lp_security() == SEC_SHARE) {
1025 /* in share level we should ignore any passwords */
1027 data_blob_free(&lm_resp);
1028 data_blob_free(&nt_resp);
1029 data_blob_clear_free(&plaintext_password);
1031 map_username(sub_user);
1032 add_session_user(sub_user);
1033 /* Then force it to null for the benfit of the code below */
1039 nt_status = check_guest_password(&server_info);
1041 } else if (doencrypt) {
1042 if (!negprot_global_auth_context) {
1043 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
1044 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1046 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
1048 if (NT_STATUS_IS_OK(nt_status)) {
1049 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
1054 struct auth_context *plaintext_auth_context = NULL;
1057 nt_status = make_auth_context_subsystem(&plaintext_auth_context);
1059 if (NT_STATUS_IS_OK(nt_status)) {
1060 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
1062 if (!make_user_info_for_reply(&user_info,
1064 plaintext_password)) {
1065 nt_status = NT_STATUS_NO_MEMORY;
1068 if (NT_STATUS_IS_OK(nt_status)) {
1069 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
1073 (plaintext_auth_context->free)(&plaintext_auth_context);
1078 free_user_info(&user_info);
1080 if (!NT_STATUS_IS_OK(nt_status)) {
1081 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
1084 if (!NT_STATUS_IS_OK(nt_status)) {
1085 data_blob_free(&nt_resp);
1086 data_blob_free(&lm_resp);
1087 data_blob_clear_free(&plaintext_password);
1088 return ERROR_NT(nt_status_squash(nt_status));
1091 /* Ensure we can't possible take a code path leading to a null defref. */
1093 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1096 nt_status = create_local_token(server_info);
1097 if (!NT_STATUS_IS_OK(nt_status)) {
1098 DEBUG(10, ("create_local_token failed: %s\n",
1099 nt_errstr(nt_status)));
1100 data_blob_free(&nt_resp);
1101 data_blob_free(&lm_resp);
1102 data_blob_clear_free(&plaintext_password);
1103 return ERROR_NT(nt_status_squash(nt_status));
1106 if (server_info->user_session_key.data) {
1107 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
1109 session_key = data_blob(NULL, 0);
1112 data_blob_clear_free(&plaintext_password);
1114 /* it's ok - setup a reply */
1115 set_message(outbuf,3,0,True);
1116 if (Protocol >= PROTOCOL_NT1) {
1117 char *p = smb_buf( outbuf );
1118 p += add_signature( outbuf, p );
1119 set_message_end( outbuf, p );
1120 /* perhaps grab OS version here?? */
1123 if (server_info->guest) {
1124 SSVAL(outbuf,smb_vwv2,1);
1127 /* register the name and uid as being validated, so further connections
1128 to a uid can get through without a password, on the same VC */
1130 if (lp_security() == SEC_SHARE) {
1131 sess_vuid = UID_FIELD_INVALID;
1132 data_blob_free(&session_key);
1133 TALLOC_FREE(server_info);
1135 /* register_vuid keeps the server info */
1136 sess_vuid = register_vuid(server_info, session_key,
1137 nt_resp.data ? nt_resp : lm_resp,
1139 if (sess_vuid == UID_FIELD_INVALID) {
1140 data_blob_free(&nt_resp);
1141 data_blob_free(&lm_resp);
1142 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1145 /* current_user_info is changed on new vuid */
1146 reload_services( True );
1148 sessionsetup_start_signing_engine(server_info, inbuf);
1151 data_blob_free(&nt_resp);
1152 data_blob_free(&lm_resp);
1154 SSVAL(outbuf,smb_uid,sess_vuid);
1155 SSVAL(inbuf,smb_uid,sess_vuid);
1157 if (!done_sesssetup)
1158 max_send = MIN(max_send,smb_bufsize);
1160 done_sesssetup = True;
1162 END_PROFILE(SMBsesssetupX);
1163 return chain_reply(inbuf,outbuf,length,bufsize);