Second part of fix for bug #8673 - NT ACL issue.
[Samba.git] / source3 / smbd / sesssetup.c
blob0de5a4bb65331f8b9351e7d96a871e75129e3c40
1 /*
2 Unix SMB/CIFS implementation.
3 handle SMBsessionsetup
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
8 Copyright (C) Volker Lendecke 2007
9 Copyright (C) Jeremy Allison 2007
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "smbd/globals.h"
27 #include "../libcli/auth/spnego.h"
29 /* For split krb5 SPNEGO blobs. */
30 struct pending_auth_data {
31 struct pending_auth_data *prev, *next;
32 uint16 vuid; /* Tag for this entry. */
33 uint16 smbpid; /* Alternate tag for this entry. */
34 size_t needed_len;
35 DATA_BLOB partial_data;
39 on a logon error possibly map the error to success if "map to guest"
40 is set approriately
42 static NTSTATUS do_map_to_guest(NTSTATUS status,
43 auth_serversupplied_info **server_info,
44 const char *user, const char *domain)
46 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
47 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
48 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
49 DEBUG(3,("No such user %s [%s] - using guest account\n",
50 user, domain));
51 status = make_server_info_guest(NULL, server_info);
55 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
56 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
57 DEBUG(3,("Registered username %s for guest access\n",
58 user));
59 status = make_server_info_guest(NULL, server_info);
63 return status;
66 /****************************************************************************
67 Add the standard 'Samba' signature to the end of the session setup.
68 ****************************************************************************/
70 static int push_signature(uint8 **outbuf)
72 char *lanman;
73 int result, tmp;
75 result = 0;
77 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
79 if (tmp == -1) return -1;
80 result += tmp;
82 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
83 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
84 SAFE_FREE(lanman);
86 else {
87 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
90 if (tmp == -1) return -1;
91 result += tmp;
93 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
95 if (tmp == -1) return -1;
96 result += tmp;
98 return result;
101 /****************************************************************************
102 Send a security blob via a session setup reply.
103 ****************************************************************************/
105 static void reply_sesssetup_blob(struct smb_request *req,
106 DATA_BLOB blob,
107 NTSTATUS nt_status)
109 if (!NT_STATUS_IS_OK(nt_status) &&
110 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
111 reply_nterror(req, nt_status_squash(nt_status));
112 return;
115 nt_status = nt_status_squash(nt_status);
116 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
117 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
118 SSVAL(req->outbuf, smb_vwv3, blob.length);
120 if ((message_push_blob(&req->outbuf, blob) == -1)
121 || (push_signature(&req->outbuf) == -1)) {
122 reply_nterror(req, NT_STATUS_NO_MEMORY);
126 /****************************************************************************
127 Do a 'guest' logon, getting back the
128 ****************************************************************************/
130 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
132 struct auth_context *auth_context;
133 auth_usersupplied_info *user_info = NULL;
135 NTSTATUS nt_status;
136 unsigned char chal[8];
138 ZERO_STRUCT(chal);
140 DEBUG(3,("Got anonymous request\n"));
142 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context,
143 chal))) {
144 return nt_status;
147 if (!make_user_info_guest(&user_info)) {
148 (auth_context->free)(&auth_context);
149 return NT_STATUS_NO_MEMORY;
152 nt_status = auth_context->check_ntlm_password(auth_context,
153 user_info,
154 server_info);
155 (auth_context->free)(&auth_context);
156 free_user_info(&user_info);
157 return nt_status;
161 #ifdef HAVE_KRB5
163 #if 0
164 /* Experiment that failed. See "only happens with a KDC" comment below. */
165 /****************************************************************************
166 Cerate a clock skew error blob for a Windows client.
167 ****************************************************************************/
169 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
171 krb5_context context = NULL;
172 krb5_error_code kerr = 0;
173 krb5_data reply;
174 krb5_principal host_princ = NULL;
175 char *host_princ_s = NULL;
176 bool ret = False;
178 *pblob_out = data_blob_null;
180 initialize_krb5_error_table();
181 kerr = krb5_init_context(&context);
182 if (kerr) {
183 return False;
185 /* Create server principal. */
186 asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
187 if (!host_princ_s) {
188 goto out;
190 strlower_m(host_princ_s);
192 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
193 if (kerr) {
194 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
195 "for name %s: Error %s\n",
196 host_princ_s, error_message(kerr) ));
197 goto out;
200 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
201 host_princ, &reply);
202 if (kerr) {
203 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
204 "failed: Error %s\n",
205 error_message(kerr) ));
206 goto out;
209 *pblob_out = data_blob(reply.data, reply.length);
210 kerberos_free_data_contents(context,&reply);
211 ret = True;
213 out:
215 if (host_princ_s) {
216 SAFE_FREE(host_princ_s);
218 if (host_princ) {
219 krb5_free_principal(context, host_princ);
221 krb5_free_context(context);
222 return ret;
224 #endif
226 /****************************************************************************
227 Reply to a session setup spnego negotiate packet for kerberos.
228 ****************************************************************************/
230 static void reply_spnego_kerberos(struct smb_request *req,
231 DATA_BLOB *secblob,
232 const char *mechOID,
233 uint16 vuid,
234 bool *p_invalidate_vuid)
236 TALLOC_CTX *mem_ctx;
237 DATA_BLOB ticket;
238 char *client, *p, *domain;
239 fstring netbios_domain_name;
240 struct passwd *pw;
241 fstring user;
242 int sess_vuid = req->vuid;
243 NTSTATUS ret = NT_STATUS_OK;
244 struct PAC_DATA *pac_data = NULL;
245 DATA_BLOB ap_rep, ap_rep_wrapped, response;
246 auth_serversupplied_info *server_info = NULL;
247 DATA_BLOB session_key = data_blob_null;
248 uint8 tok_id[2];
249 DATA_BLOB nullblob = data_blob_null;
250 fstring real_username;
251 bool map_domainuser_to_guest = False;
252 bool username_was_mapped;
253 struct PAC_LOGON_INFO *logon_info = NULL;
254 struct smbd_server_connection *sconn = smbd_server_conn;
256 ZERO_STRUCT(ticket);
257 ZERO_STRUCT(ap_rep);
258 ZERO_STRUCT(ap_rep_wrapped);
259 ZERO_STRUCT(response);
261 /* Normally we will always invalidate the intermediate vuid. */
262 *p_invalidate_vuid = True;
264 mem_ctx = talloc_init("reply_spnego_kerberos");
265 if (mem_ctx == NULL) {
266 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
267 return;
270 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
271 talloc_destroy(mem_ctx);
272 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
273 return;
276 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
277 &client, &pac_data, &ap_rep,
278 &session_key, True);
280 data_blob_free(&ticket);
282 if (!NT_STATUS_IS_OK(ret)) {
283 #if 0
284 /* Experiment that failed.
285 * See "only happens with a KDC" comment below. */
287 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
290 * Windows in this case returns
291 * NT_STATUS_MORE_PROCESSING_REQUIRED
292 * with a negTokenTarg blob containing an krb5_error
293 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
294 * The client then fixes its clock and continues rather
295 * than giving an error. JRA.
296 * -- Looks like this only happens with a KDC. JRA.
299 bool ok = make_krb5_skew_error(&ap_rep);
300 if (!ok) {
301 talloc_destroy(mem_ctx);
302 return ERROR_NT(nt_status_squash(
303 NT_STATUS_LOGON_FAILURE));
305 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
306 TOK_ID_KRB_ERROR);
307 response = spnego_gen_auth_response(&ap_rep_wrapped,
308 ret, OID_KERBEROS5_OLD);
309 reply_sesssetup_blob(conn, inbuf, outbuf, response,
310 NT_STATUS_MORE_PROCESSING_REQUIRED);
313 * In this one case we don't invalidate the
314 * intermediate vuid as we're expecting the client
315 * to re-use it for the next sessionsetupX packet. JRA.
318 *p_invalidate_vuid = False;
320 data_blob_free(&ap_rep);
321 data_blob_free(&ap_rep_wrapped);
322 data_blob_free(&response);
323 talloc_destroy(mem_ctx);
324 return -1; /* already replied */
326 #else
327 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
328 ret = NT_STATUS_LOGON_FAILURE;
330 #endif
331 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
332 nt_errstr(ret)));
333 talloc_destroy(mem_ctx);
334 reply_nterror(req, nt_status_squash(ret));
335 return;
338 DEBUG(3,("Ticket name is [%s]\n", client));
340 p = strchr_m(client, '@');
341 if (!p) {
342 DEBUG(3,("Doesn't look like a valid principal\n"));
343 data_blob_free(&ap_rep);
344 data_blob_free(&session_key);
345 talloc_destroy(mem_ctx);
346 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
347 return;
350 *p = 0;
352 /* save the PAC data if we have it */
354 if (pac_data) {
355 logon_info = get_logon_info_from_pac(pac_data);
356 if (logon_info) {
357 netsamlogon_cache_store( client, &logon_info->info3 );
361 if (!strequal(p+1, lp_realm())) {
362 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
363 if (!lp_allow_trusted_domains()) {
364 data_blob_free(&ap_rep);
365 data_blob_free(&session_key);
366 talloc_destroy(mem_ctx);
367 reply_nterror(req, nt_status_squash(
368 NT_STATUS_LOGON_FAILURE));
369 return;
373 /* this gives a fully qualified user name (ie. with full realm).
374 that leads to very long usernames, but what else can we do? */
376 domain = p+1;
378 if (logon_info && logon_info->info3.base.domain.string) {
379 fstrcpy(netbios_domain_name,
380 logon_info->info3.base.domain.string);
381 domain = netbios_domain_name;
382 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
384 } else {
386 /* If we have winbind running, we can (and must) shorten the
387 username by using the short netbios name. Otherwise we will
388 have inconsistent user names. With Kerberos, we get the
389 fully qualified realm, with ntlmssp we get the short
390 name. And even w2k3 does use ntlmssp if you for example
391 connect to an ip address. */
393 wbcErr wbc_status;
394 struct wbcDomainInfo *info = NULL;
396 DEBUG(10, ("Mapping [%s] to short name\n", domain));
398 wbc_status = wbcDomainInfo(domain, &info);
400 if (WBC_ERROR_IS_OK(wbc_status)) {
402 fstrcpy(netbios_domain_name,
403 info->short_name);
405 wbcFreeMemory(info);
406 domain = netbios_domain_name;
407 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
408 } else {
409 DEBUG(3, ("Could not find short name: %s\n",
410 wbcErrorString(wbc_status)));
414 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
416 /* lookup the passwd struct, create a new user if necessary */
418 username_was_mapped = map_username(sconn, user);
420 pw = smb_getpwnam( mem_ctx, user, real_username, True );
422 if (pw) {
423 /* if a real user check pam account restrictions */
424 /* only really perfomed if "obey pam restriction" is true */
425 /* do this before an eventual mapping to guest occurs */
426 ret = smb_pam_accountcheck(pw->pw_name);
427 if ( !NT_STATUS_IS_OK(ret)) {
428 DEBUG(1,("PAM account restriction "
429 "prevents user login\n"));
430 data_blob_free(&ap_rep);
431 data_blob_free(&session_key);
432 TALLOC_FREE(mem_ctx);
433 reply_nterror(req, nt_status_squash(ret));
434 return;
438 if (!pw) {
440 /* this was originally the behavior of Samba 2.2, if a user
441 did not have a local uid but has been authenticated, then
442 map them to a guest account */
444 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
445 map_domainuser_to_guest = True;
446 fstrcpy(user,lp_guestaccount());
447 pw = smb_getpwnam( mem_ctx, user, real_username, True );
450 /* extra sanity check that the guest account is valid */
452 if ( !pw ) {
453 DEBUG(1,("Username %s is invalid on this system\n",
454 user));
455 data_blob_free(&ap_rep);
456 data_blob_free(&session_key);
457 TALLOC_FREE(mem_ctx);
458 reply_nterror(req, nt_status_squash(
459 NT_STATUS_LOGON_FAILURE));
460 return;
464 /* setup the string used by %U */
466 sub_set_smb_name( real_username );
467 reload_services(True);
469 if ( map_domainuser_to_guest ) {
470 make_server_info_guest(NULL, &server_info);
471 } else if (logon_info) {
472 /* pass the unmapped username here since map_username()
473 will be called again from inside make_server_info_info3() */
475 ret = make_server_info_info3(mem_ctx, client, domain,
476 &server_info, &logon_info->info3);
477 if ( !NT_STATUS_IS_OK(ret) ) {
478 DEBUG(1,("make_server_info_info3 failed: %s!\n",
479 nt_errstr(ret)));
480 data_blob_free(&ap_rep);
481 data_blob_free(&session_key);
482 TALLOC_FREE(mem_ctx);
483 reply_nterror(req, nt_status_squash(ret));
484 return;
487 } else {
489 * We didn't get a PAC, we have to make up the user
490 * ourselves. Try to ask the pdb backend to provide
491 * SID consistency with ntlmssp session setup
493 struct samu *sampass;
495 sampass = samu_new(talloc_tos());
496 if (sampass == NULL) {
497 ret = NT_STATUS_NO_MEMORY;
498 data_blob_free(&ap_rep);
499 data_blob_free(&session_key);
500 TALLOC_FREE(mem_ctx);
501 reply_nterror(req, nt_status_squash(ret));
502 return;
505 if (pdb_getsampwnam(sampass, real_username)) {
506 DEBUG(10, ("found user %s in passdb, calling "
507 "make_server_info_sam\n", real_username));
508 ret = make_server_info_sam(&server_info, sampass);
509 } else {
511 * User not in passdb, make it up artificially
513 TALLOC_FREE(sampass);
514 DEBUG(10, ("didn't find user %s in passdb, calling "
515 "make_server_info_pw\n", real_username));
516 ret = make_server_info_pw(&server_info, real_username,
517 pw);
520 if ( !NT_STATUS_IS_OK(ret) ) {
521 DEBUG(1,("make_server_info_[sam|pw] failed: %s!\n",
522 nt_errstr(ret)));
523 data_blob_free(&ap_rep);
524 data_blob_free(&session_key);
525 TALLOC_FREE(mem_ctx);
526 reply_nterror(req, nt_status_squash(ret));
527 return;
530 /* make_server_info_pw does not set the domain. Without this
531 * we end up with the local netbios name in substitutions for
532 * %D. */
534 if (server_info->sam_account != NULL) {
535 pdb_set_domain(server_info->sam_account,
536 domain, PDB_SET);
540 server_info->nss_token |= username_was_mapped;
542 /* we need to build the token for the user. make_server_info_guest()
543 already does this */
545 if ( !server_info->ptok ) {
546 ret = create_local_token( server_info );
547 if ( !NT_STATUS_IS_OK(ret) ) {
548 DEBUG(10,("failed to create local token: %s\n",
549 nt_errstr(ret)));
550 data_blob_free(&ap_rep);
551 data_blob_free(&session_key);
552 TALLOC_FREE( mem_ctx );
553 TALLOC_FREE( server_info );
554 reply_nterror(req, nt_status_squash(ret));
555 return;
559 if (!is_partial_auth_vuid(sconn, sess_vuid)) {
560 sess_vuid = register_initial_vuid(sconn);
563 data_blob_free(&server_info->user_session_key);
564 server_info->user_session_key = session_key;
565 session_key = data_blob_null;
567 /* register_existing_vuid keeps the server info */
568 /* register_existing_vuid takes ownership of session_key on success,
569 * no need to free after this on success. A better interface would copy
570 * it.... */
572 sess_vuid = register_existing_vuid(sconn,
573 sess_vuid,
574 server_info,
575 nullblob,
576 client);
578 reply_outbuf(req, 4, 0);
579 SSVAL(req->outbuf,smb_uid,sess_vuid);
581 if (sess_vuid == UID_FIELD_INVALID ) {
582 ret = NT_STATUS_LOGON_FAILURE;
583 } else {
584 /* current_user_info is changed on new vuid */
585 reload_services( True );
587 SSVAL(req->outbuf, smb_vwv3, 0);
589 if (server_info->guest) {
590 SSVAL(req->outbuf,smb_vwv2,1);
593 SSVAL(req->outbuf, smb_uid, sess_vuid);
595 /* Successful logon. Keep this vuid. */
596 *p_invalidate_vuid = False;
599 /* wrap that up in a nice GSS-API wrapping */
600 if (NT_STATUS_IS_OK(ret)) {
601 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
602 TOK_ID_KRB_AP_REP);
603 } else {
604 ap_rep_wrapped = data_blob_null;
606 response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
607 mechOID);
608 reply_sesssetup_blob(req, response, ret);
610 data_blob_free(&ap_rep);
611 data_blob_free(&ap_rep_wrapped);
612 data_blob_free(&response);
613 TALLOC_FREE(mem_ctx);
616 #endif
618 /****************************************************************************
619 Send a session setup reply, wrapped in SPNEGO.
620 Get vuid and check first.
621 End the NTLMSSP exchange context if we are OK/complete fail
622 This should be split into two functions, one to handle each
623 leg of the NTLM auth steps.
624 ***************************************************************************/
626 static void reply_spnego_ntlmssp(struct smb_request *req,
627 uint16 vuid,
628 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
629 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
630 const char *OID,
631 bool wrap)
633 DATA_BLOB response;
634 struct auth_serversupplied_info *server_info = NULL;
635 struct smbd_server_connection *sconn = smbd_server_conn;
637 if (NT_STATUS_IS_OK(nt_status)) {
638 server_info = (*auth_ntlmssp_state)->server_info;
639 } else {
640 nt_status = do_map_to_guest(nt_status,
641 &server_info,
642 (*auth_ntlmssp_state)->ntlmssp_state->user,
643 (*auth_ntlmssp_state)->ntlmssp_state->domain);
646 reply_outbuf(req, 4, 0);
648 SSVAL(req->outbuf, smb_uid, vuid);
650 if (NT_STATUS_IS_OK(nt_status)) {
651 DATA_BLOB nullblob = data_blob_null;
653 if (!is_partial_auth_vuid(sconn, vuid)) {
654 nt_status = NT_STATUS_LOGON_FAILURE;
655 goto out;
658 data_blob_free(&server_info->user_session_key);
659 server_info->user_session_key =
660 data_blob_talloc(
661 server_info,
662 (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
663 (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
665 /* register_existing_vuid keeps the server info */
666 if (register_existing_vuid(sconn, vuid,
667 server_info, nullblob,
668 (*auth_ntlmssp_state)->ntlmssp_state->user) !=
669 vuid) {
670 nt_status = NT_STATUS_LOGON_FAILURE;
671 goto out;
674 (*auth_ntlmssp_state)->server_info = NULL;
676 /* current_user_info is changed on new vuid */
677 reload_services( True );
679 SSVAL(req->outbuf, smb_vwv3, 0);
681 if (server_info->guest) {
682 SSVAL(req->outbuf,smb_vwv2,1);
686 out:
688 if (wrap) {
689 response = spnego_gen_auth_response(ntlmssp_blob,
690 nt_status, OID);
691 } else {
692 response = *ntlmssp_blob;
695 reply_sesssetup_blob(req, response, nt_status);
696 if (wrap) {
697 data_blob_free(&response);
700 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
701 and the other end, that we are not finished yet. */
703 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
704 /* NB. This is *NOT* an error case. JRA */
705 auth_ntlmssp_end(auth_ntlmssp_state);
706 if (!NT_STATUS_IS_OK(nt_status)) {
707 /* Kill the intermediate vuid */
708 invalidate_vuid(sconn, vuid);
713 /****************************************************************************
714 Is this a krb5 mechanism ?
715 ****************************************************************************/
717 NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in,
718 DATA_BLOB *pblob_out,
719 char **kerb_mechOID)
721 char *OIDs[ASN1_MAX_OIDS];
722 int i;
723 NTSTATUS ret = NT_STATUS_OK;
725 *kerb_mechOID = NULL;
727 /* parse out the OIDs and the first sec blob */
728 if (!parse_negTokenTarg(blob_in, OIDs, pblob_out) ||
729 OIDs[0] == NULL) {
730 return NT_STATUS_LOGON_FAILURE;
733 /* only look at the first OID for determining the mechToken --
734 according to RFC2478, we should choose the one we want
735 and renegotiate, but i smell a client bug here..
737 Problem observed when connecting to a member (samba box)
738 of an AD domain as a user in a Samba domain. Samba member
739 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
740 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
741 NTLMSSP mechtoken. --jerry */
743 #ifdef HAVE_KRB5
744 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
745 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
746 *kerb_mechOID = SMB_STRDUP(OIDs[0]);
747 if (*kerb_mechOID == NULL) {
748 ret = NT_STATUS_NO_MEMORY;
751 #endif
753 for (i=0;OIDs[i];i++) {
754 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
755 talloc_free(OIDs[i]);
757 return ret;
760 /****************************************************************************
761 Fall back from krb5 to NTLMSSP.
762 ****************************************************************************/
764 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
765 uint16 vuid)
767 DATA_BLOB response;
769 reply_outbuf(req, 4, 0);
770 SSVAL(req->outbuf,smb_uid,vuid);
772 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
773 "but set to downgrade to NTLMSSP\n"));
775 response = spnego_gen_auth_response(NULL,
776 NT_STATUS_MORE_PROCESSING_REQUIRED,
777 OID_NTLMSSP);
778 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
779 data_blob_free(&response);
782 /****************************************************************************
783 Reply to a session setup spnego negotiate packet.
784 ****************************************************************************/
786 static void reply_spnego_negotiate(struct smb_request *req,
787 uint16 vuid,
788 DATA_BLOB blob1,
789 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
791 DATA_BLOB secblob;
792 DATA_BLOB chal;
793 char *kerb_mech = NULL;
794 NTSTATUS status;
795 struct smbd_server_connection *sconn = smbd_server_conn;
797 status = parse_spnego_mechanisms(blob1, &secblob, &kerb_mech);
798 if (!NT_STATUS_IS_OK(status)) {
799 /* Kill the intermediate vuid */
800 invalidate_vuid(sconn, vuid);
801 reply_nterror(req, nt_status_squash(status));
802 return;
805 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
806 (unsigned long)secblob.length));
808 #ifdef HAVE_KRB5
809 if (kerb_mech && ((lp_security()==SEC_ADS) ||
810 USE_KERBEROS_KEYTAB) ) {
811 bool destroy_vuid = True;
812 reply_spnego_kerberos(req, &secblob, kerb_mech,
813 vuid, &destroy_vuid);
814 data_blob_free(&secblob);
815 if (destroy_vuid) {
816 /* Kill the intermediate vuid */
817 invalidate_vuid(sconn, vuid);
819 SAFE_FREE(kerb_mech);
820 return;
822 #endif
824 if (*auth_ntlmssp_state) {
825 auth_ntlmssp_end(auth_ntlmssp_state);
828 if (kerb_mech) {
829 data_blob_free(&secblob);
830 /* The mechtoken is a krb5 ticket, but
831 * we need to fall back to NTLM. */
832 reply_spnego_downgrade_to_ntlmssp(req, vuid);
833 SAFE_FREE(kerb_mech);
834 return;
837 status = auth_ntlmssp_start(auth_ntlmssp_state);
838 if (!NT_STATUS_IS_OK(status)) {
839 /* Kill the intermediate vuid */
840 invalidate_vuid(sconn, vuid);
841 reply_nterror(req, nt_status_squash(status));
842 return;
845 status = auth_ntlmssp_update(*auth_ntlmssp_state,
846 secblob, &chal);
848 data_blob_free(&secblob);
850 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
851 &chal, status, OID_NTLMSSP, true);
853 data_blob_free(&chal);
855 /* already replied */
856 return;
859 /****************************************************************************
860 Reply to a session setup spnego auth packet.
861 ****************************************************************************/
863 static void reply_spnego_auth(struct smb_request *req,
864 uint16 vuid,
865 DATA_BLOB blob1,
866 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
868 DATA_BLOB auth = data_blob_null;
869 DATA_BLOB auth_reply = data_blob_null;
870 DATA_BLOB secblob = data_blob_null;
871 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
872 struct smbd_server_connection *sconn = smbd_server_conn;
874 if (!spnego_parse_auth(blob1, &auth)) {
875 #if 0
876 file_save("auth.dat", blob1.data, blob1.length);
877 #endif
878 /* Kill the intermediate vuid */
879 invalidate_vuid(sconn, vuid);
881 reply_nterror(req, nt_status_squash(
882 NT_STATUS_LOGON_FAILURE));
883 return;
886 if (auth.data[0] == ASN1_APPLICATION(0)) {
887 /* Might be a second negTokenTarg packet */
888 char *kerb_mech = NULL;
890 status = parse_spnego_mechanisms(auth, &secblob, &kerb_mech);
892 if (!NT_STATUS_IS_OK(status)) {
893 /* Kill the intermediate vuid */
894 invalidate_vuid(sconn, vuid);
895 reply_nterror(req, nt_status_squash(status));
896 return;
899 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
900 (unsigned long)secblob.length));
901 #ifdef HAVE_KRB5
902 if (kerb_mech && ((lp_security()==SEC_ADS) ||
903 USE_KERBEROS_KEYTAB)) {
904 bool destroy_vuid = True;
905 reply_spnego_kerberos(req, &secblob, kerb_mech,
906 vuid, &destroy_vuid);
907 data_blob_free(&secblob);
908 data_blob_free(&auth);
909 if (destroy_vuid) {
910 /* Kill the intermediate vuid */
911 invalidate_vuid(sconn, vuid);
913 SAFE_FREE(kerb_mech);
914 return;
916 #endif
917 /* Can't blunder into NTLMSSP auth if we have
918 * a krb5 ticket. */
920 if (kerb_mech) {
921 /* Kill the intermediate vuid */
922 invalidate_vuid(sconn, vuid);
923 DEBUG(3,("reply_spnego_auth: network "
924 "misconfiguration, client sent us a "
925 "krb5 ticket and kerberos security "
926 "not enabled\n"));
927 reply_nterror(req, nt_status_squash(
928 NT_STATUS_LOGON_FAILURE));
929 SAFE_FREE(kerb_mech);
933 /* If we get here it wasn't a negTokenTarg auth packet. */
934 data_blob_free(&secblob);
936 if (!*auth_ntlmssp_state) {
937 status = auth_ntlmssp_start(auth_ntlmssp_state);
938 if (!NT_STATUS_IS_OK(status)) {
939 /* Kill the intermediate vuid */
940 invalidate_vuid(sconn, vuid);
941 reply_nterror(req, nt_status_squash(status));
942 return;
946 status = auth_ntlmssp_update(*auth_ntlmssp_state,
947 auth, &auth_reply);
949 data_blob_free(&auth);
951 /* Don't send the mechid as we've already sent this (RFC4178). */
953 reply_spnego_ntlmssp(req, vuid,
954 auth_ntlmssp_state,
955 &auth_reply, status, NULL, true);
957 data_blob_free(&auth_reply);
959 /* and tell smbd that we have already replied to this packet */
960 return;
963 /****************************************************************************
964 Delete an entry on the list.
965 ****************************************************************************/
967 static void delete_partial_auth(struct smbd_server_connection *sconn,
968 struct pending_auth_data *pad)
970 if (!pad) {
971 return;
973 DLIST_REMOVE(sconn->smb1.pd_list, pad);
974 data_blob_free(&pad->partial_data);
975 SAFE_FREE(pad);
978 /****************************************************************************
979 Search for a partial SPNEGO auth fragment matching an smbpid.
980 ****************************************************************************/
982 static struct pending_auth_data *get_pending_auth_data(
983 struct smbd_server_connection *sconn,
984 uint16_t smbpid)
986 struct pending_auth_data *pad;
988 * NOTE: using the smbpid here is completely wrong...
989 * see [MS-SMB]
990 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
992 for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
993 if (pad->smbpid == smbpid) {
994 break;
997 return pad;
1000 /****************************************************************************
1001 Check the size of an SPNEGO blob. If we need more return
1002 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
1003 the blob to be more than 64k.
1004 ****************************************************************************/
1006 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
1007 uint16 smbpid, uint16 vuid,
1008 DATA_BLOB *pblob)
1010 struct pending_auth_data *pad = NULL;
1011 ASN1_DATA *data;
1012 size_t needed_len = 0;
1014 pad = get_pending_auth_data(sconn, smbpid);
1016 /* Ensure we have some data. */
1017 if (pblob->length == 0) {
1018 /* Caller can cope. */
1019 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
1020 delete_partial_auth(sconn, pad);
1021 return NT_STATUS_OK;
1024 /* Were we waiting for more data ? */
1025 if (pad) {
1026 DATA_BLOB tmp_blob;
1027 size_t copy_len = MIN(65536, pblob->length);
1029 /* Integer wrap paranoia.... */
1031 if (pad->partial_data.length + copy_len <
1032 pad->partial_data.length ||
1033 pad->partial_data.length + copy_len < copy_len) {
1035 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1036 "pad->partial_data.length = %u, "
1037 "copy_len = %u\n",
1038 (unsigned int)pad->partial_data.length,
1039 (unsigned int)copy_len ));
1041 delete_partial_auth(sconn, pad);
1042 return NT_STATUS_INVALID_PARAMETER;
1045 DEBUG(10,("check_spnego_blob_complete: "
1046 "pad->partial_data.length = %u, "
1047 "pad->needed_len = %u, "
1048 "copy_len = %u, "
1049 "pblob->length = %u,\n",
1050 (unsigned int)pad->partial_data.length,
1051 (unsigned int)pad->needed_len,
1052 (unsigned int)copy_len,
1053 (unsigned int)pblob->length ));
1055 tmp_blob = data_blob(NULL,
1056 pad->partial_data.length + copy_len);
1058 /* Concatenate the two (up to copy_len) bytes. */
1059 memcpy(tmp_blob.data,
1060 pad->partial_data.data,
1061 pad->partial_data.length);
1062 memcpy(tmp_blob.data + pad->partial_data.length,
1063 pblob->data,
1064 copy_len);
1066 /* Replace the partial data. */
1067 data_blob_free(&pad->partial_data);
1068 pad->partial_data = tmp_blob;
1069 ZERO_STRUCT(tmp_blob);
1071 /* Are we done ? */
1072 if (pblob->length >= pad->needed_len) {
1073 /* Yes, replace pblob. */
1074 data_blob_free(pblob);
1075 *pblob = pad->partial_data;
1076 ZERO_STRUCT(pad->partial_data);
1077 delete_partial_auth(sconn, pad);
1078 return NT_STATUS_OK;
1081 /* Still need more data. */
1082 pad->needed_len -= copy_len;
1083 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1086 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
1087 (pblob->data[0] != ASN1_CONTEXT(1))) {
1088 /* Not something we can determine the
1089 * length of.
1091 return NT_STATUS_OK;
1094 /* This is a new SPNEGO sessionsetup - see if
1095 * the data given in this blob is enough.
1098 data = asn1_init(NULL);
1099 if (data == NULL) {
1100 return NT_STATUS_NO_MEMORY;
1103 asn1_load(data, *pblob);
1104 if (asn1_start_tag(data, pblob->data[0])) {
1105 /* asn1_start_tag checks if the given
1106 length of the blob is enough to complete
1107 the tag. If it returns true we know
1108 there is nothing to do - the blob is
1109 complete. */
1110 asn1_free(data);
1111 return NT_STATUS_OK;
1114 if (data->nesting == NULL) {
1115 /* Incorrect tag, allocation failed,
1116 or reading the tag length failed.
1117 Let the caller catch. */
1118 asn1_free(data);
1119 return NT_STATUS_OK;
1122 /* Here we know asn1_start_tag() has set data->has_error to true.
1123 asn1_tag_remaining() will have failed due to the given blob
1124 being too short. We need to work out how short. */
1126 /* Integer wrap paranoia.... */
1128 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
1129 data->nesting->taglen + data->nesting->start < data->nesting->start) {
1131 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1132 "data.nesting->taglen = %u, "
1133 "data.nesting->start = %u\n",
1134 (unsigned int)data->nesting->taglen,
1135 (unsigned int)data->nesting->start ));
1137 asn1_free(data);
1138 return NT_STATUS_INVALID_PARAMETER;
1141 /* Total length of the needed asn1 is the tag length
1142 * plus the current offset. */
1144 needed_len = data->nesting->taglen + data->nesting->start;
1145 asn1_free(data);
1147 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1148 "pblob->length = %u\n",
1149 (unsigned int)needed_len,
1150 (unsigned int)pblob->length ));
1152 if (needed_len <= pblob->length) {
1153 /* Nothing to do - blob is complete. */
1154 /* THIS SHOULD NOT HAPPEN - asn1_start_tag()
1155 above should have caught this !!! */
1156 DEBUG(0,("check_spnego_blob_complete: logic "
1157 "error (needed_len = %u, "
1158 "pblob->length = %u).\n",
1159 (unsigned int)needed_len,
1160 (unsigned int)pblob->length ));
1161 return NT_STATUS_OK;
1164 /* Refuse the blob if it's bigger than 64k. */
1165 if (needed_len > 65536) {
1166 DEBUG(2,("check_spnego_blob_complete: needed_len "
1167 "too large (%u)\n",
1168 (unsigned int)needed_len ));
1169 return NT_STATUS_INVALID_PARAMETER;
1172 /* We must store this blob until complete. */
1173 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1174 return NT_STATUS_NO_MEMORY;
1176 pad->needed_len = needed_len - pblob->length;
1177 pad->partial_data = data_blob(pblob->data, pblob->length);
1178 if (pad->partial_data.data == NULL) {
1179 SAFE_FREE(pad);
1180 return NT_STATUS_NO_MEMORY;
1182 pad->smbpid = smbpid;
1183 pad->vuid = vuid;
1184 DLIST_ADD(sconn->smb1.pd_list, pad);
1186 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1189 /****************************************************************************
1190 Reply to a session setup command.
1191 conn POINTER CAN BE NULL HERE !
1192 ****************************************************************************/
1194 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1196 const uint8 *p;
1197 DATA_BLOB blob1;
1198 size_t bufrem;
1199 char *tmp;
1200 const char *native_os;
1201 const char *native_lanman;
1202 const char *primary_domain;
1203 const char *p2;
1204 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1205 enum remote_arch_types ra_type = get_remote_arch();
1206 int vuid = req->vuid;
1207 user_struct *vuser = NULL;
1208 NTSTATUS status = NT_STATUS_OK;
1209 uint16 smbpid = req->smbpid;
1210 struct smbd_server_connection *sconn = smbd_server_conn;
1212 DEBUG(3,("Doing spnego session setup\n"));
1214 if (global_client_caps == 0) {
1215 global_client_caps = IVAL(req->vwv+10, 0);
1217 if (!(global_client_caps & CAP_STATUS32)) {
1218 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1223 p = req->buf;
1225 if (data_blob_len == 0) {
1226 /* an invalid request */
1227 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1228 return;
1231 bufrem = smbreq_bufrem(req, p);
1232 /* pull the spnego blob */
1233 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1235 #if 0
1236 file_save("negotiate.dat", blob1.data, blob1.length);
1237 #endif
1239 p2 = (char *)req->buf + blob1.length;
1241 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1242 STR_TERMINATE);
1243 native_os = tmp ? tmp : "";
1245 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1246 STR_TERMINATE);
1247 native_lanman = tmp ? tmp : "";
1249 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1250 STR_TERMINATE);
1251 primary_domain = tmp ? tmp : "";
1253 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1254 native_os, native_lanman, primary_domain));
1256 if ( ra_type == RA_WIN2K ) {
1257 /* Vista sets neither the OS or lanman strings */
1259 if ( !strlen(native_os) && !strlen(native_lanman) )
1260 set_remote_arch(RA_VISTA);
1262 /* Windows 2003 doesn't set the native lanman string,
1263 but does set primary domain which is a bug I think */
1265 if ( !strlen(native_lanman) ) {
1266 ra_lanman_string( primary_domain );
1267 } else {
1268 ra_lanman_string( native_lanman );
1272 /* Did we get a valid vuid ? */
1273 if (!is_partial_auth_vuid(sconn, vuid)) {
1274 /* No, then try and see if this is an intermediate sessionsetup
1275 * for a large SPNEGO packet. */
1276 struct pending_auth_data *pad;
1277 pad = get_pending_auth_data(sconn, smbpid);
1278 if (pad) {
1279 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1280 "pending vuid %u\n",
1281 (unsigned int)pad->vuid ));
1282 vuid = pad->vuid;
1286 /* Do we have a valid vuid now ? */
1287 if (!is_partial_auth_vuid(sconn, vuid)) {
1288 /* No, start a new authentication setup. */
1289 vuid = register_initial_vuid(sconn);
1290 if (vuid == UID_FIELD_INVALID) {
1291 data_blob_free(&blob1);
1292 reply_nterror(req, nt_status_squash(
1293 NT_STATUS_INVALID_PARAMETER));
1294 return;
1298 vuser = get_partial_auth_user_struct(sconn, vuid);
1299 /* This MUST be valid. */
1300 if (!vuser) {
1301 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1304 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1305 * sessionsetup requests as the Windows limit on the security blob
1306 * field is 4k. Bug #4400. JRA.
1309 status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1310 if (!NT_STATUS_IS_OK(status)) {
1311 if (!NT_STATUS_EQUAL(status,
1312 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1313 /* Real error - kill the intermediate vuid */
1314 invalidate_vuid(sconn, vuid);
1316 data_blob_free(&blob1);
1317 reply_nterror(req, nt_status_squash(status));
1318 return;
1321 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1323 /* its a negTokenTarg packet */
1325 reply_spnego_negotiate(req, vuid, blob1,
1326 &vuser->auth_ntlmssp_state);
1327 data_blob_free(&blob1);
1328 return;
1331 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1333 /* its a auth packet */
1335 reply_spnego_auth(req, vuid, blob1,
1336 &vuser->auth_ntlmssp_state);
1337 data_blob_free(&blob1);
1338 return;
1341 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1342 DATA_BLOB chal;
1344 if (!vuser->auth_ntlmssp_state) {
1345 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1346 if (!NT_STATUS_IS_OK(status)) {
1347 /* Kill the intermediate vuid */
1348 invalidate_vuid(sconn, vuid);
1349 data_blob_free(&blob1);
1350 reply_nterror(req, nt_status_squash(status));
1351 return;
1355 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1356 blob1, &chal);
1358 data_blob_free(&blob1);
1360 reply_spnego_ntlmssp(req, vuid,
1361 &vuser->auth_ntlmssp_state,
1362 &chal, status, OID_NTLMSSP, false);
1363 data_blob_free(&chal);
1364 return;
1367 /* what sort of packet is this? */
1368 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1370 data_blob_free(&blob1);
1372 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1375 /****************************************************************************
1376 On new VC == 0, shutdown *all* old connections and users.
1377 It seems that only NT4.x does this. At W2K and above (XP etc.).
1378 a new session setup with VC==0 is ignored.
1379 ****************************************************************************/
1381 static int shutdown_other_smbds(struct db_record *rec,
1382 const struct connections_key *key,
1383 const struct connections_data *crec,
1384 void *private_data)
1386 const char *ip = (const char *)private_data;
1388 if (!process_exists(crec->pid)) {
1389 return 0;
1392 if (procid_is_me(&crec->pid)) {
1393 return 0;
1396 if (strcmp(ip, crec->addr) != 0) {
1397 return 0;
1400 DEBUG(0,("shutdown_other_smbds: shutting down pid %u "
1401 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid), ip));
1403 messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1404 &data_blob_null);
1405 return 0;
1408 static void setup_new_vc_session(void)
1410 char addr[INET6_ADDRSTRLEN];
1412 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1413 "compatible we would close all old resources.\n"));
1414 #if 0
1415 conn_close_all();
1416 invalidate_all_vuids();
1417 #endif
1418 if (lp_reset_on_zero_vc()) {
1419 connections_forall(shutdown_other_smbds,
1420 CONST_DISCARD(void *,
1421 client_addr(get_client_fd(),addr,sizeof(addr))));
1425 /****************************************************************************
1426 Reply to a session setup command.
1427 ****************************************************************************/
1429 void reply_sesssetup_and_X(struct smb_request *req)
1431 int sess_vuid;
1432 int smb_bufsize;
1433 DATA_BLOB lm_resp;
1434 DATA_BLOB nt_resp;
1435 DATA_BLOB plaintext_password;
1436 char *tmp;
1437 const char *user;
1438 fstring sub_user; /* Sainitised username for substituion */
1439 const char *domain;
1440 const char *native_os;
1441 const char *native_lanman;
1442 const char *primary_domain;
1443 auth_usersupplied_info *user_info = NULL;
1444 auth_serversupplied_info *server_info = NULL;
1445 uint16 smb_flag2 = req->flags2;
1447 NTSTATUS nt_status;
1448 struct smbd_server_connection *sconn = smbd_server_conn;
1450 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1452 START_PROFILE(SMBsesssetupX);
1454 ZERO_STRUCT(lm_resp);
1455 ZERO_STRUCT(nt_resp);
1456 ZERO_STRUCT(plaintext_password);
1458 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1460 /* a SPNEGO session setup has 12 command words, whereas a normal
1461 NT1 session setup has 13. See the cifs spec. */
1462 if (req->wct == 12 &&
1463 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1465 if (!sconn->smb1.negprot.spnego) {
1466 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1467 "at SPNEGO session setup when it was not "
1468 "negotiated.\n"));
1469 reply_nterror(req, nt_status_squash(
1470 NT_STATUS_LOGON_FAILURE));
1471 END_PROFILE(SMBsesssetupX);
1472 return;
1475 if (SVAL(req->vwv+4, 0) == 0) {
1476 setup_new_vc_session();
1479 reply_sesssetup_and_X_spnego(req);
1480 END_PROFILE(SMBsesssetupX);
1481 return;
1484 smb_bufsize = SVAL(req->vwv+2, 0);
1486 if (get_Protocol() < PROTOCOL_NT1) {
1487 uint16 passlen1 = SVAL(req->vwv+7, 0);
1489 /* Never do NT status codes with protocols before NT1 as we
1490 * don't get client caps. */
1491 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1493 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1494 reply_nterror(req, nt_status_squash(
1495 NT_STATUS_INVALID_PARAMETER));
1496 END_PROFILE(SMBsesssetupX);
1497 return;
1500 if (doencrypt) {
1501 lm_resp = data_blob(req->buf, passlen1);
1502 } else {
1503 plaintext_password = data_blob(req->buf, passlen1+1);
1504 /* Ensure null termination */
1505 plaintext_password.data[passlen1] = 0;
1508 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1509 req->buf + passlen1, STR_TERMINATE);
1510 user = tmp ? tmp : "";
1512 domain = "";
1514 } else {
1515 uint16 passlen1 = SVAL(req->vwv+7, 0);
1516 uint16 passlen2 = SVAL(req->vwv+8, 0);
1517 enum remote_arch_types ra_type = get_remote_arch();
1518 const uint8_t *p = req->buf;
1519 const uint8_t *save_p = req->buf;
1520 uint16 byte_count;
1523 if(global_client_caps == 0) {
1524 global_client_caps = IVAL(req->vwv+11, 0);
1526 if (!(global_client_caps & CAP_STATUS32)) {
1527 remove_from_common_flags2(
1528 FLAGS2_32_BIT_ERROR_CODES);
1531 /* client_caps is used as final determination if
1532 * client is NT or Win95. This is needed to return
1533 * the correct error codes in some circumstances.
1536 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1537 ra_type == RA_WIN95) {
1538 if(!(global_client_caps & (CAP_NT_SMBS|
1539 CAP_STATUS32))) {
1540 set_remote_arch( RA_WIN95);
1545 if (!doencrypt) {
1546 /* both Win95 and WinNT stuff up the password
1547 * lengths for non-encrypting systems. Uggh.
1549 if passlen1==24 its a win95 system, and its setting
1550 the password length incorrectly. Luckily it still
1551 works with the default code because Win95 will null
1552 terminate the password anyway
1554 if passlen1>0 and passlen2>0 then maybe its a NT box
1555 and its setting passlen2 to some random value which
1556 really stuffs things up. we need to fix that one. */
1558 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1559 passlen2 != 1) {
1560 passlen2 = 0;
1564 /* check for nasty tricks */
1565 if (passlen1 > MAX_PASS_LEN
1566 || passlen1 > smbreq_bufrem(req, p)) {
1567 reply_nterror(req, nt_status_squash(
1568 NT_STATUS_INVALID_PARAMETER));
1569 END_PROFILE(SMBsesssetupX);
1570 return;
1573 if (passlen2 > MAX_PASS_LEN
1574 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1575 reply_nterror(req, nt_status_squash(
1576 NT_STATUS_INVALID_PARAMETER));
1577 END_PROFILE(SMBsesssetupX);
1578 return;
1581 /* Save the lanman2 password and the NT md4 password. */
1583 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1584 doencrypt = False;
1587 if (doencrypt) {
1588 lm_resp = data_blob(p, passlen1);
1589 nt_resp = data_blob(p+passlen1, passlen2);
1590 } else if (lp_security() != SEC_SHARE) {
1592 * In share level we should ignore any passwords, so
1593 * only read them if we're not.
1595 char *pass = NULL;
1596 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1598 if (unic && (passlen2 == 0) && passlen1) {
1599 /* Only a ascii plaintext password was sent. */
1600 (void)srvstr_pull_talloc(talloc_tos(),
1601 req->inbuf,
1602 req->flags2,
1603 &pass,
1604 req->buf,
1605 passlen1,
1606 STR_TERMINATE|STR_ASCII);
1607 } else {
1608 (void)srvstr_pull_talloc(talloc_tos(),
1609 req->inbuf,
1610 req->flags2,
1611 &pass,
1612 req->buf,
1613 unic ? passlen2 : passlen1,
1614 STR_TERMINATE);
1616 if (!pass) {
1617 reply_nterror(req, nt_status_squash(
1618 NT_STATUS_INVALID_PARAMETER));
1619 END_PROFILE(SMBsesssetupX);
1620 return;
1622 plaintext_password = data_blob(pass, strlen(pass)+1);
1625 p += passlen1 + passlen2;
1627 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1628 STR_TERMINATE);
1629 user = tmp ? tmp : "";
1631 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1632 STR_TERMINATE);
1633 domain = tmp ? tmp : "";
1635 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1636 STR_TERMINATE);
1637 native_os = tmp ? tmp : "";
1639 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1640 STR_TERMINATE);
1641 native_lanman = tmp ? tmp : "";
1643 /* not documented or decoded by Ethereal but there is one more
1644 * string in the extra bytes which is the same as the
1645 * PrimaryDomain when using extended security. Windows NT 4
1646 * and 2003 use this string to store the native lanman string.
1647 * Windows 9x does not include a string here at all so we have
1648 * to check if we have any extra bytes left */
1650 byte_count = SVAL(req->vwv+13, 0);
1651 if ( PTR_DIFF(p, save_p) < byte_count) {
1652 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1653 STR_TERMINATE);
1654 primary_domain = tmp ? tmp : "";
1655 } else {
1656 primary_domain = talloc_strdup(talloc_tos(), "null");
1659 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1660 "PrimaryDomain=[%s]\n",
1661 domain, native_os, native_lanman, primary_domain));
1663 if ( ra_type == RA_WIN2K ) {
1664 if ( strlen(native_lanman) == 0 )
1665 ra_lanman_string( primary_domain );
1666 else
1667 ra_lanman_string( native_lanman );
1672 if (SVAL(req->vwv+4, 0) == 0) {
1673 setup_new_vc_session();
1676 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1677 domain, user, get_remote_machine_name()));
1679 if (*user) {
1680 if (sconn->smb1.negprot.spnego) {
1682 /* This has to be here, because this is a perfectly
1683 * valid behaviour for guest logons :-( */
1685 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1686 "at 'normal' session setup after "
1687 "negotiating spnego.\n"));
1688 reply_nterror(req, nt_status_squash(
1689 NT_STATUS_LOGON_FAILURE));
1690 END_PROFILE(SMBsesssetupX);
1691 return;
1693 fstrcpy(sub_user, user);
1694 } else {
1695 fstrcpy(sub_user, lp_guestaccount());
1698 sub_set_smb_name(sub_user);
1700 reload_services(True);
1702 if (lp_security() == SEC_SHARE) {
1703 /* In share level we should ignore any passwords */
1705 data_blob_free(&lm_resp);
1706 data_blob_free(&nt_resp);
1707 data_blob_clear_free(&plaintext_password);
1709 map_username(sconn, sub_user);
1710 add_session_user(sconn, sub_user);
1711 add_session_workgroup(sconn, domain);
1712 /* Then force it to null for the benfit of the code below */
1713 user = "";
1716 if (!*user) {
1718 nt_status = check_guest_password(&server_info);
1720 } else if (doencrypt) {
1721 struct auth_context *negprot_auth_context = NULL;
1722 negprot_auth_context = sconn->smb1.negprot.auth_context;
1723 if (!negprot_auth_context) {
1724 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1725 "session setup without negprot denied!\n"));
1726 reply_nterror(req, nt_status_squash(
1727 NT_STATUS_LOGON_FAILURE));
1728 END_PROFILE(SMBsesssetupX);
1729 return;
1731 nt_status = make_user_info_for_reply_enc(&user_info, user,
1732 domain,
1733 lm_resp, nt_resp);
1734 if (NT_STATUS_IS_OK(nt_status)) {
1735 nt_status = negprot_auth_context->check_ntlm_password(
1736 negprot_auth_context,
1737 user_info,
1738 &server_info);
1740 } else {
1741 struct auth_context *plaintext_auth_context = NULL;
1743 nt_status = make_auth_context_subsystem(
1744 &plaintext_auth_context);
1746 if (NT_STATUS_IS_OK(nt_status)) {
1747 uint8_t chal[8];
1749 plaintext_auth_context->get_ntlm_challenge(
1750 plaintext_auth_context, chal);
1752 if (!make_user_info_for_reply(&user_info,
1753 user, domain, chal,
1754 plaintext_password)) {
1755 nt_status = NT_STATUS_NO_MEMORY;
1758 if (NT_STATUS_IS_OK(nt_status)) {
1759 nt_status = plaintext_auth_context->check_ntlm_password(
1760 plaintext_auth_context,
1761 user_info,
1762 &server_info);
1764 (plaintext_auth_context->free)(
1765 &plaintext_auth_context);
1770 free_user_info(&user_info);
1772 if (!NT_STATUS_IS_OK(nt_status)) {
1773 nt_status = do_map_to_guest(nt_status, &server_info,
1774 user, domain);
1777 if (!NT_STATUS_IS_OK(nt_status)) {
1778 data_blob_free(&nt_resp);
1779 data_blob_free(&lm_resp);
1780 data_blob_clear_free(&plaintext_password);
1781 reply_nterror(req, nt_status_squash(nt_status));
1782 END_PROFILE(SMBsesssetupX);
1783 return;
1786 /* Ensure we can't possible take a code path leading to a
1787 * null defref. */
1788 if (!server_info) {
1789 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1790 END_PROFILE(SMBsesssetupX);
1791 return;
1794 if (!server_info->ptok) {
1795 nt_status = create_local_token(server_info);
1797 if (!NT_STATUS_IS_OK(nt_status)) {
1798 DEBUG(10, ("create_local_token failed: %s\n",
1799 nt_errstr(nt_status)));
1800 data_blob_free(&nt_resp);
1801 data_blob_free(&lm_resp);
1802 data_blob_clear_free(&plaintext_password);
1803 reply_nterror(req, nt_status_squash(nt_status));
1804 END_PROFILE(SMBsesssetupX);
1805 return;
1809 data_blob_clear_free(&plaintext_password);
1811 /* it's ok - setup a reply */
1812 reply_outbuf(req, 3, 0);
1813 if (get_Protocol() >= PROTOCOL_NT1) {
1814 push_signature(&req->outbuf);
1815 /* perhaps grab OS version here?? */
1818 if (server_info->guest) {
1819 SSVAL(req->outbuf,smb_vwv2,1);
1822 /* register the name and uid as being validated, so further connections
1823 to a uid can get through without a password, on the same VC */
1825 if (lp_security() == SEC_SHARE) {
1826 sess_vuid = UID_FIELD_INVALID;
1827 TALLOC_FREE(server_info);
1828 } else {
1829 /* Ignore the initial vuid. */
1830 sess_vuid = register_initial_vuid(sconn);
1831 if (sess_vuid == UID_FIELD_INVALID) {
1832 data_blob_free(&nt_resp);
1833 data_blob_free(&lm_resp);
1834 reply_nterror(req, nt_status_squash(
1835 NT_STATUS_LOGON_FAILURE));
1836 END_PROFILE(SMBsesssetupX);
1837 return;
1839 /* register_existing_vuid keeps the server info */
1840 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1841 server_info,
1842 nt_resp.data ? nt_resp : lm_resp,
1843 sub_user);
1844 if (sess_vuid == UID_FIELD_INVALID) {
1845 data_blob_free(&nt_resp);
1846 data_blob_free(&lm_resp);
1847 reply_nterror(req, nt_status_squash(
1848 NT_STATUS_LOGON_FAILURE));
1849 END_PROFILE(SMBsesssetupX);
1850 return;
1853 /* current_user_info is changed on new vuid */
1854 reload_services( True );
1857 data_blob_free(&nt_resp);
1858 data_blob_free(&lm_resp);
1860 SSVAL(req->outbuf,smb_uid,sess_vuid);
1861 SSVAL(req->inbuf,smb_uid,sess_vuid);
1862 req->vuid = sess_vuid;
1864 if (!sconn->smb1.sessions.done_sesssetup) {
1865 sconn->smb1.sessions.max_send =
1866 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1868 sconn->smb1.sessions.done_sesssetup = true;
1870 END_PROFILE(SMBsesssetupX);
1871 chain_reply(req);
1872 return;