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);
324 if ( map_domainuser_to_guest ) {
325 make_server_info_guest(&server_info);
326 } else if (logon_info) {
327 /* pass the unmapped username here since map_username()
328 will be called again from inside make_server_info_info3() */
330 ret = make_server_info_info3(mem_ctx, client, domain,
331 &server_info, &logon_info->info3);
332 if ( !NT_STATUS_IS_OK(ret) ) {
333 DEBUG(1,("make_server_info_info3 failed: %s!\n",
336 data_blob_free(&ap_rep);
337 data_blob_free(&session_key);
338 TALLOC_FREE(mem_ctx);
340 return ERROR_NT(nt_status_squash(ret));
344 ret = make_server_info_pw(&server_info, real_username, pw);
346 if ( !NT_STATUS_IS_OK(ret) ) {
347 DEBUG(1,("make_server_info_pw failed: %s!\n",
350 data_blob_free(&ap_rep);
351 data_blob_free(&session_key);
352 TALLOC_FREE(mem_ctx);
354 return ERROR_NT(nt_status_squash(ret));
357 /* make_server_info_pw does not set the domain. Without this
358 * we end up with the local netbios name in substitutions for
361 if (server_info->sam_account != NULL) {
362 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
366 server_info->was_mapped |= username_was_mapped;
368 /* we need to build the token for the user. make_server_info_guest()
371 if ( !server_info->ptok ) {
372 ret = create_local_token( server_info );
373 if ( !NT_STATUS_IS_OK(ret) ) {
375 data_blob_free(&ap_rep);
376 data_blob_free(&session_key);
378 TALLOC_FREE( mem_ctx );
379 TALLOC_FREE( server_info );
380 return ERROR_NT(nt_status_squash(ret));
384 /* register_vuid keeps the server info */
385 /* register_vuid takes ownership of session_key, no need to free after this.
386 A better interface would copy it.... */
387 sess_vuid = register_vuid(server_info, session_key, nullblob, client);
391 if (sess_vuid == UID_FIELD_INVALID ) {
392 ret = NT_STATUS_LOGON_FAILURE;
394 /* current_user_info is changed on new vuid */
395 reload_services( True );
397 set_message(outbuf,4,0,True);
398 SSVAL(outbuf, smb_vwv3, 0);
400 if (server_info->guest) {
401 SSVAL(outbuf,smb_vwv2,1);
404 SSVAL(outbuf, smb_uid, sess_vuid);
406 sessionsetup_start_signing_engine(server_info, inbuf);
409 /* wrap that up in a nice GSS-API wrapping */
410 if (NT_STATUS_IS_OK(ret)) {
411 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
413 ap_rep_wrapped = data_blob(NULL, 0);
415 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
416 reply_sesssetup_blob(conn, outbuf, response, ret);
418 data_blob_free(&ap_rep);
419 data_blob_free(&ap_rep_wrapped);
420 data_blob_free(&response);
421 TALLOC_FREE(mem_ctx);
424 return -1; /* already replied */
428 /****************************************************************************
429 Send a session setup reply, wrapped in SPNEGO.
430 Get vuid and check first.
431 End the NTLMSSP exchange context if we are OK/complete fail
432 This should be split into two functions, one to handle each
433 leg of the NTLM auth steps.
434 ***************************************************************************/
436 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
438 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
439 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
444 struct auth_serversupplied_info *server_info = NULL;
446 if (NT_STATUS_IS_OK(nt_status)) {
447 server_info = (*auth_ntlmssp_state)->server_info;
449 nt_status = do_map_to_guest(nt_status,
451 (*auth_ntlmssp_state)->ntlmssp_state->user,
452 (*auth_ntlmssp_state)->ntlmssp_state->domain);
455 if (NT_STATUS_IS_OK(nt_status)) {
457 DATA_BLOB nullblob = data_blob(NULL, 0);
458 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
460 /* register_vuid keeps the server info */
461 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
462 (*auth_ntlmssp_state)->server_info = NULL;
464 if (sess_vuid == UID_FIELD_INVALID ) {
465 nt_status = NT_STATUS_LOGON_FAILURE;
468 /* current_user_info is changed on new vuid */
469 reload_services( True );
471 set_message(outbuf,4,0,True);
472 SSVAL(outbuf, smb_vwv3, 0);
474 if (server_info->guest) {
475 SSVAL(outbuf,smb_vwv2,1);
478 SSVAL(outbuf,smb_uid,sess_vuid);
480 sessionsetup_start_signing_engine(server_info, inbuf);
485 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
487 response = *ntlmssp_blob;
490 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
492 data_blob_free(&response);
495 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
496 and the other end, that we are not finished yet. */
498 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
499 /* NB. This is *NOT* an error case. JRA */
500 auth_ntlmssp_end(auth_ntlmssp_state);
501 /* Kill the intermediate vuid */
502 invalidate_vuid(vuid);
508 /****************************************************************************
509 Reply to a session setup spnego negotiate packet.
510 ****************************************************************************/
512 static int reply_spnego_negotiate(connection_struct *conn,
516 int length, int bufsize,
518 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
520 char *OIDs[ASN1_MAX_OIDS];
525 BOOL got_kerberos_mechanism = False;
529 /* parse out the OIDs and the first sec blob */
530 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
531 /* Kill the intermediate vuid */
532 invalidate_vuid(vuid);
534 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
537 /* only look at the first OID for determining the mechToken --
538 accoirding to RFC2478, we should choose the one we want
539 and renegotiate, but i smell a client bug here..
541 Problem observed when connecting to a member (samba box)
542 of an AD domain as a user in a Samba domain. Samba member
543 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
544 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
545 NTLMSSP mechtoken. --jerry */
548 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
549 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
550 got_kerberos_mechanism = True;
554 for (i=0;OIDs[i];i++) {
555 DEBUG(3,("Got OID %s\n", OIDs[i]));
558 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
561 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
562 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
563 length, bufsize, &secblob);
564 data_blob_free(&secblob);
565 /* Kill the intermediate vuid */
566 invalidate_vuid(vuid);
572 if (*auth_ntlmssp_state) {
573 auth_ntlmssp_end(auth_ntlmssp_state);
576 nt_status = auth_ntlmssp_start(auth_ntlmssp_state);
577 if (!NT_STATUS_IS_OK(nt_status)) {
578 /* Kill the intermediate vuid */
579 invalidate_vuid(vuid);
581 return ERROR_NT(nt_status_squash(nt_status));
584 nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
587 data_blob_free(&secblob);
589 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
590 &chal, nt_status, True);
592 data_blob_free(&chal);
594 /* already replied */
598 /****************************************************************************
599 Reply to a session setup spnego auth packet.
600 ****************************************************************************/
602 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
604 int length, int bufsize,
606 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
608 DATA_BLOB auth, auth_reply;
609 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
611 if (!spnego_parse_auth(blob1, &auth)) {
613 file_save("auth.dat", blob1.data, blob1.length);
615 /* Kill the intermediate vuid */
616 invalidate_vuid(vuid);
618 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
621 if (!*auth_ntlmssp_state) {
622 /* Kill the intermediate vuid */
623 invalidate_vuid(vuid);
625 /* auth before negotiatiate? */
626 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
629 nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
632 data_blob_free(&auth);
634 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
636 &auth_reply, nt_status, True);
638 data_blob_free(&auth_reply);
640 /* and tell smbd that we have already replied to this packet */
644 /****************************************************************************
645 Reply to a session setup command.
646 conn POINTER CAN BE NULL HERE !
647 ****************************************************************************/
649 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
651 int length,int bufsize)
657 fstring native_os, native_lanman, primary_domain;
659 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
660 enum remote_arch_types ra_type = get_remote_arch();
661 int vuid = SVAL(inbuf,smb_uid);
662 user_struct *vuser = NULL;
664 DEBUG(3,("Doing spnego session setup\n"));
666 if (global_client_caps == 0) {
667 global_client_caps = IVAL(inbuf,smb_vwv10);
669 if (!(global_client_caps & CAP_STATUS32)) {
670 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
675 p = (uint8 *)smb_buf(inbuf);
677 if (data_blob_len == 0) {
678 /* an invalid request */
679 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
682 bufrem = smb_bufrem(inbuf, p);
683 /* pull the spnego blob */
684 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
687 file_save("negotiate.dat", blob1.data, blob1.length);
690 p2 = inbuf + smb_vwv13 + data_blob_len;
691 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
692 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
693 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
694 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
695 native_os, native_lanman, primary_domain));
697 if ( ra_type == RA_WIN2K ) {
698 /* Windows 2003 doesn't set the native lanman string,
699 but does set primary domain which is a bug I think */
701 if ( !strlen(native_lanman) )
702 ra_lanman_string( primary_domain );
704 ra_lanman_string( native_lanman );
707 vuser = get_partial_auth_user_struct(vuid);
709 vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);
710 if (vuid == UID_FIELD_INVALID ) {
711 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
714 vuser = get_partial_auth_user_struct(vuid);
718 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
721 SSVAL(outbuf,smb_uid,vuid);
723 if (blob1.data[0] == ASN1_APPLICATION(0)) {
724 /* its a negTokenTarg packet */
725 ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
726 &vuser->auth_ntlmssp_state);
727 data_blob_free(&blob1);
731 if (blob1.data[0] == ASN1_CONTEXT(1)) {
732 /* its a auth packet */
733 ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
734 &vuser->auth_ntlmssp_state);
735 data_blob_free(&blob1);
739 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
742 if (!vuser->auth_ntlmssp_state) {
743 nt_status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
744 if (!NT_STATUS_IS_OK(nt_status)) {
745 /* Kill the intermediate vuid */
746 invalidate_vuid(vuid);
748 return ERROR_NT(nt_status_squash(nt_status));
752 nt_status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
755 data_blob_free(&blob1);
757 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
758 &vuser->auth_ntlmssp_state,
759 &chal, nt_status, False);
760 data_blob_free(&chal);
764 /* what sort of packet is this? */
765 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
767 data_blob_free(&blob1);
769 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
772 /****************************************************************************
773 On new VC == 0, shutdown *all* old connections and users.
774 It seems that only NT4.x does this. At W2K and above (XP etc.).
775 a new session setup with VC==0 is ignored.
776 ****************************************************************************/
778 static int shutdown_other_smbds(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
781 struct sessionid *sessionid = (struct sessionid *)dbuf.dptr;
782 const char *ip = (const char *)p;
784 if (!process_exists(pid_to_procid(sessionid->pid))) {
788 if (sessionid->pid == sys_getpid()) {
792 if (strcmp(ip, sessionid->ip_addr) != 0) {
796 message_send_pid(pid_to_procid(sessionid->pid), MSG_SHUTDOWN,
801 static void setup_new_vc_session(void)
803 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
806 invalidate_all_vuids();
808 if (lp_reset_on_zero_vc()) {
809 session_traverse(shutdown_other_smbds, client_addr());
813 /****************************************************************************
814 Reply to a session setup command.
815 ****************************************************************************/
817 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
818 int length,int bufsize)
824 DATA_BLOB plaintext_password;
826 fstring sub_user; /* Sainitised username for substituion */
829 fstring native_lanman;
830 fstring primary_domain;
831 static BOOL done_sesssetup = False;
832 extern BOOL global_encrypted_passwords_negotiated;
833 extern BOOL global_spnego_negotiated;
834 extern enum protocol_types Protocol;
837 auth_usersupplied_info *user_info = NULL;
838 extern struct auth_context *negprot_global_auth_context;
839 auth_serversupplied_info *server_info = NULL;
843 BOOL doencrypt = global_encrypted_passwords_negotiated;
845 DATA_BLOB session_key;
847 START_PROFILE(SMBsesssetupX);
849 ZERO_STRUCT(lm_resp);
850 ZERO_STRUCT(nt_resp);
851 ZERO_STRUCT(plaintext_password);
853 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
855 /* a SPNEGO session setup has 12 command words, whereas a normal
856 NT1 session setup has 13. See the cifs spec. */
857 if (CVAL(inbuf, smb_wct) == 12 &&
858 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
859 if (!global_spnego_negotiated) {
860 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
861 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
864 if (SVAL(inbuf,smb_vwv4) == 0) {
865 setup_new_vc_session();
867 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
870 smb_bufsize = SVAL(inbuf,smb_vwv2);
872 if (Protocol < PROTOCOL_NT1) {
873 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
875 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
876 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
878 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
879 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
883 lm_resp = data_blob(smb_buf(inbuf), passlen1);
885 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
886 /* Ensure null termination */
887 plaintext_password.data[passlen1] = 0;
890 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
894 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
895 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
896 enum remote_arch_types ra_type = get_remote_arch();
897 char *p = smb_buf(inbuf);
898 char *save_p = smb_buf(inbuf);
902 if(global_client_caps == 0) {
903 global_client_caps = IVAL(inbuf,smb_vwv11);
905 if (!(global_client_caps & CAP_STATUS32)) {
906 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
909 /* client_caps is used as final determination if client is NT or Win95.
910 This is needed to return the correct error codes in some
914 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
915 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
916 set_remote_arch( RA_WIN95);
922 /* both Win95 and WinNT stuff up the password lengths for
923 non-encrypting systems. Uggh.
925 if passlen1==24 its a win95 system, and its setting the
926 password length incorrectly. Luckily it still works with the
927 default code because Win95 will null terminate the password
930 if passlen1>0 and passlen2>0 then maybe its a NT box and its
931 setting passlen2 to some random value which really stuffs
932 things up. we need to fix that one. */
934 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
938 /* check for nasty tricks */
939 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
940 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
943 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
944 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
947 /* Save the lanman2 password and the NT md4 password. */
949 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
954 lm_resp = data_blob(p, passlen1);
955 nt_resp = data_blob(p+passlen1, passlen2);
958 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
961 /* This was the previous fix. Not sure if it's still valid. JRA. */
962 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
963 /* NT4.0 stuffs up plaintext unicode password lengths... */
964 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
965 sizeof(pass), passlen1, STR_TERMINATE);
968 if (unic && (passlen2 == 0) && passlen1) {
969 /* Only a ascii plaintext password was sent. */
970 srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
971 passlen1, STR_TERMINATE|STR_ASCII);
973 srvstr_pull(inbuf, pass, smb_buf(inbuf),
974 sizeof(pass), unic ? passlen2 : passlen1,
977 plaintext_password = data_blob(pass, strlen(pass)+1);
980 p += passlen1 + passlen2;
981 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
982 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
983 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
984 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
986 /* not documented or decoded by Ethereal but there is one more string
987 in the extra bytes which is the same as the PrimaryDomain when using
988 extended security. Windows NT 4 and 2003 use this string to store
989 the native lanman string. Windows 9x does not include a string here
990 at all so we have to check if we have any extra bytes left */
992 byte_count = SVAL(inbuf, smb_vwv13);
993 if ( PTR_DIFF(p, save_p) < byte_count)
994 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
996 fstrcpy( primary_domain, "null" );
998 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
999 domain, native_os, native_lanman, primary_domain));
1001 if ( ra_type == RA_WIN2K ) {
1002 if ( strlen(native_lanman) == 0 )
1003 ra_lanman_string( primary_domain );
1005 ra_lanman_string( native_lanman );
1010 if (SVAL(inbuf,smb_vwv4) == 0) {
1011 setup_new_vc_session();
1014 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
1017 if (global_spnego_negotiated) {
1019 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
1021 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
1022 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1024 fstrcpy(sub_user, user);
1026 fstrcpy(sub_user, lp_guestaccount());
1029 sub_set_smb_name(sub_user);
1031 reload_services(True);
1033 if (lp_security() == SEC_SHARE) {
1034 /* in share level we should ignore any passwords */
1036 data_blob_free(&lm_resp);
1037 data_blob_free(&nt_resp);
1038 data_blob_clear_free(&plaintext_password);
1040 map_username(sub_user);
1041 add_session_user(sub_user);
1042 /* Then force it to null for the benfit of the code below */
1048 nt_status = check_guest_password(&server_info);
1050 } else if (doencrypt) {
1051 if (!negprot_global_auth_context) {
1052 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
1053 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1055 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
1057 if (NT_STATUS_IS_OK(nt_status)) {
1058 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
1063 struct auth_context *plaintext_auth_context = NULL;
1066 nt_status = make_auth_context_subsystem(&plaintext_auth_context);
1068 if (NT_STATUS_IS_OK(nt_status)) {
1069 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
1071 if (!make_user_info_for_reply(&user_info,
1073 plaintext_password)) {
1074 nt_status = NT_STATUS_NO_MEMORY;
1077 if (NT_STATUS_IS_OK(nt_status)) {
1078 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
1082 (plaintext_auth_context->free)(&plaintext_auth_context);
1087 free_user_info(&user_info);
1089 if (!NT_STATUS_IS_OK(nt_status)) {
1090 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
1093 if (!NT_STATUS_IS_OK(nt_status)) {
1094 data_blob_free(&nt_resp);
1095 data_blob_free(&lm_resp);
1096 data_blob_clear_free(&plaintext_password);
1097 return ERROR_NT(nt_status_squash(nt_status));
1100 /* Ensure we can't possible take a code path leading to a null defref. */
1102 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1105 nt_status = create_local_token(server_info);
1106 if (!NT_STATUS_IS_OK(nt_status)) {
1107 DEBUG(10, ("create_local_token failed: %s\n",
1108 nt_errstr(nt_status)));
1109 data_blob_free(&nt_resp);
1110 data_blob_free(&lm_resp);
1111 data_blob_clear_free(&plaintext_password);
1112 return ERROR_NT(nt_status_squash(nt_status));
1115 if (server_info->user_session_key.data) {
1116 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
1118 session_key = data_blob(NULL, 0);
1121 data_blob_clear_free(&plaintext_password);
1123 /* it's ok - setup a reply */
1124 set_message(outbuf,3,0,True);
1125 if (Protocol >= PROTOCOL_NT1) {
1126 char *p = smb_buf( outbuf );
1127 p += add_signature( outbuf, p );
1128 set_message_end( outbuf, p );
1129 /* perhaps grab OS version here?? */
1132 if (server_info->guest) {
1133 SSVAL(outbuf,smb_vwv2,1);
1136 /* register the name and uid as being validated, so further connections
1137 to a uid can get through without a password, on the same VC */
1139 if (lp_security() == SEC_SHARE) {
1140 sess_vuid = UID_FIELD_INVALID;
1141 data_blob_free(&session_key);
1142 TALLOC_FREE(server_info);
1144 /* register_vuid keeps the server info */
1145 sess_vuid = register_vuid(server_info, session_key,
1146 nt_resp.data ? nt_resp : lm_resp,
1148 if (sess_vuid == UID_FIELD_INVALID) {
1149 data_blob_free(&nt_resp);
1150 data_blob_free(&lm_resp);
1151 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1154 /* current_user_info is changed on new vuid */
1155 reload_services( True );
1157 sessionsetup_start_signing_engine(server_info, inbuf);
1160 data_blob_free(&nt_resp);
1161 data_blob_free(&lm_resp);
1163 SSVAL(outbuf,smb_uid,sess_vuid);
1164 SSVAL(inbuf,smb_uid,sess_vuid);
1166 if (!done_sesssetup)
1167 max_send = MIN(max_send,smb_bufsize);
1169 done_sesssetup = True;
1171 END_PROFILE(SMBsesssetupX);
1172 return chain_reply(inbuf,outbuf,length,bufsize);