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 set_message(outbuf,4,0,True);
100 nt_status = nt_status_squash(nt_status);
101 SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
102 SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
103 SSVAL(outbuf, smb_vwv3, blob.length);
106 /* should we cap this? */
107 memcpy(p, blob.data, blob.length);
110 p += add_signature( outbuf, p );
112 set_message_end(outbuf,p);
115 return send_smb(smbd_server_fd(),outbuf);
118 /****************************************************************************
119 Do a 'guest' logon, getting back the
120 ****************************************************************************/
122 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
124 struct auth_context *auth_context;
125 auth_usersupplied_info *user_info = NULL;
128 unsigned char chal[8];
132 DEBUG(3,("Got anonymous request\n"));
134 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) {
138 if (!make_user_info_guest(&user_info)) {
139 (auth_context->free)(&auth_context);
140 return NT_STATUS_NO_MEMORY;
143 nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info);
144 (auth_context->free)(&auth_context);
145 free_user_info(&user_info);
151 /****************************************************************************
152 reply to a session setup spnego negotiate packet for kerberos
153 ****************************************************************************/
154 static int reply_spnego_kerberos(connection_struct *conn,
155 char *inbuf, char *outbuf,
156 int length, int bufsize,
161 char *client, *p, *domain;
162 fstring netbios_domain_name;
168 DATA_BLOB ap_rep, ap_rep_wrapped, response;
169 auth_serversupplied_info *server_info = NULL;
170 DATA_BLOB session_key = data_blob(NULL, 0);
172 DATA_BLOB nullblob = data_blob(NULL, 0);
173 fstring real_username;
174 BOOL map_domainuser_to_guest = False;
175 PAC_LOGON_INFO *logon_info = NULL;
178 ZERO_STRUCT(pac_data);
180 ZERO_STRUCT(ap_rep_wrapped);
181 ZERO_STRUCT(response);
183 mem_ctx = talloc_init("reply_spnego_kerberos");
185 return ERROR_NT(NT_STATUS_NO_MEMORY);
187 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
188 talloc_destroy(mem_ctx);
189 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
192 ret = ads_verify_ticket(mem_ctx, lp_realm(), &ticket, &client, &pac_data, &ap_rep, &session_key);
194 data_blob_free(&ticket);
196 if (!NT_STATUS_IS_OK(ret)) {
197 DEBUG(1,("Failed to verify incoming ticket!\n"));
198 talloc_destroy(mem_ctx);
199 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
202 DEBUG(3,("Ticket name is [%s]\n", client));
204 p = strchr_m(client, '@');
206 DEBUG(3,("Doesn't look like a valid principal\n"));
207 data_blob_free(&ap_rep);
208 data_blob_free(&session_key);
210 talloc_destroy(mem_ctx);
211 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
216 /* save the PAC data if we have it */
219 logon_info = get_logon_info_from_pac(pac_data);
220 netsamlogon_cache_store( client, &logon_info->info3 );
223 if (!strequal(p+1, lp_realm())) {
224 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
225 if (!lp_allow_trusted_domains()) {
226 data_blob_free(&ap_rep);
227 data_blob_free(&session_key);
229 talloc_destroy(mem_ctx);
230 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
234 /* this gives a fully qualified user name (ie. with full realm).
235 that leads to very long usernames, but what else can we do? */
239 if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) {
241 unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, -1);
242 domain = netbios_domain_name;
243 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
247 /* If we have winbind running, we can (and must) shorten the
248 username by using the short netbios name. Otherwise we will
249 have inconsistent user names. With Kerberos, we get the
250 fully qualified realm, with ntlmssp we get the short
251 name. And even w2k3 does use ntlmssp if you for example
252 connect to an ip address. */
254 struct winbindd_request wb_request;
255 struct winbindd_response wb_response;
256 NSS_STATUS wb_result;
258 ZERO_STRUCT(wb_request);
259 ZERO_STRUCT(wb_response);
261 DEBUG(10, ("Mapping [%s] to short name\n", domain));
263 fstrcpy(wb_request.domain_name, domain);
265 wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
266 &wb_request, &wb_response);
268 if (wb_result == NSS_STATUS_SUCCESS) {
270 fstrcpy(netbios_domain_name,
271 wb_response.data.domain_info.name);
272 domain = netbios_domain_name;
274 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
276 DEBUG(3, ("Could not find short name -- winbind "
281 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
283 /* lookup the passwd struct, create a new user if necessary */
285 map_username( user );
287 pw = smb_getpwnam( user, real_username, True );
290 /* this was originally the behavior of Samba 2.2, if a user
291 did not have a local uid but has been authenticated, then
292 map them to a guest account */
294 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
295 map_domainuser_to_guest = True;
296 fstrcpy(user,lp_guestaccount());
297 pw = smb_getpwnam( user, real_username, True );
300 /* extra sanity check that the guest account is valid */
303 DEBUG(1,("Username %s is invalid on this system\n", user));
305 data_blob_free(&ap_rep);
306 data_blob_free(&session_key);
307 talloc_destroy(mem_ctx);
308 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
312 /* setup the string used by %U */
314 sub_set_smb_name( real_username );
315 reload_services(True);
316 if ( map_domainuser_to_guest ) {
317 make_server_info_guest(&server_info);
318 } else if (logon_info) {
319 ret = make_server_info_pac(&server_info, real_username, pw, logon_info);
321 if ( !NT_STATUS_IS_OK(ret) ) {
322 DEBUG(1,("make_server_info_pac failed!\n"));
324 data_blob_free(&ap_rep);
325 data_blob_free(&session_key);
327 talloc_destroy(mem_ctx);
328 return ERROR_NT(ret);
332 ret = make_server_info_pw(&server_info, real_username, pw);
334 if ( !NT_STATUS_IS_OK(ret) ) {
335 DEBUG(1,("make_server_info_from_pw failed!\n"));
337 data_blob_free(&ap_rep);
338 data_blob_free(&session_key);
340 talloc_destroy(mem_ctx);
341 return ERROR_NT(ret);
344 /* make_server_info_pw does not set the domain. Without this we end up
345 * with the local netbios name in substitutions for %D. */
347 if (server_info->sam_account != NULL) {
348 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
355 /* register_vuid keeps the server info */
356 /* register_vuid takes ownership of session_key, no need to free after this.
357 A better interface would copy it.... */
358 sess_vuid = register_vuid(server_info, session_key, nullblob, client);
362 if (sess_vuid == -1) {
363 ret = NT_STATUS_LOGON_FAILURE;
365 /* current_user_info is changed on new vuid */
366 reload_services( True );
368 set_message(outbuf,4,0,True);
369 SSVAL(outbuf, smb_vwv3, 0);
371 if (server_info->guest) {
372 SSVAL(outbuf,smb_vwv2,1);
375 SSVAL(outbuf, smb_uid, sess_vuid);
377 sessionsetup_start_signing_engine(server_info, inbuf);
380 /* wrap that up in a nice GSS-API wrapping */
381 if (NT_STATUS_IS_OK(ret)) {
382 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
384 ap_rep_wrapped = data_blob(NULL, 0);
386 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
387 reply_sesssetup_blob(conn, outbuf, response, ret);
389 data_blob_free(&ap_rep);
390 data_blob_free(&ap_rep_wrapped);
391 data_blob_free(&response);
392 talloc_destroy(mem_ctx);
394 return -1; /* already replied */
398 /****************************************************************************
399 Send a session setup reply, wrapped in SPNEGO.
400 Get vuid and check first.
401 End the NTLMSSP exchange context if we are OK/complete fail
402 This should be split into two functions, one to handle each
403 leg of the NTLM auth steps.
404 ***************************************************************************/
406 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
408 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
409 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
414 struct auth_serversupplied_info *server_info = NULL;
416 if (NT_STATUS_IS_OK(nt_status)) {
417 server_info = (*auth_ntlmssp_state)->server_info;
419 nt_status = do_map_to_guest(nt_status,
421 (*auth_ntlmssp_state)->ntlmssp_state->user,
422 (*auth_ntlmssp_state)->ntlmssp_state->domain);
425 if (NT_STATUS_IS_OK(nt_status)) {
427 DATA_BLOB nullblob = data_blob(NULL, 0);
428 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
430 /* register_vuid keeps the server info */
431 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
432 (*auth_ntlmssp_state)->server_info = NULL;
434 if (sess_vuid == -1) {
435 nt_status = NT_STATUS_LOGON_FAILURE;
438 /* current_user_info is changed on new vuid */
439 reload_services( True );
441 set_message(outbuf,4,0,True);
442 SSVAL(outbuf, smb_vwv3, 0);
444 if (server_info->guest) {
445 SSVAL(outbuf,smb_vwv2,1);
448 SSVAL(outbuf,smb_uid,sess_vuid);
450 sessionsetup_start_signing_engine(server_info, inbuf);
455 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
457 response = *ntlmssp_blob;
460 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
462 data_blob_free(&response);
465 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
466 and the other end, that we are not finished yet. */
468 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
469 /* NB. This is *NOT* an error case. JRA */
470 auth_ntlmssp_end(auth_ntlmssp_state);
471 /* Kill the intermediate vuid */
472 invalidate_vuid(vuid);
478 /****************************************************************************
479 Reply to a session setup spnego negotiate packet.
480 ****************************************************************************/
482 static int reply_spnego_negotiate(connection_struct *conn,
486 int length, int bufsize,
488 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
490 char *OIDs[ASN1_MAX_OIDS];
495 BOOL got_kerberos_mechanism = False;
499 /* parse out the OIDs and the first sec blob */
500 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
501 /* Kill the intermediate vuid */
502 invalidate_vuid(vuid);
504 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
507 /* only look at the first OID for determining the mechToken --
508 accoirding to RFC2478, we should choose the one we want
509 and renegotiate, but i smell a client bug here..
511 Problem observed when connecting to a member (samba box)
512 of an AD domain as a user in a Samba domain. Samba member
513 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
514 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
515 NTLMSSP mechtoken. --jerry */
518 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
519 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
520 got_kerberos_mechanism = True;
524 for (i=0;OIDs[i];i++) {
525 DEBUG(3,("Got OID %s\n", OIDs[i]));
528 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
531 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
532 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
533 length, bufsize, &secblob);
534 data_blob_free(&secblob);
535 /* Kill the intermediate vuid */
536 invalidate_vuid(vuid);
542 if (*auth_ntlmssp_state) {
543 auth_ntlmssp_end(auth_ntlmssp_state);
546 nt_status = auth_ntlmssp_start(auth_ntlmssp_state);
547 if (!NT_STATUS_IS_OK(nt_status)) {
548 /* Kill the intermediate vuid */
549 invalidate_vuid(vuid);
551 return ERROR_NT(nt_status);
554 nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
557 data_blob_free(&secblob);
559 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
560 &chal, nt_status, True);
562 data_blob_free(&chal);
564 /* already replied */
568 /****************************************************************************
569 Reply to a session setup spnego auth packet.
570 ****************************************************************************/
572 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
574 int length, int bufsize,
576 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
578 DATA_BLOB auth, auth_reply;
579 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
581 if (!spnego_parse_auth(blob1, &auth)) {
583 file_save("auth.dat", blob1.data, blob1.length);
585 /* Kill the intermediate vuid */
586 invalidate_vuid(vuid);
588 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
591 if (!*auth_ntlmssp_state) {
592 /* Kill the intermediate vuid */
593 invalidate_vuid(vuid);
595 /* auth before negotiatiate? */
596 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
599 nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
602 data_blob_free(&auth);
604 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
606 &auth_reply, nt_status, True);
608 data_blob_free(&auth_reply);
610 /* and tell smbd that we have already replied to this packet */
614 /****************************************************************************
615 Reply to a session setup command.
616 ****************************************************************************/
618 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
620 int length,int bufsize)
626 fstring native_os, native_lanman, primary_domain;
628 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
629 enum remote_arch_types ra_type = get_remote_arch();
630 int vuid = SVAL(inbuf,smb_uid);
631 user_struct *vuser = NULL;
633 DEBUG(3,("Doing spnego session setup\n"));
635 if (global_client_caps == 0) {
636 global_client_caps = IVAL(inbuf,smb_vwv10);
638 if (!(global_client_caps & CAP_STATUS32)) {
639 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
644 p = (uint8 *)smb_buf(inbuf);
646 if (data_blob_len == 0) {
647 /* an invalid request */
648 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
651 bufrem = smb_bufrem(inbuf, p);
652 /* pull the spnego blob */
653 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
656 file_save("negotiate.dat", blob1.data, blob1.length);
659 p2 = inbuf + smb_vwv13 + data_blob_len;
660 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
661 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
662 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
663 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
664 native_os, native_lanman, primary_domain));
666 if ( ra_type == RA_WIN2K ) {
667 /* Windows 2003 doesn't set the native lanman string,
668 but does set primary domain which is a bug I think */
670 if ( !strlen(native_lanman) )
671 ra_lanman_string( primary_domain );
673 ra_lanman_string( native_lanman );
676 vuser = get_partial_auth_user_struct(vuid);
678 vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);
680 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
683 vuser = get_partial_auth_user_struct(vuid);
687 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
690 SSVAL(outbuf,smb_uid,vuid);
692 if (blob1.data[0] == ASN1_APPLICATION(0)) {
693 /* its a negTokenTarg packet */
694 ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
695 &vuser->auth_ntlmssp_state);
696 data_blob_free(&blob1);
700 if (blob1.data[0] == ASN1_CONTEXT(1)) {
701 /* its a auth packet */
702 ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
703 &vuser->auth_ntlmssp_state);
704 data_blob_free(&blob1);
708 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
711 if (!vuser->auth_ntlmssp_state) {
712 nt_status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
713 if (!NT_STATUS_IS_OK(nt_status)) {
714 /* Kill the intermediate vuid */
715 invalidate_vuid(vuid);
717 return ERROR_NT(nt_status);
721 nt_status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
724 data_blob_free(&blob1);
726 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
727 &vuser->auth_ntlmssp_state,
728 &chal, nt_status, False);
729 data_blob_free(&chal);
733 /* what sort of packet is this? */
734 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
736 data_blob_free(&blob1);
738 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
741 /****************************************************************************
742 On new VC == 0, shutdown *all* old connections and users.
743 It seems that only NT4.x does this. At W2K and above (XP etc.).
744 a new session setup with VC==0 is ignored.
745 ****************************************************************************/
747 static int shutdown_other_smbds(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
750 struct sessionid *sessionid = (struct sessionid *)dbuf.dptr;
751 const char *ip = (const char *)p;
753 if (!process_exists(pid_to_procid(sessionid->pid))) {
757 if (sessionid->pid == sys_getpid()) {
761 if (strcmp(ip, sessionid->ip_addr) != 0) {
765 message_send_pid(pid_to_procid(sessionid->pid), MSG_SHUTDOWN,
770 static void setup_new_vc_session(void)
772 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
775 invalidate_all_vuids();
777 if (lp_reset_on_zero_vc()) {
778 session_traverse(shutdown_other_smbds, client_addr());
782 /****************************************************************************
783 Reply to a session setup command.
784 ****************************************************************************/
786 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
787 int length,int bufsize)
793 DATA_BLOB plaintext_password;
795 fstring sub_user; /* Sainitised username for substituion */
798 fstring native_lanman;
799 fstring primary_domain;
800 static BOOL done_sesssetup = False;
801 extern BOOL global_encrypted_passwords_negotiated;
802 extern BOOL global_spnego_negotiated;
803 extern enum protocol_types Protocol;
806 auth_usersupplied_info *user_info = NULL;
807 extern struct auth_context *negprot_global_auth_context;
808 auth_serversupplied_info *server_info = NULL;
812 BOOL doencrypt = global_encrypted_passwords_negotiated;
814 DATA_BLOB session_key;
816 START_PROFILE(SMBsesssetupX);
818 ZERO_STRUCT(lm_resp);
819 ZERO_STRUCT(nt_resp);
820 ZERO_STRUCT(plaintext_password);
822 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
824 /* a SPNEGO session setup has 12 command words, whereas a normal
825 NT1 session setup has 13. See the cifs spec. */
826 if (CVAL(inbuf, smb_wct) == 12 &&
827 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
828 if (!global_spnego_negotiated) {
829 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
830 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
833 if (SVAL(inbuf,smb_vwv4) == 0) {
834 setup_new_vc_session();
836 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
839 smb_bufsize = SVAL(inbuf,smb_vwv2);
841 if (Protocol < PROTOCOL_NT1) {
842 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
844 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
845 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
847 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
848 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
852 lm_resp = data_blob(smb_buf(inbuf), passlen1);
854 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
855 /* Ensure null termination */
856 plaintext_password.data[passlen1] = 0;
859 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
863 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
864 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
865 enum remote_arch_types ra_type = get_remote_arch();
866 char *p = smb_buf(inbuf);
867 char *save_p = smb_buf(inbuf);
871 if(global_client_caps == 0) {
872 global_client_caps = IVAL(inbuf,smb_vwv11);
874 if (!(global_client_caps & CAP_STATUS32)) {
875 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
878 /* client_caps is used as final determination if client is NT or Win95.
879 This is needed to return the correct error codes in some
883 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
884 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
885 set_remote_arch( RA_WIN95);
891 /* both Win95 and WinNT stuff up the password lengths for
892 non-encrypting systems. Uggh.
894 if passlen1==24 its a win95 system, and its setting the
895 password length incorrectly. Luckily it still works with the
896 default code because Win95 will null terminate the password
899 if passlen1>0 and passlen2>0 then maybe its a NT box and its
900 setting passlen2 to some random value which really stuffs
901 things up. we need to fix that one. */
903 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
907 /* check for nasty tricks */
908 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
909 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
912 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
913 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
916 /* Save the lanman2 password and the NT md4 password. */
918 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
923 lm_resp = data_blob(p, passlen1);
924 nt_resp = data_blob(p+passlen1, passlen2);
927 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
930 /* This was the previous fix. Not sure if it's still valid. JRA. */
931 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
932 /* NT4.0 stuffs up plaintext unicode password lengths... */
933 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
934 sizeof(pass), passlen1, STR_TERMINATE);
937 if (unic && (passlen2 == 0) && passlen1) {
938 /* Only a ascii plaintext password was sent. */
939 srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
940 passlen1, STR_TERMINATE|STR_ASCII);
942 srvstr_pull(inbuf, pass, smb_buf(inbuf),
943 sizeof(pass), unic ? passlen2 : passlen1,
946 plaintext_password = data_blob(pass, strlen(pass)+1);
949 p += passlen1 + passlen2;
950 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
951 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
952 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
953 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
955 /* not documented or decoded by Ethereal but there is one more string
956 in the extra bytes which is the same as the PrimaryDomain when using
957 extended security. Windows NT 4 and 2003 use this string to store
958 the native lanman string. Windows 9x does not include a string here
959 at all so we have to check if we have any extra bytes left */
961 byte_count = SVAL(inbuf, smb_vwv13);
962 if ( PTR_DIFF(p, save_p) < byte_count)
963 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
965 fstrcpy( primary_domain, "null" );
967 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
968 domain, native_os, native_lanman, primary_domain));
970 if ( ra_type == RA_WIN2K ) {
971 if ( strlen(native_lanman) == 0 )
972 ra_lanman_string( primary_domain );
974 ra_lanman_string( native_lanman );
979 if (SVAL(inbuf,smb_vwv4) == 0) {
980 setup_new_vc_session();
983 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
986 if (global_spnego_negotiated) {
988 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
990 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
991 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
993 fstrcpy(sub_user, user);
995 fstrcpy(sub_user, lp_guestaccount());
998 sub_set_smb_name(sub_user);
1000 reload_services(True);
1002 if (lp_security() == SEC_SHARE) {
1003 /* in share level we should ignore any passwords */
1005 data_blob_free(&lm_resp);
1006 data_blob_free(&nt_resp);
1007 data_blob_clear_free(&plaintext_password);
1009 map_username(sub_user);
1010 add_session_user(sub_user);
1011 /* Then force it to null for the benfit of the code below */
1017 nt_status = check_guest_password(&server_info);
1019 } else if (doencrypt) {
1020 if (!negprot_global_auth_context) {
1021 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
1022 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
1024 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
1026 if (NT_STATUS_IS_OK(nt_status)) {
1027 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
1032 struct auth_context *plaintext_auth_context = NULL;
1034 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
1035 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
1037 if (!make_user_info_for_reply(&user_info,
1039 plaintext_password)) {
1040 nt_status = NT_STATUS_NO_MEMORY;
1043 if (NT_STATUS_IS_OK(nt_status)) {
1044 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
1048 (plaintext_auth_context->free)(&plaintext_auth_context);
1053 free_user_info(&user_info);
1055 if (!NT_STATUS_IS_OK(nt_status)) {
1056 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
1059 if (!NT_STATUS_IS_OK(nt_status)) {
1060 data_blob_free(&nt_resp);
1061 data_blob_free(&lm_resp);
1062 data_blob_clear_free(&plaintext_password);
1063 return ERROR_NT(nt_status_squash(nt_status));
1066 if (server_info->user_session_key.data) {
1067 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
1069 session_key = data_blob(NULL, 0);
1072 data_blob_clear_free(&plaintext_password);
1074 /* it's ok - setup a reply */
1075 set_message(outbuf,3,0,True);
1076 if (Protocol >= PROTOCOL_NT1) {
1077 char *p = smb_buf( outbuf );
1078 p += add_signature( outbuf, p );
1079 set_message_end( outbuf, p );
1080 /* perhaps grab OS version here?? */
1083 if (server_info->guest) {
1084 SSVAL(outbuf,smb_vwv2,1);
1087 /* register the name and uid as being validated, so further connections
1088 to a uid can get through without a password, on the same VC */
1090 /* register_vuid keeps the server info */
1091 sess_vuid = register_vuid(server_info, session_key, nt_resp.data ? nt_resp : lm_resp, sub_user);
1092 data_blob_free(&nt_resp);
1093 data_blob_free(&lm_resp);
1095 if (sess_vuid == -1) {
1096 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
1099 /* current_user_info is changed on new vuid */
1100 reload_services( True );
1102 sessionsetup_start_signing_engine(server_info, inbuf);
1104 SSVAL(outbuf,smb_uid,sess_vuid);
1105 SSVAL(inbuf,smb_uid,sess_vuid);
1107 if (!done_sesssetup)
1108 max_send = MIN(max_send,smb_bufsize);
1110 done_sesssetup = True;
1112 END_PROFILE(SMBsesssetupX);
1113 return chain_reply(inbuf,outbuf,length,bufsize);