make scannedonly notify the scanner if no .scanned: file was found during rename
[Samba/gebeck_regimport.git] / source3 / smbd / sesssetup.c
blob9d8e7ece2c7cf7cecd8274d4d6c26f2b41ab4972
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"
28 #include "../libcli/auth/ntlmssp.h"
29 #include "ntlmssp_wrap.h"
30 #include "librpc/gen_ndr/messaging.h"
32 /* For split krb5 SPNEGO blobs. */
33 struct pending_auth_data {
34 struct pending_auth_data *prev, *next;
35 uint16 vuid; /* Tag for this entry. */
36 uint16 smbpid; /* Alternate tag for this entry. */
37 size_t needed_len;
38 DATA_BLOB partial_data;
42 on a logon error possibly map the error to success if "map to guest"
43 is set approriately
45 NTSTATUS do_map_to_guest(NTSTATUS status,
46 struct auth_serversupplied_info **server_info,
47 const char *user, const char *domain)
49 user = user ? user : "";
50 domain = domain ? domain : "";
52 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
53 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
54 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
55 DEBUG(3,("No such user %s [%s] - using guest account\n",
56 user, domain));
57 status = make_server_info_guest(NULL, server_info);
61 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
62 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
63 DEBUG(3,("Registered username %s for guest access\n",
64 user));
65 status = make_server_info_guest(NULL, server_info);
69 return status;
72 /****************************************************************************
73 Add the standard 'Samba' signature to the end of the session setup.
74 ****************************************************************************/
76 static int push_signature(uint8 **outbuf)
78 char *lanman;
79 int result, tmp;
81 result = 0;
83 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
85 if (tmp == -1) return -1;
86 result += tmp;
88 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
89 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
90 SAFE_FREE(lanman);
92 else {
93 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
96 if (tmp == -1) return -1;
97 result += tmp;
99 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
101 if (tmp == -1) return -1;
102 result += tmp;
104 return result;
107 /****************************************************************************
108 Send a security blob via a session setup reply.
109 ****************************************************************************/
111 static void reply_sesssetup_blob(struct smb_request *req,
112 DATA_BLOB blob,
113 NTSTATUS nt_status)
115 if (!NT_STATUS_IS_OK(nt_status) &&
116 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
117 reply_nterror(req, nt_status_squash(nt_status));
118 return;
121 nt_status = nt_status_squash(nt_status);
122 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
123 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
124 SSVAL(req->outbuf, smb_vwv3, blob.length);
126 if ((message_push_blob(&req->outbuf, blob) == -1)
127 || (push_signature(&req->outbuf) == -1)) {
128 reply_nterror(req, NT_STATUS_NO_MEMORY);
132 /****************************************************************************
133 Do a 'guest' logon, getting back the
134 ****************************************************************************/
136 static NTSTATUS check_guest_password(struct auth_serversupplied_info **server_info)
138 struct auth_context *auth_context;
139 struct auth_usersupplied_info *user_info = NULL;
141 NTSTATUS nt_status;
142 unsigned char chal[8];
144 ZERO_STRUCT(chal);
146 DEBUG(3,("Got anonymous request\n"));
148 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context,
149 chal))) {
150 return nt_status;
153 if (!make_user_info_guest(&user_info)) {
154 TALLOC_FREE(auth_context);
155 return NT_STATUS_NO_MEMORY;
158 nt_status = auth_context->check_ntlm_password(auth_context,
159 user_info,
160 server_info);
161 TALLOC_FREE(auth_context);
162 free_user_info(&user_info);
163 return nt_status;
167 #ifdef HAVE_KRB5
169 #if 0
170 /* Experiment that failed. See "only happens with a KDC" comment below. */
171 /****************************************************************************
172 Cerate a clock skew error blob for a Windows client.
173 ****************************************************************************/
175 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
177 krb5_context context = NULL;
178 krb5_error_code kerr = 0;
179 krb5_data reply;
180 krb5_principal host_princ = NULL;
181 char *host_princ_s = NULL;
182 bool ret = False;
184 *pblob_out = data_blob_null;
186 initialize_krb5_error_table();
187 kerr = krb5_init_context(&context);
188 if (kerr) {
189 return False;
191 /* Create server principal. */
192 asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
193 if (!host_princ_s) {
194 goto out;
196 strlower_m(host_princ_s);
198 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
199 if (kerr) {
200 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
201 "for name %s: Error %s\n",
202 host_princ_s, error_message(kerr) ));
203 goto out;
206 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
207 host_princ, &reply);
208 if (kerr) {
209 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
210 "failed: Error %s\n",
211 error_message(kerr) ));
212 goto out;
215 *pblob_out = data_blob(reply.data, reply.length);
216 kerberos_free_data_contents(context,&reply);
217 ret = True;
219 out:
221 if (host_princ_s) {
222 SAFE_FREE(host_princ_s);
224 if (host_princ) {
225 krb5_free_principal(context, host_princ);
227 krb5_free_context(context);
228 return ret;
230 #endif
232 /****************************************************************************
233 Reply to a session setup spnego negotiate packet for kerberos.
234 ****************************************************************************/
236 static void reply_spnego_kerberos(struct smb_request *req,
237 DATA_BLOB *secblob,
238 const char *mechOID,
239 uint16 vuid,
240 bool *p_invalidate_vuid)
242 TALLOC_CTX *mem_ctx;
243 DATA_BLOB ticket;
244 char *client, *p, *domain;
245 fstring netbios_domain_name;
246 struct passwd *pw;
247 fstring user;
248 int sess_vuid = req->vuid;
249 NTSTATUS ret = NT_STATUS_OK;
250 DATA_BLOB ap_rep, ap_rep_wrapped, response;
251 struct auth_serversupplied_info *server_info = NULL;
252 DATA_BLOB session_key = data_blob_null;
253 uint8 tok_id[2];
254 DATA_BLOB nullblob = data_blob_null;
255 fstring real_username;
256 bool map_domainuser_to_guest = False;
257 bool username_was_mapped;
258 struct PAC_LOGON_INFO *logon_info = NULL;
259 struct smbd_server_connection *sconn = req->sconn;
261 ZERO_STRUCT(ticket);
262 ZERO_STRUCT(ap_rep);
263 ZERO_STRUCT(ap_rep_wrapped);
264 ZERO_STRUCT(response);
266 /* Normally we will always invalidate the intermediate vuid. */
267 *p_invalidate_vuid = True;
269 mem_ctx = talloc_init("reply_spnego_kerberos");
270 if (mem_ctx == NULL) {
271 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
272 return;
275 if (!spnego_parse_krb5_wrap(mem_ctx, *secblob, &ticket, tok_id)) {
276 talloc_destroy(mem_ctx);
277 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
278 return;
281 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
282 &client, &logon_info, &ap_rep,
283 &session_key, True);
285 data_blob_free(&ticket);
287 if (!NT_STATUS_IS_OK(ret)) {
288 #if 0
289 /* Experiment that failed.
290 * See "only happens with a KDC" comment below. */
292 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
295 * Windows in this case returns
296 * NT_STATUS_MORE_PROCESSING_REQUIRED
297 * with a negTokenTarg blob containing an krb5_error
298 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
299 * The client then fixes its clock and continues rather
300 * than giving an error. JRA.
301 * -- Looks like this only happens with a KDC. JRA.
304 bool ok = make_krb5_skew_error(&ap_rep);
305 if (!ok) {
306 talloc_destroy(mem_ctx);
307 return ERROR_NT(nt_status_squash(
308 NT_STATUS_LOGON_FAILURE));
310 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
311 TOK_ID_KRB_ERROR);
312 response = spnego_gen_auth_response(&ap_rep_wrapped,
313 ret, OID_KERBEROS5_OLD);
314 reply_sesssetup_blob(conn, inbuf, outbuf, response,
315 NT_STATUS_MORE_PROCESSING_REQUIRED);
318 * In this one case we don't invalidate the
319 * intermediate vuid as we're expecting the client
320 * to re-use it for the next sessionsetupX packet. JRA.
323 *p_invalidate_vuid = False;
325 data_blob_free(&ap_rep);
326 data_blob_free(&ap_rep_wrapped);
327 data_blob_free(&response);
328 talloc_destroy(mem_ctx);
329 return -1; /* already replied */
331 #else
332 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
333 ret = NT_STATUS_LOGON_FAILURE;
335 #endif
336 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
337 nt_errstr(ret)));
338 talloc_destroy(mem_ctx);
339 reply_nterror(req, nt_status_squash(ret));
340 return;
343 DEBUG(3,("Ticket name is [%s]\n", client));
345 p = strchr_m(client, '@');
346 if (!p) {
347 DEBUG(3,("Doesn't look like a valid principal\n"));
348 data_blob_free(&ap_rep);
349 data_blob_free(&session_key);
350 talloc_destroy(mem_ctx);
351 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
352 return;
355 *p = 0;
357 /* save the PAC data if we have it */
359 if (logon_info) {
360 netsamlogon_cache_store( client, &logon_info->info3 );
363 if (!strequal(p+1, lp_realm())) {
364 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
365 if (!lp_allow_trusted_domains()) {
366 data_blob_free(&ap_rep);
367 data_blob_free(&session_key);
368 talloc_destroy(mem_ctx);
369 reply_nterror(req, nt_status_squash(
370 NT_STATUS_LOGON_FAILURE));
371 return;
375 /* this gives a fully qualified user name (ie. with full realm).
376 that leads to very long usernames, but what else can we do? */
378 domain = p+1;
380 if (logon_info && logon_info->info3.base.domain.string) {
381 fstrcpy(netbios_domain_name,
382 logon_info->info3.base.domain.string);
383 domain = netbios_domain_name;
384 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
386 } else {
388 /* If we have winbind running, we can (and must) shorten the
389 username by using the short netbios name. Otherwise we will
390 have inconsistent user names. With Kerberos, we get the
391 fully qualified realm, with ntlmssp we get the short
392 name. And even w2k3 does use ntlmssp if you for example
393 connect to an ip address. */
395 wbcErr wbc_status;
396 struct wbcDomainInfo *info = NULL;
398 DEBUG(10, ("Mapping [%s] to short name\n", domain));
400 wbc_status = wbcDomainInfo(domain, &info);
402 if (WBC_ERROR_IS_OK(wbc_status)) {
404 fstrcpy(netbios_domain_name,
405 info->short_name);
407 wbcFreeMemory(info);
408 domain = netbios_domain_name;
409 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
410 } else {
411 DEBUG(3, ("Could not find short name: %s\n",
412 wbcErrorString(wbc_status)));
416 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
418 /* lookup the passwd struct, create a new user if necessary */
420 username_was_mapped = map_username(user);
422 pw = smb_getpwnam( mem_ctx, user, real_username, True );
424 if (pw) {
425 /* if a real user check pam account restrictions */
426 /* only really perfomed if "obey pam restriction" is true */
427 /* do this before an eventual mapping to guest occurs */
428 ret = smb_pam_accountcheck(pw->pw_name);
429 if ( !NT_STATUS_IS_OK(ret)) {
430 DEBUG(1,("PAM account restriction "
431 "prevents user login\n"));
432 data_blob_free(&ap_rep);
433 data_blob_free(&session_key);
434 TALLOC_FREE(mem_ctx);
435 reply_nterror(req, nt_status_squash(ret));
436 return;
440 if (!pw) {
442 /* this was originally the behavior of Samba 2.2, if a user
443 did not have a local uid but has been authenticated, then
444 map them to a guest account */
446 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
447 map_domainuser_to_guest = True;
448 fstrcpy(user,lp_guestaccount());
449 pw = smb_getpwnam( mem_ctx, user, real_username, True );
452 /* extra sanity check that the guest account is valid */
454 if ( !pw ) {
455 DEBUG(1,("Username %s is invalid on this system\n",
456 user));
457 data_blob_free(&ap_rep);
458 data_blob_free(&session_key);
459 TALLOC_FREE(mem_ctx);
460 reply_nterror(req, nt_status_squash(
461 NT_STATUS_LOGON_FAILURE));
462 return;
466 /* setup the string used by %U */
468 sub_set_smb_name( real_username );
469 reload_services(True);
471 if ( map_domainuser_to_guest ) {
472 make_server_info_guest(NULL, &server_info);
473 } else if (logon_info) {
474 /* pass the unmapped username here since map_username()
475 will be called again from inside make_server_info_info3() */
477 ret = make_server_info_info3(mem_ctx, client, domain,
478 &server_info, &logon_info->info3);
479 if ( !NT_STATUS_IS_OK(ret) ) {
480 DEBUG(1,("make_server_info_info3 failed: %s!\n",
481 nt_errstr(ret)));
482 data_blob_free(&ap_rep);
483 data_blob_free(&session_key);
484 TALLOC_FREE(mem_ctx);
485 reply_nterror(req, nt_status_squash(ret));
486 return;
489 } else {
491 * We didn't get a PAC, we have to make up the user
492 * ourselves. Try to ask the pdb backend to provide
493 * SID consistency with ntlmssp session setup
495 struct samu *sampass;
497 sampass = samu_new(talloc_tos());
498 if (sampass == NULL) {
499 ret = NT_STATUS_NO_MEMORY;
500 data_blob_free(&ap_rep);
501 data_blob_free(&session_key);
502 TALLOC_FREE(mem_ctx);
503 reply_nterror(req, nt_status_squash(ret));
504 return;
507 if (pdb_getsampwnam(sampass, real_username)) {
508 DEBUG(10, ("found user %s in passdb, calling "
509 "make_server_info_sam\n", real_username));
510 ret = make_server_info_sam(&server_info, sampass);
511 TALLOC_FREE(sampass);
512 } else {
514 * User not in passdb, make it up artificially
516 TALLOC_FREE(sampass);
517 DEBUG(10, ("didn't find user %s in passdb, calling "
518 "make_server_info_pw\n", real_username));
519 ret = make_server_info_pw(&server_info, real_username,
520 pw);
523 if ( !NT_STATUS_IS_OK(ret) ) {
524 DEBUG(1,("make_server_info_[sam|pw] failed: %s!\n",
525 nt_errstr(ret)));
526 data_blob_free(&ap_rep);
527 data_blob_free(&session_key);
528 TALLOC_FREE(mem_ctx);
529 reply_nterror(req, nt_status_squash(ret));
530 return;
533 /* make_server_info_pw does not set the domain. Without this
534 * we end up with the local netbios name in substitutions for
535 * %D. */
537 if (server_info->info3 != NULL) {
538 server_info->info3->base.domain.string =
539 talloc_strdup(server_info->info3, domain);
543 server_info->nss_token |= username_was_mapped;
545 /* we need to build the token for the user. make_server_info_guest()
546 already does this */
548 if ( !server_info->ptok ) {
549 ret = create_local_token( server_info );
550 if ( !NT_STATUS_IS_OK(ret) ) {
551 DEBUG(10,("failed to create local token: %s\n",
552 nt_errstr(ret)));
553 data_blob_free(&ap_rep);
554 data_blob_free(&session_key);
555 TALLOC_FREE( mem_ctx );
556 TALLOC_FREE( server_info );
557 reply_nterror(req, nt_status_squash(ret));
558 return;
562 if (!is_partial_auth_vuid(sconn, sess_vuid)) {
563 sess_vuid = register_initial_vuid(sconn);
566 data_blob_free(&server_info->user_session_key);
567 server_info->user_session_key = session_key;
568 talloc_steal(server_info, session_key.data);
570 session_key = data_blob_null;
572 /* register_existing_vuid keeps the server info */
573 /* register_existing_vuid takes ownership of session_key on success,
574 * no need to free after this on success. A better interface would copy
575 * it.... */
577 sess_vuid = register_existing_vuid(sconn,
578 sess_vuid,
579 server_info,
580 nullblob,
581 client);
583 reply_outbuf(req, 4, 0);
584 SSVAL(req->outbuf,smb_uid,sess_vuid);
586 if (sess_vuid == UID_FIELD_INVALID ) {
587 ret = NT_STATUS_LOGON_FAILURE;
588 } else {
589 /* current_user_info is changed on new vuid */
590 reload_services( True );
592 SSVAL(req->outbuf, smb_vwv3, 0);
594 if (server_info->guest) {
595 SSVAL(req->outbuf,smb_vwv2,1);
598 SSVAL(req->outbuf, smb_uid, sess_vuid);
600 /* Successful logon. Keep this vuid. */
601 *p_invalidate_vuid = False;
604 /* wrap that up in a nice GSS-API wrapping */
605 if (NT_STATUS_IS_OK(ret)) {
606 ap_rep_wrapped = spnego_gen_krb5_wrap(talloc_tos(), ap_rep,
607 TOK_ID_KRB_AP_REP);
608 } else {
609 ap_rep_wrapped = data_blob_null;
611 response = spnego_gen_auth_response(talloc_tos(), &ap_rep_wrapped, ret,
612 mechOID);
613 reply_sesssetup_blob(req, response, ret);
615 data_blob_free(&ap_rep);
616 data_blob_free(&ap_rep_wrapped);
617 data_blob_free(&response);
618 TALLOC_FREE(mem_ctx);
621 #endif
623 /****************************************************************************
624 Send a session setup reply, wrapped in SPNEGO.
625 Get vuid and check first.
626 End the NTLMSSP exchange context if we are OK/complete fail
627 This should be split into two functions, one to handle each
628 leg of the NTLM auth steps.
629 ***************************************************************************/
631 static void reply_spnego_ntlmssp(struct smb_request *req,
632 uint16 vuid,
633 struct auth_ntlmssp_state **auth_ntlmssp_state,
634 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
635 const char *OID,
636 bool wrap)
638 bool do_invalidate = true;
639 DATA_BLOB response;
640 struct auth_serversupplied_info *server_info = NULL;
641 struct smbd_server_connection *sconn = req->sconn;
643 if (NT_STATUS_IS_OK(nt_status)) {
644 nt_status = auth_ntlmssp_steal_server_info(talloc_tos(),
645 (*auth_ntlmssp_state), &server_info);
646 } else {
647 /* Note that this server_info won't have a session
648 * key. But for map to guest, that's exactly the right
649 * thing - we can't reasonably guess the key the
650 * client wants, as the password was wrong */
651 nt_status = do_map_to_guest(nt_status,
652 &server_info,
653 auth_ntlmssp_get_username(*auth_ntlmssp_state),
654 auth_ntlmssp_get_domain(*auth_ntlmssp_state));
657 reply_outbuf(req, 4, 0);
659 SSVAL(req->outbuf, smb_uid, vuid);
661 if (NT_STATUS_IS_OK(nt_status)) {
662 DATA_BLOB nullblob = data_blob_null;
664 if (!is_partial_auth_vuid(sconn, vuid)) {
665 nt_status = NT_STATUS_LOGON_FAILURE;
666 goto out;
669 /* register_existing_vuid keeps the server info */
670 if (register_existing_vuid(sconn, vuid,
671 server_info, nullblob,
672 auth_ntlmssp_get_username(*auth_ntlmssp_state)) !=
673 vuid) {
674 /* The problem is, *auth_ntlmssp_state points
675 * into the vuser this will have
676 * talloc_free()'ed in
677 * register_existing_vuid() */
678 do_invalidate = false;
679 nt_status = NT_STATUS_LOGON_FAILURE;
680 goto out;
683 /* current_user_info is changed on new vuid */
684 reload_services( True );
686 SSVAL(req->outbuf, smb_vwv3, 0);
688 if (server_info->guest) {
689 SSVAL(req->outbuf,smb_vwv2,1);
693 out:
695 if (wrap) {
696 response = spnego_gen_auth_response(talloc_tos(),
697 ntlmssp_blob,
698 nt_status, OID);
699 } else {
700 response = *ntlmssp_blob;
703 reply_sesssetup_blob(req, response, nt_status);
704 if (wrap) {
705 data_blob_free(&response);
708 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
709 and the other end, that we are not finished yet. */
711 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
712 /* NB. This is *NOT* an error case. JRA */
713 if (do_invalidate) {
714 TALLOC_FREE(*auth_ntlmssp_state);
715 if (!NT_STATUS_IS_OK(nt_status)) {
716 /* Kill the intermediate vuid */
717 invalidate_vuid(sconn, vuid);
723 /****************************************************************************
724 Is this a krb5 mechanism ?
725 ****************************************************************************/
727 NTSTATUS parse_spnego_mechanisms(TALLOC_CTX *ctx,
728 DATA_BLOB blob_in,
729 DATA_BLOB *pblob_out,
730 char **kerb_mechOID)
732 char *OIDs[ASN1_MAX_OIDS];
733 int i;
734 NTSTATUS ret = NT_STATUS_OK;
736 *kerb_mechOID = NULL;
738 /* parse out the OIDs and the first sec blob */
739 if (!spnego_parse_negTokenInit(ctx, blob_in, OIDs, NULL, pblob_out)) {
740 return NT_STATUS_LOGON_FAILURE;
743 /* only look at the first OID for determining the mechToken --
744 according to RFC2478, we should choose the one we want
745 and renegotiate, but i smell a client bug here..
747 Problem observed when connecting to a member (samba box)
748 of an AD domain as a user in a Samba domain. Samba member
749 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
750 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
751 NTLMSSP mechtoken. --jerry */
753 #ifdef HAVE_KRB5
754 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
755 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
756 *kerb_mechOID = talloc_strdup(ctx, OIDs[0]);
757 if (*kerb_mechOID == NULL) {
758 ret = NT_STATUS_NO_MEMORY;
761 #endif
763 for (i=0;OIDs[i];i++) {
764 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
765 talloc_free(OIDs[i]);
767 return ret;
770 /****************************************************************************
771 Fall back from krb5 to NTLMSSP.
772 ****************************************************************************/
774 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
775 uint16 vuid)
777 DATA_BLOB response;
779 reply_outbuf(req, 4, 0);
780 SSVAL(req->outbuf,smb_uid,vuid);
782 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
783 "but set to downgrade to NTLMSSP\n"));
785 response = spnego_gen_auth_response(talloc_tos(), NULL,
786 NT_STATUS_MORE_PROCESSING_REQUIRED,
787 OID_NTLMSSP);
788 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
789 data_blob_free(&response);
792 /****************************************************************************
793 Reply to a session setup spnego negotiate packet.
794 ****************************************************************************/
796 static void reply_spnego_negotiate(struct smb_request *req,
797 uint16 vuid,
798 DATA_BLOB blob1,
799 struct auth_ntlmssp_state **auth_ntlmssp_state)
801 DATA_BLOB secblob;
802 DATA_BLOB chal;
803 char *kerb_mech = NULL;
804 NTSTATUS status;
805 struct smbd_server_connection *sconn = req->sconn;
807 status = parse_spnego_mechanisms(talloc_tos(),
808 blob1, &secblob, &kerb_mech);
809 if (!NT_STATUS_IS_OK(status)) {
810 /* Kill the intermediate vuid */
811 invalidate_vuid(sconn, vuid);
812 reply_nterror(req, nt_status_squash(status));
813 return;
816 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
817 (unsigned long)secblob.length));
819 #ifdef HAVE_KRB5
820 if (kerb_mech && ((lp_security()==SEC_ADS) ||
821 USE_KERBEROS_KEYTAB) ) {
822 bool destroy_vuid = True;
823 reply_spnego_kerberos(req, &secblob, kerb_mech,
824 vuid, &destroy_vuid);
825 data_blob_free(&secblob);
826 if (destroy_vuid) {
827 /* Kill the intermediate vuid */
828 invalidate_vuid(sconn, vuid);
830 TALLOC_FREE(kerb_mech);
831 return;
833 #endif
835 if (*auth_ntlmssp_state) {
836 TALLOC_FREE(*auth_ntlmssp_state);
839 if (kerb_mech) {
840 data_blob_free(&secblob);
841 /* The mechtoken is a krb5 ticket, but
842 * we need to fall back to NTLM. */
843 reply_spnego_downgrade_to_ntlmssp(req, vuid);
844 TALLOC_FREE(kerb_mech);
845 return;
848 status = auth_ntlmssp_start(auth_ntlmssp_state);
849 if (!NT_STATUS_IS_OK(status)) {
850 /* Kill the intermediate vuid */
851 invalidate_vuid(sconn, vuid);
852 reply_nterror(req, nt_status_squash(status));
853 return;
856 status = auth_ntlmssp_update(*auth_ntlmssp_state,
857 secblob, &chal);
859 data_blob_free(&secblob);
861 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
862 &chal, status, OID_NTLMSSP, true);
864 data_blob_free(&chal);
866 /* already replied */
867 return;
870 /****************************************************************************
871 Reply to a session setup spnego auth packet.
872 ****************************************************************************/
874 static void reply_spnego_auth(struct smb_request *req,
875 uint16 vuid,
876 DATA_BLOB blob1,
877 struct auth_ntlmssp_state **auth_ntlmssp_state)
879 DATA_BLOB auth = data_blob_null;
880 DATA_BLOB auth_reply = data_blob_null;
881 DATA_BLOB secblob = data_blob_null;
882 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
883 struct smbd_server_connection *sconn = req->sconn;
885 if (!spnego_parse_auth(talloc_tos(), blob1, &auth)) {
886 #if 0
887 file_save("auth.dat", blob1.data, blob1.length);
888 #endif
889 /* Kill the intermediate vuid */
890 invalidate_vuid(sconn, vuid);
892 reply_nterror(req, nt_status_squash(
893 NT_STATUS_LOGON_FAILURE));
894 return;
897 if (auth.data[0] == ASN1_APPLICATION(0)) {
898 /* Might be a second negTokenTarg packet */
899 char *kerb_mech = NULL;
901 status = parse_spnego_mechanisms(talloc_tos(),
902 auth, &secblob, &kerb_mech);
904 if (!NT_STATUS_IS_OK(status)) {
905 /* Kill the intermediate vuid */
906 invalidate_vuid(sconn, vuid);
907 reply_nterror(req, nt_status_squash(status));
908 return;
911 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
912 (unsigned long)secblob.length));
913 #ifdef HAVE_KRB5
914 if (kerb_mech && ((lp_security()==SEC_ADS) ||
915 USE_KERBEROS_KEYTAB)) {
916 bool destroy_vuid = True;
917 reply_spnego_kerberos(req, &secblob, kerb_mech,
918 vuid, &destroy_vuid);
919 data_blob_free(&secblob);
920 data_blob_free(&auth);
921 if (destroy_vuid) {
922 /* Kill the intermediate vuid */
923 invalidate_vuid(sconn, vuid);
925 TALLOC_FREE(kerb_mech);
926 return;
928 #endif
929 /* Can't blunder into NTLMSSP auth if we have
930 * a krb5 ticket. */
932 if (kerb_mech) {
933 /* Kill the intermediate vuid */
934 invalidate_vuid(sconn, vuid);
935 DEBUG(3,("reply_spnego_auth: network "
936 "misconfiguration, client sent us a "
937 "krb5 ticket and kerberos security "
938 "not enabled\n"));
939 reply_nterror(req, nt_status_squash(
940 NT_STATUS_LOGON_FAILURE));
941 TALLOC_FREE(kerb_mech);
945 /* If we get here it wasn't a negTokenTarg auth packet. */
946 data_blob_free(&secblob);
948 if (!*auth_ntlmssp_state) {
949 status = auth_ntlmssp_start(auth_ntlmssp_state);
950 if (!NT_STATUS_IS_OK(status)) {
951 /* Kill the intermediate vuid */
952 invalidate_vuid(sconn, vuid);
953 reply_nterror(req, nt_status_squash(status));
954 return;
958 status = auth_ntlmssp_update(*auth_ntlmssp_state,
959 auth, &auth_reply);
961 data_blob_free(&auth);
963 /* Don't send the mechid as we've already sent this (RFC4178). */
965 reply_spnego_ntlmssp(req, vuid,
966 auth_ntlmssp_state,
967 &auth_reply, status, NULL, true);
969 data_blob_free(&auth_reply);
971 /* and tell smbd that we have already replied to this packet */
972 return;
975 /****************************************************************************
976 Delete an entry on the list.
977 ****************************************************************************/
979 static void delete_partial_auth(struct smbd_server_connection *sconn,
980 struct pending_auth_data *pad)
982 if (!pad) {
983 return;
985 DLIST_REMOVE(sconn->smb1.pd_list, pad);
986 data_blob_free(&pad->partial_data);
987 SAFE_FREE(pad);
990 /****************************************************************************
991 Search for a partial SPNEGO auth fragment matching an smbpid.
992 ****************************************************************************/
994 static struct pending_auth_data *get_pending_auth_data(
995 struct smbd_server_connection *sconn,
996 uint16_t smbpid)
998 struct pending_auth_data *pad;
1000 * NOTE: using the smbpid here is completely wrong...
1001 * see [MS-SMB]
1002 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
1004 for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
1005 if (pad->smbpid == smbpid) {
1006 break;
1009 return pad;
1012 /****************************************************************************
1013 Check the size of an SPNEGO blob. If we need more return
1014 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
1015 the blob to be more than 64k.
1016 ****************************************************************************/
1018 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
1019 uint16 smbpid, uint16 vuid,
1020 DATA_BLOB *pblob)
1022 struct pending_auth_data *pad = NULL;
1023 ASN1_DATA *data;
1024 size_t needed_len = 0;
1026 pad = get_pending_auth_data(sconn, smbpid);
1028 /* Ensure we have some data. */
1029 if (pblob->length == 0) {
1030 /* Caller can cope. */
1031 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
1032 delete_partial_auth(sconn, pad);
1033 return NT_STATUS_OK;
1036 /* Were we waiting for more data ? */
1037 if (pad) {
1038 DATA_BLOB tmp_blob;
1039 size_t copy_len = MIN(65536, pblob->length);
1041 /* Integer wrap paranoia.... */
1043 if (pad->partial_data.length + copy_len <
1044 pad->partial_data.length ||
1045 pad->partial_data.length + copy_len < copy_len) {
1047 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1048 "pad->partial_data.length = %u, "
1049 "copy_len = %u\n",
1050 (unsigned int)pad->partial_data.length,
1051 (unsigned int)copy_len ));
1053 delete_partial_auth(sconn, pad);
1054 return NT_STATUS_INVALID_PARAMETER;
1057 DEBUG(10,("check_spnego_blob_complete: "
1058 "pad->partial_data.length = %u, "
1059 "pad->needed_len = %u, "
1060 "copy_len = %u, "
1061 "pblob->length = %u,\n",
1062 (unsigned int)pad->partial_data.length,
1063 (unsigned int)pad->needed_len,
1064 (unsigned int)copy_len,
1065 (unsigned int)pblob->length ));
1067 tmp_blob = data_blob(NULL,
1068 pad->partial_data.length + copy_len);
1070 /* Concatenate the two (up to copy_len) bytes. */
1071 memcpy(tmp_blob.data,
1072 pad->partial_data.data,
1073 pad->partial_data.length);
1074 memcpy(tmp_blob.data + pad->partial_data.length,
1075 pblob->data,
1076 copy_len);
1078 /* Replace the partial data. */
1079 data_blob_free(&pad->partial_data);
1080 pad->partial_data = tmp_blob;
1081 ZERO_STRUCT(tmp_blob);
1083 /* Are we done ? */
1084 if (pblob->length >= pad->needed_len) {
1085 /* Yes, replace pblob. */
1086 data_blob_free(pblob);
1087 *pblob = pad->partial_data;
1088 ZERO_STRUCT(pad->partial_data);
1089 delete_partial_auth(sconn, pad);
1090 return NT_STATUS_OK;
1093 /* Still need more data. */
1094 pad->needed_len -= copy_len;
1095 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1098 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
1099 (pblob->data[0] != ASN1_CONTEXT(1))) {
1100 /* Not something we can determine the
1101 * length of.
1103 return NT_STATUS_OK;
1106 /* This is a new SPNEGO sessionsetup - see if
1107 * the data given in this blob is enough.
1110 data = asn1_init(NULL);
1111 if (data == NULL) {
1112 return NT_STATUS_NO_MEMORY;
1115 asn1_load(data, *pblob);
1116 asn1_start_tag(data, pblob->data[0]);
1117 if (data->has_error || data->nesting == NULL) {
1118 asn1_free(data);
1119 /* Let caller catch. */
1120 return NT_STATUS_OK;
1123 /* Integer wrap paranoia.... */
1125 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
1126 data->nesting->taglen + data->nesting->start < data->nesting->start) {
1128 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1129 "data.nesting->taglen = %u, "
1130 "data.nesting->start = %u\n",
1131 (unsigned int)data->nesting->taglen,
1132 (unsigned int)data->nesting->start ));
1134 asn1_free(data);
1135 return NT_STATUS_INVALID_PARAMETER;
1138 /* Total length of the needed asn1 is the tag length
1139 * plus the current offset. */
1141 needed_len = data->nesting->taglen + data->nesting->start;
1142 asn1_free(data);
1144 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1145 "pblob->length = %u\n",
1146 (unsigned int)needed_len,
1147 (unsigned int)pblob->length ));
1149 if (needed_len <= pblob->length) {
1150 /* Nothing to do - blob is complete. */
1151 return NT_STATUS_OK;
1154 /* Refuse the blob if it's bigger than 64k. */
1155 if (needed_len > 65536) {
1156 DEBUG(2,("check_spnego_blob_complete: needed_len "
1157 "too large (%u)\n",
1158 (unsigned int)needed_len ));
1159 return NT_STATUS_INVALID_PARAMETER;
1162 /* We must store this blob until complete. */
1163 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1164 return NT_STATUS_NO_MEMORY;
1166 pad->needed_len = needed_len - pblob->length;
1167 pad->partial_data = data_blob(pblob->data, pblob->length);
1168 if (pad->partial_data.data == NULL) {
1169 SAFE_FREE(pad);
1170 return NT_STATUS_NO_MEMORY;
1172 pad->smbpid = smbpid;
1173 pad->vuid = vuid;
1174 DLIST_ADD(sconn->smb1.pd_list, pad);
1176 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1179 /****************************************************************************
1180 Reply to a session setup command.
1181 conn POINTER CAN BE NULL HERE !
1182 ****************************************************************************/
1184 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1186 const uint8 *p;
1187 DATA_BLOB blob1;
1188 size_t bufrem;
1189 char *tmp;
1190 const char *native_os;
1191 const char *native_lanman;
1192 const char *primary_domain;
1193 const char *p2;
1194 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1195 enum remote_arch_types ra_type = get_remote_arch();
1196 int vuid = req->vuid;
1197 user_struct *vuser = NULL;
1198 NTSTATUS status = NT_STATUS_OK;
1199 uint16 smbpid = req->smbpid;
1200 struct smbd_server_connection *sconn = req->sconn;
1202 DEBUG(3,("Doing spnego session setup\n"));
1204 if (global_client_caps == 0) {
1205 global_client_caps = IVAL(req->vwv+10, 0);
1207 if (!(global_client_caps & CAP_STATUS32)) {
1208 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1213 p = req->buf;
1215 if (data_blob_len == 0) {
1216 /* an invalid request */
1217 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1218 return;
1221 bufrem = smbreq_bufrem(req, p);
1222 /* pull the spnego blob */
1223 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1225 #if 0
1226 file_save("negotiate.dat", blob1.data, blob1.length);
1227 #endif
1229 p2 = (char *)req->buf + blob1.length;
1231 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1232 STR_TERMINATE);
1233 native_os = tmp ? tmp : "";
1235 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1236 STR_TERMINATE);
1237 native_lanman = tmp ? tmp : "";
1239 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1240 STR_TERMINATE);
1241 primary_domain = tmp ? tmp : "";
1243 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1244 native_os, native_lanman, primary_domain));
1246 if ( ra_type == RA_WIN2K ) {
1247 /* Vista sets neither the OS or lanman strings */
1249 if ( !strlen(native_os) && !strlen(native_lanman) )
1250 set_remote_arch(RA_VISTA);
1252 /* Windows 2003 doesn't set the native lanman string,
1253 but does set primary domain which is a bug I think */
1255 if ( !strlen(native_lanman) ) {
1256 ra_lanman_string( primary_domain );
1257 } else {
1258 ra_lanman_string( native_lanman );
1262 /* Did we get a valid vuid ? */
1263 if (!is_partial_auth_vuid(sconn, vuid)) {
1264 /* No, then try and see if this is an intermediate sessionsetup
1265 * for a large SPNEGO packet. */
1266 struct pending_auth_data *pad;
1267 pad = get_pending_auth_data(sconn, smbpid);
1268 if (pad) {
1269 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1270 "pending vuid %u\n",
1271 (unsigned int)pad->vuid ));
1272 vuid = pad->vuid;
1276 /* Do we have a valid vuid now ? */
1277 if (!is_partial_auth_vuid(sconn, vuid)) {
1278 /* No, start a new authentication setup. */
1279 vuid = register_initial_vuid(sconn);
1280 if (vuid == UID_FIELD_INVALID) {
1281 data_blob_free(&blob1);
1282 reply_nterror(req, nt_status_squash(
1283 NT_STATUS_INVALID_PARAMETER));
1284 return;
1288 vuser = get_partial_auth_user_struct(sconn, vuid);
1289 /* This MUST be valid. */
1290 if (!vuser) {
1291 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1294 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1295 * sessionsetup requests as the Windows limit on the security blob
1296 * field is 4k. Bug #4400. JRA.
1299 status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1300 if (!NT_STATUS_IS_OK(status)) {
1301 if (!NT_STATUS_EQUAL(status,
1302 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1303 /* Real error - kill the intermediate vuid */
1304 invalidate_vuid(sconn, vuid);
1306 data_blob_free(&blob1);
1307 reply_nterror(req, nt_status_squash(status));
1308 return;
1311 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1313 /* its a negTokenTarg packet */
1315 reply_spnego_negotiate(req, vuid, blob1,
1316 &vuser->auth_ntlmssp_state);
1317 data_blob_free(&blob1);
1318 return;
1321 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1323 /* its a auth packet */
1325 reply_spnego_auth(req, vuid, blob1,
1326 &vuser->auth_ntlmssp_state);
1327 data_blob_free(&blob1);
1328 return;
1331 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1332 DATA_BLOB chal;
1334 if (!vuser->auth_ntlmssp_state) {
1335 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1336 if (!NT_STATUS_IS_OK(status)) {
1337 /* Kill the intermediate vuid */
1338 invalidate_vuid(sconn, vuid);
1339 data_blob_free(&blob1);
1340 reply_nterror(req, nt_status_squash(status));
1341 return;
1345 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1346 blob1, &chal);
1348 data_blob_free(&blob1);
1350 reply_spnego_ntlmssp(req, vuid,
1351 &vuser->auth_ntlmssp_state,
1352 &chal, status, OID_NTLMSSP, false);
1353 data_blob_free(&chal);
1354 return;
1357 /* what sort of packet is this? */
1358 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1360 data_blob_free(&blob1);
1362 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1365 /****************************************************************************
1366 On new VC == 0, shutdown *all* old connections and users.
1367 It seems that only NT4.x does this. At W2K and above (XP etc.).
1368 a new session setup with VC==0 is ignored.
1369 ****************************************************************************/
1371 struct shutdown_state {
1372 const char *ip;
1373 struct messaging_context *msg_ctx;
1376 static int shutdown_other_smbds(const struct connections_key *key,
1377 const struct connections_data *crec,
1378 void *private_data)
1380 struct shutdown_state *state = (struct shutdown_state *)private_data;
1382 if (!process_exists(crec->pid)) {
1383 return 0;
1386 if (procid_is_me(&crec->pid)) {
1387 return 0;
1390 if (strcmp(state->ip, crec->addr) != 0) {
1391 return 0;
1394 DEBUG(0,("shutdown_other_smbds: shutting down pid %u "
1395 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
1396 state->ip));
1398 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
1399 &data_blob_null);
1400 return 0;
1403 static void setup_new_vc_session(struct messaging_context *msg_ctx)
1405 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1406 "compatible we would close all old resources.\n"));
1407 #if 0
1408 conn_close_all();
1409 invalidate_all_vuids();
1410 #endif
1411 if (lp_reset_on_zero_vc()) {
1412 char addr[INET6_ADDRSTRLEN];
1413 struct shutdown_state state;
1415 state.ip = client_addr(get_client_fd(),addr,sizeof(addr));
1416 state.msg_ctx = msg_ctx;
1417 connections_forall_read(shutdown_other_smbds, &state);
1421 /****************************************************************************
1422 Reply to a session setup command.
1423 ****************************************************************************/
1425 void reply_sesssetup_and_X(struct smb_request *req)
1427 int sess_vuid;
1428 int smb_bufsize;
1429 DATA_BLOB lm_resp;
1430 DATA_BLOB nt_resp;
1431 DATA_BLOB plaintext_password;
1432 char *tmp;
1433 const char *user;
1434 fstring sub_user; /* Sanitised username for substituion */
1435 const char *domain;
1436 const char *native_os;
1437 const char *native_lanman;
1438 const char *primary_domain;
1439 struct auth_usersupplied_info *user_info = NULL;
1440 struct auth_serversupplied_info *server_info = NULL;
1441 uint16 smb_flag2 = req->flags2;
1443 NTSTATUS nt_status;
1444 struct smbd_server_connection *sconn = req->sconn;
1446 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1448 START_PROFILE(SMBsesssetupX);
1450 ZERO_STRUCT(lm_resp);
1451 ZERO_STRUCT(nt_resp);
1452 ZERO_STRUCT(plaintext_password);
1454 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1456 /* a SPNEGO session setup has 12 command words, whereas a normal
1457 NT1 session setup has 13. See the cifs spec. */
1458 if (req->wct == 12 &&
1459 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1461 if (!sconn->smb1.negprot.spnego) {
1462 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1463 "at SPNEGO session setup when it was not "
1464 "negotiated.\n"));
1465 reply_nterror(req, nt_status_squash(
1466 NT_STATUS_LOGON_FAILURE));
1467 END_PROFILE(SMBsesssetupX);
1468 return;
1471 if (SVAL(req->vwv+4, 0) == 0) {
1472 setup_new_vc_session(req->sconn->msg_ctx);
1475 reply_sesssetup_and_X_spnego(req);
1476 END_PROFILE(SMBsesssetupX);
1477 return;
1480 smb_bufsize = SVAL(req->vwv+2, 0);
1482 if (get_Protocol() < PROTOCOL_NT1) {
1483 uint16 passlen1 = SVAL(req->vwv+7, 0);
1485 /* Never do NT status codes with protocols before NT1 as we
1486 * don't get client caps. */
1487 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1489 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1490 reply_nterror(req, nt_status_squash(
1491 NT_STATUS_INVALID_PARAMETER));
1492 END_PROFILE(SMBsesssetupX);
1493 return;
1496 if (doencrypt) {
1497 lm_resp = data_blob(req->buf, passlen1);
1498 } else {
1499 plaintext_password = data_blob(req->buf, passlen1+1);
1500 /* Ensure null termination */
1501 plaintext_password.data[passlen1] = 0;
1504 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1505 req->buf + passlen1, STR_TERMINATE);
1506 user = tmp ? tmp : "";
1508 domain = "";
1510 } else {
1511 uint16 passlen1 = SVAL(req->vwv+7, 0);
1512 uint16 passlen2 = SVAL(req->vwv+8, 0);
1513 enum remote_arch_types ra_type = get_remote_arch();
1514 const uint8_t *p = req->buf;
1515 const uint8_t *save_p = req->buf;
1516 uint16 byte_count;
1519 if(global_client_caps == 0) {
1520 global_client_caps = IVAL(req->vwv+11, 0);
1522 if (!(global_client_caps & CAP_STATUS32)) {
1523 remove_from_common_flags2(
1524 FLAGS2_32_BIT_ERROR_CODES);
1527 /* client_caps is used as final determination if
1528 * client is NT or Win95. This is needed to return
1529 * the correct error codes in some circumstances.
1532 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1533 ra_type == RA_WIN95) {
1534 if(!(global_client_caps & (CAP_NT_SMBS|
1535 CAP_STATUS32))) {
1536 set_remote_arch( RA_WIN95);
1541 if (!doencrypt) {
1542 /* both Win95 and WinNT stuff up the password
1543 * lengths for non-encrypting systems. Uggh.
1545 if passlen1==24 its a win95 system, and its setting
1546 the password length incorrectly. Luckily it still
1547 works with the default code because Win95 will null
1548 terminate the password anyway
1550 if passlen1>0 and passlen2>0 then maybe its a NT box
1551 and its setting passlen2 to some random value which
1552 really stuffs things up. we need to fix that one. */
1554 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1555 passlen2 != 1) {
1556 passlen2 = 0;
1560 /* check for nasty tricks */
1561 if (passlen1 > MAX_PASS_LEN
1562 || passlen1 > smbreq_bufrem(req, p)) {
1563 reply_nterror(req, nt_status_squash(
1564 NT_STATUS_INVALID_PARAMETER));
1565 END_PROFILE(SMBsesssetupX);
1566 return;
1569 if (passlen2 > MAX_PASS_LEN
1570 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1571 reply_nterror(req, nt_status_squash(
1572 NT_STATUS_INVALID_PARAMETER));
1573 END_PROFILE(SMBsesssetupX);
1574 return;
1577 /* Save the lanman2 password and the NT md4 password. */
1579 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1580 doencrypt = False;
1583 if (doencrypt) {
1584 lm_resp = data_blob(p, passlen1);
1585 nt_resp = data_blob(p+passlen1, passlen2);
1586 } else if (lp_security() != SEC_SHARE) {
1588 * In share level we should ignore any passwords, so
1589 * only read them if we're not.
1591 char *pass = NULL;
1592 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1594 if (unic && (passlen2 == 0) && passlen1) {
1595 /* Only a ascii plaintext password was sent. */
1596 (void)srvstr_pull_talloc(talloc_tos(),
1597 req->inbuf,
1598 req->flags2,
1599 &pass,
1600 req->buf,
1601 passlen1,
1602 STR_TERMINATE|STR_ASCII);
1603 } else {
1604 (void)srvstr_pull_talloc(talloc_tos(),
1605 req->inbuf,
1606 req->flags2,
1607 &pass,
1608 req->buf,
1609 unic ? passlen2 : passlen1,
1610 STR_TERMINATE);
1612 if (!pass) {
1613 reply_nterror(req, nt_status_squash(
1614 NT_STATUS_INVALID_PARAMETER));
1615 END_PROFILE(SMBsesssetupX);
1616 return;
1618 plaintext_password = data_blob(pass, strlen(pass)+1);
1621 p += passlen1 + passlen2;
1623 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1624 STR_TERMINATE);
1625 user = tmp ? tmp : "";
1627 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1628 STR_TERMINATE);
1629 domain = tmp ? tmp : "";
1631 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1632 STR_TERMINATE);
1633 native_os = tmp ? tmp : "";
1635 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1636 STR_TERMINATE);
1637 native_lanman = tmp ? tmp : "";
1639 /* not documented or decoded by Ethereal but there is one more
1640 * string in the extra bytes which is the same as the
1641 * PrimaryDomain when using extended security. Windows NT 4
1642 * and 2003 use this string to store the native lanman string.
1643 * Windows 9x does not include a string here at all so we have
1644 * to check if we have any extra bytes left */
1646 byte_count = SVAL(req->vwv+13, 0);
1647 if ( PTR_DIFF(p, save_p) < byte_count) {
1648 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1649 STR_TERMINATE);
1650 primary_domain = tmp ? tmp : "";
1651 } else {
1652 primary_domain = talloc_strdup(talloc_tos(), "null");
1655 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1656 "PrimaryDomain=[%s]\n",
1657 domain, native_os, native_lanman, primary_domain));
1659 if ( ra_type == RA_WIN2K ) {
1660 if ( strlen(native_lanman) == 0 )
1661 ra_lanman_string( primary_domain );
1662 else
1663 ra_lanman_string( native_lanman );
1668 if (SVAL(req->vwv+4, 0) == 0) {
1669 setup_new_vc_session(req->sconn->msg_ctx);
1672 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1673 domain, user, get_remote_machine_name()));
1675 if (*user) {
1676 if (sconn->smb1.negprot.spnego) {
1678 /* This has to be here, because this is a perfectly
1679 * valid behaviour for guest logons :-( */
1681 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1682 "at 'normal' session setup after "
1683 "negotiating spnego.\n"));
1684 reply_nterror(req, nt_status_squash(
1685 NT_STATUS_LOGON_FAILURE));
1686 END_PROFILE(SMBsesssetupX);
1687 return;
1689 fstrcpy(sub_user, user);
1690 } else {
1691 fstrcpy(sub_user, lp_guestaccount());
1694 sub_set_smb_name(sub_user);
1696 reload_services(True);
1698 if (lp_security() == SEC_SHARE) {
1699 /* In share level we should ignore any passwords */
1701 data_blob_free(&lm_resp);
1702 data_blob_free(&nt_resp);
1703 data_blob_clear_free(&plaintext_password);
1705 map_username(sub_user);
1706 add_session_user(sconn, sub_user);
1707 add_session_workgroup(sconn, domain);
1708 /* Then force it to null for the benfit of the code below */
1709 user = "";
1712 if (!*user) {
1714 nt_status = check_guest_password(&server_info);
1716 } else if (doencrypt) {
1717 struct auth_context *negprot_auth_context = NULL;
1718 negprot_auth_context = sconn->smb1.negprot.auth_context;
1719 if (!negprot_auth_context) {
1720 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1721 "session setup without negprot denied!\n"));
1722 reply_nterror(req, nt_status_squash(
1723 NT_STATUS_LOGON_FAILURE));
1724 END_PROFILE(SMBsesssetupX);
1725 return;
1727 nt_status = make_user_info_for_reply_enc(&user_info, user,
1728 domain,
1729 lm_resp, nt_resp);
1730 if (NT_STATUS_IS_OK(nt_status)) {
1731 nt_status = negprot_auth_context->check_ntlm_password(
1732 negprot_auth_context,
1733 user_info,
1734 &server_info);
1736 } else {
1737 struct auth_context *plaintext_auth_context = NULL;
1739 nt_status = make_auth_context_subsystem(
1740 &plaintext_auth_context);
1742 if (NT_STATUS_IS_OK(nt_status)) {
1743 uint8_t chal[8];
1745 plaintext_auth_context->get_ntlm_challenge(
1746 plaintext_auth_context, chal);
1748 if (!make_user_info_for_reply(&user_info,
1749 user, domain, chal,
1750 plaintext_password)) {
1751 nt_status = NT_STATUS_NO_MEMORY;
1754 if (NT_STATUS_IS_OK(nt_status)) {
1755 nt_status = plaintext_auth_context->check_ntlm_password(
1756 plaintext_auth_context,
1757 user_info,
1758 &server_info);
1760 TALLOC_FREE(plaintext_auth_context);
1765 free_user_info(&user_info);
1767 if (!NT_STATUS_IS_OK(nt_status)) {
1768 nt_status = do_map_to_guest(nt_status, &server_info,
1769 user, domain);
1772 if (!NT_STATUS_IS_OK(nt_status)) {
1773 data_blob_free(&nt_resp);
1774 data_blob_free(&lm_resp);
1775 data_blob_clear_free(&plaintext_password);
1776 reply_nterror(req, nt_status_squash(nt_status));
1777 END_PROFILE(SMBsesssetupX);
1778 return;
1781 /* Ensure we can't possible take a code path leading to a
1782 * null defref. */
1783 if (!server_info) {
1784 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1785 END_PROFILE(SMBsesssetupX);
1786 return;
1789 if (!server_info->ptok) {
1790 nt_status = create_local_token(server_info);
1792 if (!NT_STATUS_IS_OK(nt_status)) {
1793 DEBUG(10, ("create_local_token failed: %s\n",
1794 nt_errstr(nt_status)));
1795 data_blob_free(&nt_resp);
1796 data_blob_free(&lm_resp);
1797 data_blob_clear_free(&plaintext_password);
1798 reply_nterror(req, nt_status_squash(nt_status));
1799 END_PROFILE(SMBsesssetupX);
1800 return;
1804 data_blob_clear_free(&plaintext_password);
1806 /* it's ok - setup a reply */
1807 reply_outbuf(req, 3, 0);
1808 if (get_Protocol() >= PROTOCOL_NT1) {
1809 push_signature(&req->outbuf);
1810 /* perhaps grab OS version here?? */
1813 if (server_info->guest) {
1814 SSVAL(req->outbuf,smb_vwv2,1);
1817 /* register the name and uid as being validated, so further connections
1818 to a uid can get through without a password, on the same VC */
1820 if (lp_security() == SEC_SHARE) {
1821 sess_vuid = UID_FIELD_INVALID;
1822 TALLOC_FREE(server_info);
1823 } else {
1824 /* Ignore the initial vuid. */
1825 sess_vuid = register_initial_vuid(sconn);
1826 if (sess_vuid == UID_FIELD_INVALID) {
1827 data_blob_free(&nt_resp);
1828 data_blob_free(&lm_resp);
1829 reply_nterror(req, nt_status_squash(
1830 NT_STATUS_LOGON_FAILURE));
1831 END_PROFILE(SMBsesssetupX);
1832 return;
1834 /* register_existing_vuid keeps the server info */
1835 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1836 server_info,
1837 nt_resp.data ? nt_resp : lm_resp,
1838 sub_user);
1839 if (sess_vuid == UID_FIELD_INVALID) {
1840 data_blob_free(&nt_resp);
1841 data_blob_free(&lm_resp);
1842 reply_nterror(req, nt_status_squash(
1843 NT_STATUS_LOGON_FAILURE));
1844 END_PROFILE(SMBsesssetupX);
1845 return;
1848 /* current_user_info is changed on new vuid */
1849 reload_services( True );
1852 data_blob_free(&nt_resp);
1853 data_blob_free(&lm_resp);
1855 SSVAL(req->outbuf,smb_uid,sess_vuid);
1856 SSVAL(req->inbuf,smb_uid,sess_vuid);
1857 req->vuid = sess_vuid;
1859 if (!sconn->smb1.sessions.done_sesssetup) {
1860 sconn->smb1.sessions.max_send =
1861 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1863 sconn->smb1.sessions.done_sesssetup = true;
1865 END_PROFILE(SMBsesssetupX);
1866 chain_reply(req);
1867 return;