s4:cleanups More trailing spaces and tabs
[Samba.git] / source3 / smbd / sesssetup.c
blob612cf2231ae96dcaa7ee72a71205be620cf14d80
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 "ntlmssp.h"
30 /* For split krb5 SPNEGO blobs. */
31 struct pending_auth_data {
32 struct pending_auth_data *prev, *next;
33 uint16 vuid; /* Tag for this entry. */
34 uint16 smbpid; /* Alternate tag for this entry. */
35 size_t needed_len;
36 DATA_BLOB partial_data;
40 on a logon error possibly map the error to success if "map to guest"
41 is set approriately
43 static NTSTATUS do_map_to_guest(NTSTATUS status,
44 auth_serversupplied_info **server_info,
45 const char *user, const char *domain)
47 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
48 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
49 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
50 DEBUG(3,("No such user %s [%s] - using guest account\n",
51 user, domain));
52 status = make_server_info_guest(NULL, server_info);
56 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
57 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
58 DEBUG(3,("Registered username %s for guest access\n",
59 user));
60 status = make_server_info_guest(NULL, server_info);
64 return status;
67 /****************************************************************************
68 Add the standard 'Samba' signature to the end of the session setup.
69 ****************************************************************************/
71 static int push_signature(uint8 **outbuf)
73 char *lanman;
74 int result, tmp;
76 result = 0;
78 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
80 if (tmp == -1) return -1;
81 result += tmp;
83 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
84 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
85 SAFE_FREE(lanman);
87 else {
88 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
91 if (tmp == -1) return -1;
92 result += tmp;
94 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
96 if (tmp == -1) return -1;
97 result += tmp;
99 return result;
102 /****************************************************************************
103 Send a security blob via a session setup reply.
104 ****************************************************************************/
106 static void reply_sesssetup_blob(struct smb_request *req,
107 DATA_BLOB blob,
108 NTSTATUS nt_status)
110 if (!NT_STATUS_IS_OK(nt_status) &&
111 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
112 reply_nterror(req, nt_status_squash(nt_status));
113 return;
116 nt_status = nt_status_squash(nt_status);
117 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
118 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
119 SSVAL(req->outbuf, smb_vwv3, blob.length);
121 if ((message_push_blob(&req->outbuf, blob) == -1)
122 || (push_signature(&req->outbuf) == -1)) {
123 reply_nterror(req, NT_STATUS_NO_MEMORY);
127 /****************************************************************************
128 Do a 'guest' logon, getting back the
129 ****************************************************************************/
131 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
133 struct auth_context *auth_context;
134 auth_usersupplied_info *user_info = NULL;
136 NTSTATUS nt_status;
137 unsigned char chal[8];
139 ZERO_STRUCT(chal);
141 DEBUG(3,("Got anonymous request\n"));
143 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context,
144 chal))) {
145 return nt_status;
148 if (!make_user_info_guest(&user_info)) {
149 (auth_context->free)(&auth_context);
150 return NT_STATUS_NO_MEMORY;
153 nt_status = auth_context->check_ntlm_password(auth_context,
154 user_info,
155 server_info);
156 (auth_context->free)(&auth_context);
157 free_user_info(&user_info);
158 return nt_status;
162 #ifdef HAVE_KRB5
164 #if 0
165 /* Experiment that failed. See "only happens with a KDC" comment below. */
166 /****************************************************************************
167 Cerate a clock skew error blob for a Windows client.
168 ****************************************************************************/
170 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
172 krb5_context context = NULL;
173 krb5_error_code kerr = 0;
174 krb5_data reply;
175 krb5_principal host_princ = NULL;
176 char *host_princ_s = NULL;
177 bool ret = False;
179 *pblob_out = data_blob_null;
181 initialize_krb5_error_table();
182 kerr = krb5_init_context(&context);
183 if (kerr) {
184 return False;
186 /* Create server principal. */
187 asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
188 if (!host_princ_s) {
189 goto out;
191 strlower_m(host_princ_s);
193 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
194 if (kerr) {
195 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
196 "for name %s: Error %s\n",
197 host_princ_s, error_message(kerr) ));
198 goto out;
201 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
202 host_princ, &reply);
203 if (kerr) {
204 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
205 "failed: Error %s\n",
206 error_message(kerr) ));
207 goto out;
210 *pblob_out = data_blob(reply.data, reply.length);
211 kerberos_free_data_contents(context,&reply);
212 ret = True;
214 out:
216 if (host_princ_s) {
217 SAFE_FREE(host_princ_s);
219 if (host_princ) {
220 krb5_free_principal(context, host_princ);
222 krb5_free_context(context);
223 return ret;
225 #endif
227 /****************************************************************************
228 Reply to a session setup spnego negotiate packet for kerberos.
229 ****************************************************************************/
231 static void reply_spnego_kerberos(struct smb_request *req,
232 DATA_BLOB *secblob,
233 const char *mechOID,
234 uint16 vuid,
235 bool *p_invalidate_vuid)
237 TALLOC_CTX *mem_ctx;
238 DATA_BLOB ticket;
239 char *client, *p, *domain;
240 fstring netbios_domain_name;
241 struct passwd *pw;
242 fstring user;
243 int sess_vuid = req->vuid;
244 NTSTATUS ret = NT_STATUS_OK;
245 struct PAC_DATA *pac_data = NULL;
246 DATA_BLOB ap_rep, ap_rep_wrapped, response;
247 auth_serversupplied_info *server_info = NULL;
248 DATA_BLOB session_key = data_blob_null;
249 uint8 tok_id[2];
250 DATA_BLOB nullblob = data_blob_null;
251 fstring real_username;
252 bool map_domainuser_to_guest = False;
253 bool username_was_mapped;
254 struct PAC_LOGON_INFO *logon_info = NULL;
255 struct smbd_server_connection *sconn = smbd_server_conn;
257 ZERO_STRUCT(ticket);
258 ZERO_STRUCT(ap_rep);
259 ZERO_STRUCT(ap_rep_wrapped);
260 ZERO_STRUCT(response);
262 /* Normally we will always invalidate the intermediate vuid. */
263 *p_invalidate_vuid = True;
265 mem_ctx = talloc_init("reply_spnego_kerberos");
266 if (mem_ctx == NULL) {
267 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
268 return;
271 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
272 talloc_destroy(mem_ctx);
273 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
274 return;
277 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
278 &client, &pac_data, &ap_rep,
279 &session_key, True);
281 data_blob_free(&ticket);
283 if (!NT_STATUS_IS_OK(ret)) {
284 #if 0
285 /* Experiment that failed.
286 * See "only happens with a KDC" comment below. */
288 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
291 * Windows in this case returns
292 * NT_STATUS_MORE_PROCESSING_REQUIRED
293 * with a negTokenTarg blob containing an krb5_error
294 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
295 * The client then fixes its clock and continues rather
296 * than giving an error. JRA.
297 * -- Looks like this only happens with a KDC. JRA.
300 bool ok = make_krb5_skew_error(&ap_rep);
301 if (!ok) {
302 talloc_destroy(mem_ctx);
303 return ERROR_NT(nt_status_squash(
304 NT_STATUS_LOGON_FAILURE));
306 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
307 TOK_ID_KRB_ERROR);
308 response = spnego_gen_auth_response(&ap_rep_wrapped,
309 ret, OID_KERBEROS5_OLD);
310 reply_sesssetup_blob(conn, inbuf, outbuf, response,
311 NT_STATUS_MORE_PROCESSING_REQUIRED);
314 * In this one case we don't invalidate the
315 * intermediate vuid as we're expecting the client
316 * to re-use it for the next sessionsetupX packet. JRA.
319 *p_invalidate_vuid = False;
321 data_blob_free(&ap_rep);
322 data_blob_free(&ap_rep_wrapped);
323 data_blob_free(&response);
324 talloc_destroy(mem_ctx);
325 return -1; /* already replied */
327 #else
328 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
329 ret = NT_STATUS_LOGON_FAILURE;
331 #endif
332 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
333 nt_errstr(ret)));
334 talloc_destroy(mem_ctx);
335 reply_nterror(req, nt_status_squash(ret));
336 return;
339 DEBUG(3,("Ticket name is [%s]\n", client));
341 p = strchr_m(client, '@');
342 if (!p) {
343 DEBUG(3,("Doesn't look like a valid principal\n"));
344 data_blob_free(&ap_rep);
345 data_blob_free(&session_key);
346 talloc_destroy(mem_ctx);
347 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
348 return;
351 *p = 0;
353 /* save the PAC data if we have it */
355 if (pac_data) {
356 logon_info = get_logon_info_from_pac(pac_data);
357 if (logon_info) {
358 netsamlogon_cache_store( client, &logon_info->info3 );
362 if (!strequal(p+1, lp_realm())) {
363 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
364 if (!lp_allow_trusted_domains()) {
365 data_blob_free(&ap_rep);
366 data_blob_free(&session_key);
367 talloc_destroy(mem_ctx);
368 reply_nterror(req, nt_status_squash(
369 NT_STATUS_LOGON_FAILURE));
370 return;
374 /* this gives a fully qualified user name (ie. with full realm).
375 that leads to very long usernames, but what else can we do? */
377 domain = p+1;
379 if (logon_info && logon_info->info3.base.domain.string) {
380 fstrcpy(netbios_domain_name,
381 logon_info->info3.base.domain.string);
382 domain = netbios_domain_name;
383 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
385 } else {
387 /* If we have winbind running, we can (and must) shorten the
388 username by using the short netbios name. Otherwise we will
389 have inconsistent user names. With Kerberos, we get the
390 fully qualified realm, with ntlmssp we get the short
391 name. And even w2k3 does use ntlmssp if you for example
392 connect to an ip address. */
394 wbcErr wbc_status;
395 struct wbcDomainInfo *info = NULL;
397 DEBUG(10, ("Mapping [%s] to short name\n", domain));
399 wbc_status = wbcDomainInfo(domain, &info);
401 if (WBC_ERROR_IS_OK(wbc_status)) {
403 fstrcpy(netbios_domain_name,
404 info->short_name);
406 wbcFreeMemory(info);
407 domain = netbios_domain_name;
408 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
409 } else {
410 DEBUG(3, ("Could not find short name: %s\n",
411 wbcErrorString(wbc_status)));
415 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
417 /* lookup the passwd struct, create a new user if necessary */
419 username_was_mapped = map_username(sconn, user);
421 pw = smb_getpwnam( mem_ctx, user, real_username, True );
423 if (pw) {
424 /* if a real user check pam account restrictions */
425 /* only really perfomed if "obey pam restriction" is true */
426 /* do this before an eventual mapping to guest occurs */
427 ret = smb_pam_accountcheck(pw->pw_name);
428 if ( !NT_STATUS_IS_OK(ret)) {
429 DEBUG(1,("PAM account restriction "
430 "prevents user login\n"));
431 data_blob_free(&ap_rep);
432 data_blob_free(&session_key);
433 TALLOC_FREE(mem_ctx);
434 reply_nterror(req, nt_status_squash(ret));
435 return;
439 if (!pw) {
441 /* this was originally the behavior of Samba 2.2, if a user
442 did not have a local uid but has been authenticated, then
443 map them to a guest account */
445 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
446 map_domainuser_to_guest = True;
447 fstrcpy(user,lp_guestaccount());
448 pw = smb_getpwnam( mem_ctx, user, real_username, True );
451 /* extra sanity check that the guest account is valid */
453 if ( !pw ) {
454 DEBUG(1,("Username %s is invalid on this system\n",
455 user));
456 data_blob_free(&ap_rep);
457 data_blob_free(&session_key);
458 TALLOC_FREE(mem_ctx);
459 reply_nterror(req, nt_status_squash(
460 NT_STATUS_LOGON_FAILURE));
461 return;
465 /* setup the string used by %U */
467 sub_set_smb_name( real_username );
468 reload_services(True);
470 if ( map_domainuser_to_guest ) {
471 make_server_info_guest(NULL, &server_info);
472 } else if (logon_info) {
473 /* pass the unmapped username here since map_username()
474 will be called again from inside make_server_info_info3() */
476 ret = make_server_info_info3(mem_ctx, client, domain,
477 &server_info, &logon_info->info3);
478 if ( !NT_STATUS_IS_OK(ret) ) {
479 DEBUG(1,("make_server_info_info3 failed: %s!\n",
480 nt_errstr(ret)));
481 data_blob_free(&ap_rep);
482 data_blob_free(&session_key);
483 TALLOC_FREE(mem_ctx);
484 reply_nterror(req, nt_status_squash(ret));
485 return;
488 } else {
489 ret = make_server_info_pw(&server_info, real_username, pw);
491 if ( !NT_STATUS_IS_OK(ret) ) {
492 DEBUG(1,("make_server_info_pw failed: %s!\n",
493 nt_errstr(ret)));
494 data_blob_free(&ap_rep);
495 data_blob_free(&session_key);
496 TALLOC_FREE(mem_ctx);
497 reply_nterror(req, nt_status_squash(ret));
498 return;
501 /* make_server_info_pw does not set the domain. Without this
502 * we end up with the local netbios name in substitutions for
503 * %D. */
505 if (server_info->sam_account != NULL) {
506 pdb_set_domain(server_info->sam_account,
507 domain, PDB_SET);
511 server_info->nss_token |= username_was_mapped;
513 /* we need to build the token for the user. make_server_info_guest()
514 already does this */
516 if ( !server_info->ptok ) {
517 ret = create_local_token( server_info );
518 if ( !NT_STATUS_IS_OK(ret) ) {
519 DEBUG(10,("failed to create local token: %s\n",
520 nt_errstr(ret)));
521 data_blob_free(&ap_rep);
522 data_blob_free(&session_key);
523 TALLOC_FREE( mem_ctx );
524 TALLOC_FREE( server_info );
525 reply_nterror(req, nt_status_squash(ret));
526 return;
530 if (!is_partial_auth_vuid(sconn, sess_vuid)) {
531 sess_vuid = register_initial_vuid(sconn);
534 data_blob_free(&server_info->user_session_key);
535 server_info->user_session_key = session_key;
536 session_key = data_blob_null;
538 /* register_existing_vuid keeps the server info */
539 /* register_existing_vuid takes ownership of session_key on success,
540 * no need to free after this on success. A better interface would copy
541 * it.... */
543 sess_vuid = register_existing_vuid(sconn,
544 sess_vuid,
545 server_info,
546 nullblob,
547 client);
549 reply_outbuf(req, 4, 0);
550 SSVAL(req->outbuf,smb_uid,sess_vuid);
552 if (sess_vuid == UID_FIELD_INVALID ) {
553 ret = NT_STATUS_LOGON_FAILURE;
554 } else {
555 /* current_user_info is changed on new vuid */
556 reload_services( True );
558 SSVAL(req->outbuf, smb_vwv3, 0);
560 if (server_info->guest) {
561 SSVAL(req->outbuf,smb_vwv2,1);
564 SSVAL(req->outbuf, smb_uid, sess_vuid);
566 /* Successful logon. Keep this vuid. */
567 *p_invalidate_vuid = False;
570 /* wrap that up in a nice GSS-API wrapping */
571 if (NT_STATUS_IS_OK(ret)) {
572 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
573 TOK_ID_KRB_AP_REP);
574 } else {
575 ap_rep_wrapped = data_blob_null;
577 response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
578 mechOID);
579 reply_sesssetup_blob(req, response, ret);
581 data_blob_free(&ap_rep);
582 data_blob_free(&ap_rep_wrapped);
583 data_blob_free(&response);
584 TALLOC_FREE(mem_ctx);
587 #endif
589 /****************************************************************************
590 Send a session setup reply, wrapped in SPNEGO.
591 Get vuid and check first.
592 End the NTLMSSP exchange context if we are OK/complete fail
593 This should be split into two functions, one to handle each
594 leg of the NTLM auth steps.
595 ***************************************************************************/
597 static void reply_spnego_ntlmssp(struct smb_request *req,
598 uint16 vuid,
599 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
600 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
601 const char *OID,
602 bool wrap)
604 DATA_BLOB response;
605 struct auth_serversupplied_info *server_info = NULL;
606 struct smbd_server_connection *sconn = smbd_server_conn;
608 if (NT_STATUS_IS_OK(nt_status)) {
609 server_info = (*auth_ntlmssp_state)->server_info;
610 } else {
611 nt_status = do_map_to_guest(nt_status,
612 &server_info,
613 (*auth_ntlmssp_state)->ntlmssp_state->user,
614 (*auth_ntlmssp_state)->ntlmssp_state->domain);
617 reply_outbuf(req, 4, 0);
619 SSVAL(req->outbuf, smb_uid, vuid);
621 if (NT_STATUS_IS_OK(nt_status)) {
622 DATA_BLOB nullblob = data_blob_null;
624 if (!is_partial_auth_vuid(sconn, vuid)) {
625 nt_status = NT_STATUS_LOGON_FAILURE;
626 goto out;
629 data_blob_free(&server_info->user_session_key);
630 server_info->user_session_key =
631 data_blob_talloc(
632 server_info,
633 (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
634 (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
636 /* register_existing_vuid keeps the server info */
637 if (register_existing_vuid(sconn, vuid,
638 server_info, nullblob,
639 (*auth_ntlmssp_state)->ntlmssp_state->user) !=
640 vuid) {
641 nt_status = NT_STATUS_LOGON_FAILURE;
642 goto out;
645 (*auth_ntlmssp_state)->server_info = NULL;
647 /* current_user_info is changed on new vuid */
648 reload_services( True );
650 SSVAL(req->outbuf, smb_vwv3, 0);
652 if (server_info->guest) {
653 SSVAL(req->outbuf,smb_vwv2,1);
657 out:
659 if (wrap) {
660 response = spnego_gen_auth_response(ntlmssp_blob,
661 nt_status, OID);
662 } else {
663 response = *ntlmssp_blob;
666 reply_sesssetup_blob(req, response, nt_status);
667 if (wrap) {
668 data_blob_free(&response);
671 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
672 and the other end, that we are not finished yet. */
674 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
675 /* NB. This is *NOT* an error case. JRA */
676 auth_ntlmssp_end(auth_ntlmssp_state);
677 if (!NT_STATUS_IS_OK(nt_status)) {
678 /* Kill the intermediate vuid */
679 invalidate_vuid(sconn, vuid);
684 /****************************************************************************
685 Is this a krb5 mechanism ?
686 ****************************************************************************/
688 NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in,
689 DATA_BLOB *pblob_out,
690 char **kerb_mechOID)
692 char *OIDs[ASN1_MAX_OIDS];
693 int i;
694 NTSTATUS ret = NT_STATUS_OK;
696 *kerb_mechOID = NULL;
698 /* parse out the OIDs and the first sec blob */
699 if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
700 return NT_STATUS_LOGON_FAILURE;
703 /* only look at the first OID for determining the mechToken --
704 according to RFC2478, we should choose the one we want
705 and renegotiate, but i smell a client bug here..
707 Problem observed when connecting to a member (samba box)
708 of an AD domain as a user in a Samba domain. Samba member
709 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
710 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
711 NTLMSSP mechtoken. --jerry */
713 #ifdef HAVE_KRB5
714 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
715 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
716 *kerb_mechOID = SMB_STRDUP(OIDs[0]);
717 if (*kerb_mechOID == NULL) {
718 ret = NT_STATUS_NO_MEMORY;
721 #endif
723 for (i=0;OIDs[i];i++) {
724 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
725 talloc_free(OIDs[i]);
727 return ret;
730 /****************************************************************************
731 Fall back from krb5 to NTLMSSP.
732 ****************************************************************************/
734 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
735 uint16 vuid)
737 DATA_BLOB response;
739 reply_outbuf(req, 4, 0);
740 SSVAL(req->outbuf,smb_uid,vuid);
742 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
743 "but set to downgrade to NTLMSSP\n"));
745 response = spnego_gen_auth_response(NULL,
746 NT_STATUS_MORE_PROCESSING_REQUIRED,
747 OID_NTLMSSP);
748 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
749 data_blob_free(&response);
752 /****************************************************************************
753 Reply to a session setup spnego negotiate packet.
754 ****************************************************************************/
756 static void reply_spnego_negotiate(struct smb_request *req,
757 uint16 vuid,
758 DATA_BLOB blob1,
759 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
761 DATA_BLOB secblob;
762 DATA_BLOB chal;
763 char *kerb_mech = NULL;
764 NTSTATUS status;
765 struct smbd_server_connection *sconn = smbd_server_conn;
767 status = parse_spnego_mechanisms(blob1, &secblob, &kerb_mech);
768 if (!NT_STATUS_IS_OK(status)) {
769 /* Kill the intermediate vuid */
770 invalidate_vuid(sconn, vuid);
771 reply_nterror(req, nt_status_squash(status));
772 return;
775 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
776 (unsigned long)secblob.length));
778 #ifdef HAVE_KRB5
779 if (kerb_mech && ((lp_security()==SEC_ADS) ||
780 USE_KERBEROS_KEYTAB) ) {
781 bool destroy_vuid = True;
782 reply_spnego_kerberos(req, &secblob, kerb_mech,
783 vuid, &destroy_vuid);
784 data_blob_free(&secblob);
785 if (destroy_vuid) {
786 /* Kill the intermediate vuid */
787 invalidate_vuid(sconn, vuid);
789 SAFE_FREE(kerb_mech);
790 return;
792 #endif
794 if (*auth_ntlmssp_state) {
795 auth_ntlmssp_end(auth_ntlmssp_state);
798 if (kerb_mech) {
799 data_blob_free(&secblob);
800 /* The mechtoken is a krb5 ticket, but
801 * we need to fall back to NTLM. */
802 reply_spnego_downgrade_to_ntlmssp(req, vuid);
803 SAFE_FREE(kerb_mech);
804 return;
807 status = auth_ntlmssp_start(auth_ntlmssp_state);
808 if (!NT_STATUS_IS_OK(status)) {
809 /* Kill the intermediate vuid */
810 invalidate_vuid(sconn, vuid);
811 reply_nterror(req, nt_status_squash(status));
812 return;
815 status = auth_ntlmssp_update(*auth_ntlmssp_state,
816 secblob, &chal);
818 data_blob_free(&secblob);
820 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
821 &chal, status, OID_NTLMSSP, true);
823 data_blob_free(&chal);
825 /* already replied */
826 return;
829 /****************************************************************************
830 Reply to a session setup spnego auth packet.
831 ****************************************************************************/
833 static void reply_spnego_auth(struct smb_request *req,
834 uint16 vuid,
835 DATA_BLOB blob1,
836 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
838 DATA_BLOB auth = data_blob_null;
839 DATA_BLOB auth_reply = data_blob_null;
840 DATA_BLOB secblob = data_blob_null;
841 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
842 struct smbd_server_connection *sconn = smbd_server_conn;
844 if (!spnego_parse_auth(blob1, &auth)) {
845 #if 0
846 file_save("auth.dat", blob1.data, blob1.length);
847 #endif
848 /* Kill the intermediate vuid */
849 invalidate_vuid(sconn, vuid);
851 reply_nterror(req, nt_status_squash(
852 NT_STATUS_LOGON_FAILURE));
853 return;
856 if (auth.data[0] == ASN1_APPLICATION(0)) {
857 /* Might be a second negTokenTarg packet */
858 char *kerb_mech = NULL;
860 status = parse_spnego_mechanisms(auth, &secblob, &kerb_mech);
862 if (!NT_STATUS_IS_OK(status)) {
863 /* Kill the intermediate vuid */
864 invalidate_vuid(sconn, vuid);
865 reply_nterror(req, nt_status_squash(status));
866 return;
869 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
870 (unsigned long)secblob.length));
871 #ifdef HAVE_KRB5
872 if (kerb_mech && ((lp_security()==SEC_ADS) ||
873 USE_KERBEROS_KEYTAB)) {
874 bool destroy_vuid = True;
875 reply_spnego_kerberos(req, &secblob, kerb_mech,
876 vuid, &destroy_vuid);
877 data_blob_free(&secblob);
878 data_blob_free(&auth);
879 if (destroy_vuid) {
880 /* Kill the intermediate vuid */
881 invalidate_vuid(sconn, vuid);
883 SAFE_FREE(kerb_mech);
884 return;
886 #endif
887 /* Can't blunder into NTLMSSP auth if we have
888 * a krb5 ticket. */
890 if (kerb_mech) {
891 /* Kill the intermediate vuid */
892 invalidate_vuid(sconn, vuid);
893 DEBUG(3,("reply_spnego_auth: network "
894 "misconfiguration, client sent us a "
895 "krb5 ticket and kerberos security "
896 "not enabled\n"));
897 reply_nterror(req, nt_status_squash(
898 NT_STATUS_LOGON_FAILURE));
899 SAFE_FREE(kerb_mech);
903 /* If we get here it wasn't a negTokenTarg auth packet. */
904 data_blob_free(&secblob);
906 if (!*auth_ntlmssp_state) {
907 status = auth_ntlmssp_start(auth_ntlmssp_state);
908 if (!NT_STATUS_IS_OK(status)) {
909 /* Kill the intermediate vuid */
910 invalidate_vuid(sconn, vuid);
911 reply_nterror(req, nt_status_squash(status));
912 return;
916 status = auth_ntlmssp_update(*auth_ntlmssp_state,
917 auth, &auth_reply);
919 data_blob_free(&auth);
921 /* Don't send the mechid as we've already sent this (RFC4178). */
923 reply_spnego_ntlmssp(req, vuid,
924 auth_ntlmssp_state,
925 &auth_reply, status, NULL, true);
927 data_blob_free(&auth_reply);
929 /* and tell smbd that we have already replied to this packet */
930 return;
933 /****************************************************************************
934 Delete an entry on the list.
935 ****************************************************************************/
937 static void delete_partial_auth(struct smbd_server_connection *sconn,
938 struct pending_auth_data *pad)
940 if (!pad) {
941 return;
943 DLIST_REMOVE(sconn->smb1.pd_list, pad);
944 data_blob_free(&pad->partial_data);
945 SAFE_FREE(pad);
948 /****************************************************************************
949 Search for a partial SPNEGO auth fragment matching an smbpid.
950 ****************************************************************************/
952 static struct pending_auth_data *get_pending_auth_data(
953 struct smbd_server_connection *sconn,
954 uint16_t smbpid)
956 struct pending_auth_data *pad;
958 * NOTE: using the smbpid here is completely wrong...
959 * see [MS-SMB]
960 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
962 for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
963 if (pad->smbpid == smbpid) {
964 break;
967 return pad;
970 /****************************************************************************
971 Check the size of an SPNEGO blob. If we need more return
972 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
973 the blob to be more than 64k.
974 ****************************************************************************/
976 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
977 uint16 smbpid, uint16 vuid,
978 DATA_BLOB *pblob)
980 struct pending_auth_data *pad = NULL;
981 ASN1_DATA *data;
982 size_t needed_len = 0;
984 pad = get_pending_auth_data(sconn, smbpid);
986 /* Ensure we have some data. */
987 if (pblob->length == 0) {
988 /* Caller can cope. */
989 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
990 delete_partial_auth(sconn, pad);
991 return NT_STATUS_OK;
994 /* Were we waiting for more data ? */
995 if (pad) {
996 DATA_BLOB tmp_blob;
997 size_t copy_len = MIN(65536, pblob->length);
999 /* Integer wrap paranoia.... */
1001 if (pad->partial_data.length + copy_len <
1002 pad->partial_data.length ||
1003 pad->partial_data.length + copy_len < copy_len) {
1005 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1006 "pad->partial_data.length = %u, "
1007 "copy_len = %u\n",
1008 (unsigned int)pad->partial_data.length,
1009 (unsigned int)copy_len ));
1011 delete_partial_auth(sconn, pad);
1012 return NT_STATUS_INVALID_PARAMETER;
1015 DEBUG(10,("check_spnego_blob_complete: "
1016 "pad->partial_data.length = %u, "
1017 "pad->needed_len = %u, "
1018 "copy_len = %u, "
1019 "pblob->length = %u,\n",
1020 (unsigned int)pad->partial_data.length,
1021 (unsigned int)pad->needed_len,
1022 (unsigned int)copy_len,
1023 (unsigned int)pblob->length ));
1025 tmp_blob = data_blob(NULL,
1026 pad->partial_data.length + copy_len);
1028 /* Concatenate the two (up to copy_len) bytes. */
1029 memcpy(tmp_blob.data,
1030 pad->partial_data.data,
1031 pad->partial_data.length);
1032 memcpy(tmp_blob.data + pad->partial_data.length,
1033 pblob->data,
1034 copy_len);
1036 /* Replace the partial data. */
1037 data_blob_free(&pad->partial_data);
1038 pad->partial_data = tmp_blob;
1039 ZERO_STRUCT(tmp_blob);
1041 /* Are we done ? */
1042 if (pblob->length >= pad->needed_len) {
1043 /* Yes, replace pblob. */
1044 data_blob_free(pblob);
1045 *pblob = pad->partial_data;
1046 ZERO_STRUCT(pad->partial_data);
1047 delete_partial_auth(sconn, pad);
1048 return NT_STATUS_OK;
1051 /* Still need more data. */
1052 pad->needed_len -= copy_len;
1053 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1056 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
1057 (pblob->data[0] != ASN1_CONTEXT(1))) {
1058 /* Not something we can determine the
1059 * length of.
1061 return NT_STATUS_OK;
1064 /* This is a new SPNEGO sessionsetup - see if
1065 * the data given in this blob is enough.
1068 data = asn1_init(NULL);
1069 if (data == NULL) {
1070 return NT_STATUS_NO_MEMORY;
1073 asn1_load(data, *pblob);
1074 asn1_start_tag(data, pblob->data[0]);
1075 if (data->has_error || data->nesting == NULL) {
1076 asn1_free(data);
1077 /* Let caller catch. */
1078 return NT_STATUS_OK;
1081 /* Integer wrap paranoia.... */
1083 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
1084 data->nesting->taglen + data->nesting->start < data->nesting->start) {
1086 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1087 "data.nesting->taglen = %u, "
1088 "data.nesting->start = %u\n",
1089 (unsigned int)data->nesting->taglen,
1090 (unsigned int)data->nesting->start ));
1092 asn1_free(data);
1093 return NT_STATUS_INVALID_PARAMETER;
1096 /* Total length of the needed asn1 is the tag length
1097 * plus the current offset. */
1099 needed_len = data->nesting->taglen + data->nesting->start;
1100 asn1_free(data);
1102 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1103 "pblob->length = %u\n",
1104 (unsigned int)needed_len,
1105 (unsigned int)pblob->length ));
1107 if (needed_len <= pblob->length) {
1108 /* Nothing to do - blob is complete. */
1109 return NT_STATUS_OK;
1112 /* Refuse the blob if it's bigger than 64k. */
1113 if (needed_len > 65536) {
1114 DEBUG(2,("check_spnego_blob_complete: needed_len "
1115 "too large (%u)\n",
1116 (unsigned int)needed_len ));
1117 return NT_STATUS_INVALID_PARAMETER;
1120 /* We must store this blob until complete. */
1121 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1122 return NT_STATUS_NO_MEMORY;
1124 pad->needed_len = needed_len - pblob->length;
1125 pad->partial_data = data_blob(pblob->data, pblob->length);
1126 if (pad->partial_data.data == NULL) {
1127 SAFE_FREE(pad);
1128 return NT_STATUS_NO_MEMORY;
1130 pad->smbpid = smbpid;
1131 pad->vuid = vuid;
1132 DLIST_ADD(sconn->smb1.pd_list, pad);
1134 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1137 /****************************************************************************
1138 Reply to a session setup command.
1139 conn POINTER CAN BE NULL HERE !
1140 ****************************************************************************/
1142 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1144 const uint8 *p;
1145 DATA_BLOB blob1;
1146 size_t bufrem;
1147 char *tmp;
1148 const char *native_os;
1149 const char *native_lanman;
1150 const char *primary_domain;
1151 const char *p2;
1152 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1153 enum remote_arch_types ra_type = get_remote_arch();
1154 int vuid = req->vuid;
1155 user_struct *vuser = NULL;
1156 NTSTATUS status = NT_STATUS_OK;
1157 uint16 smbpid = req->smbpid;
1158 struct smbd_server_connection *sconn = smbd_server_conn;
1160 DEBUG(3,("Doing spnego session setup\n"));
1162 if (global_client_caps == 0) {
1163 global_client_caps = IVAL(req->vwv+10, 0);
1165 if (!(global_client_caps & CAP_STATUS32)) {
1166 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1171 p = req->buf;
1173 if (data_blob_len == 0) {
1174 /* an invalid request */
1175 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1176 return;
1179 bufrem = smbreq_bufrem(req, p);
1180 /* pull the spnego blob */
1181 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1183 #if 0
1184 file_save("negotiate.dat", blob1.data, blob1.length);
1185 #endif
1187 p2 = (char *)req->buf + data_blob_len;
1189 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1190 STR_TERMINATE);
1191 native_os = tmp ? tmp : "";
1193 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1194 STR_TERMINATE);
1195 native_lanman = tmp ? tmp : "";
1197 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1198 STR_TERMINATE);
1199 primary_domain = tmp ? tmp : "";
1201 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1202 native_os, native_lanman, primary_domain));
1204 if ( ra_type == RA_WIN2K ) {
1205 /* Vista sets neither the OS or lanman strings */
1207 if ( !strlen(native_os) && !strlen(native_lanman) )
1208 set_remote_arch(RA_VISTA);
1210 /* Windows 2003 doesn't set the native lanman string,
1211 but does set primary domain which is a bug I think */
1213 if ( !strlen(native_lanman) ) {
1214 ra_lanman_string( primary_domain );
1215 } else {
1216 ra_lanman_string( native_lanman );
1220 /* Did we get a valid vuid ? */
1221 if (!is_partial_auth_vuid(sconn, vuid)) {
1222 /* No, then try and see if this is an intermediate sessionsetup
1223 * for a large SPNEGO packet. */
1224 struct pending_auth_data *pad;
1225 pad = get_pending_auth_data(sconn, smbpid);
1226 if (pad) {
1227 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1228 "pending vuid %u\n",
1229 (unsigned int)pad->vuid ));
1230 vuid = pad->vuid;
1234 /* Do we have a valid vuid now ? */
1235 if (!is_partial_auth_vuid(sconn, vuid)) {
1236 /* No, start a new authentication setup. */
1237 vuid = register_initial_vuid(sconn);
1238 if (vuid == UID_FIELD_INVALID) {
1239 data_blob_free(&blob1);
1240 reply_nterror(req, nt_status_squash(
1241 NT_STATUS_INVALID_PARAMETER));
1242 return;
1246 vuser = get_partial_auth_user_struct(sconn, vuid);
1247 /* This MUST be valid. */
1248 if (!vuser) {
1249 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1252 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1253 * sessionsetup requests as the Windows limit on the security blob
1254 * field is 4k. Bug #4400. JRA.
1257 status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1258 if (!NT_STATUS_IS_OK(status)) {
1259 if (!NT_STATUS_EQUAL(status,
1260 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1261 /* Real error - kill the intermediate vuid */
1262 invalidate_vuid(sconn, vuid);
1264 data_blob_free(&blob1);
1265 reply_nterror(req, nt_status_squash(status));
1266 return;
1269 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1271 /* its a negTokenTarg packet */
1273 reply_spnego_negotiate(req, vuid, blob1,
1274 &vuser->auth_ntlmssp_state);
1275 data_blob_free(&blob1);
1276 return;
1279 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1281 /* its a auth packet */
1283 reply_spnego_auth(req, vuid, blob1,
1284 &vuser->auth_ntlmssp_state);
1285 data_blob_free(&blob1);
1286 return;
1289 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1290 DATA_BLOB chal;
1292 if (!vuser->auth_ntlmssp_state) {
1293 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1294 if (!NT_STATUS_IS_OK(status)) {
1295 /* Kill the intermediate vuid */
1296 invalidate_vuid(sconn, vuid);
1297 data_blob_free(&blob1);
1298 reply_nterror(req, nt_status_squash(status));
1299 return;
1303 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1304 blob1, &chal);
1306 data_blob_free(&blob1);
1308 reply_spnego_ntlmssp(req, vuid,
1309 &vuser->auth_ntlmssp_state,
1310 &chal, status, OID_NTLMSSP, false);
1311 data_blob_free(&chal);
1312 return;
1315 /* what sort of packet is this? */
1316 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1318 data_blob_free(&blob1);
1320 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1323 /****************************************************************************
1324 On new VC == 0, shutdown *all* old connections and users.
1325 It seems that only NT4.x does this. At W2K and above (XP etc.).
1326 a new session setup with VC==0 is ignored.
1327 ****************************************************************************/
1329 static int shutdown_other_smbds(struct db_record *rec,
1330 const struct connections_key *key,
1331 const struct connections_data *crec,
1332 void *private_data)
1334 const char *ip = (const char *)private_data;
1336 if (!process_exists(crec->pid)) {
1337 return 0;
1340 if (procid_is_me(&crec->pid)) {
1341 return 0;
1344 if (strcmp(ip, crec->addr) != 0) {
1345 return 0;
1348 DEBUG(0,("shutdown_other_smbds: shutting down pid %u "
1349 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid), ip));
1351 messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1352 &data_blob_null);
1353 return 0;
1356 static void setup_new_vc_session(void)
1358 char addr[INET6_ADDRSTRLEN];
1360 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1361 "compatible we would close all old resources.\n"));
1362 #if 0
1363 conn_close_all();
1364 invalidate_all_vuids();
1365 #endif
1366 if (lp_reset_on_zero_vc()) {
1367 connections_forall(shutdown_other_smbds,
1368 CONST_DISCARD(void *,
1369 client_addr(get_client_fd(),addr,sizeof(addr))));
1373 /****************************************************************************
1374 Reply to a session setup command.
1375 ****************************************************************************/
1377 void reply_sesssetup_and_X(struct smb_request *req)
1379 int sess_vuid;
1380 int smb_bufsize;
1381 DATA_BLOB lm_resp;
1382 DATA_BLOB nt_resp;
1383 DATA_BLOB plaintext_password;
1384 char *tmp;
1385 const char *user;
1386 fstring sub_user; /* Sainitised username for substituion */
1387 const char *domain;
1388 const char *native_os;
1389 const char *native_lanman;
1390 const char *primary_domain;
1391 auth_usersupplied_info *user_info = NULL;
1392 auth_serversupplied_info *server_info = NULL;
1393 uint16 smb_flag2 = req->flags2;
1395 NTSTATUS nt_status;
1396 struct smbd_server_connection *sconn = smbd_server_conn;
1398 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1400 START_PROFILE(SMBsesssetupX);
1402 ZERO_STRUCT(lm_resp);
1403 ZERO_STRUCT(nt_resp);
1404 ZERO_STRUCT(plaintext_password);
1406 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1408 /* a SPNEGO session setup has 12 command words, whereas a normal
1409 NT1 session setup has 13. See the cifs spec. */
1410 if (req->wct == 12 &&
1411 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1413 if (!sconn->smb1.negprot.spnego) {
1414 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1415 "at SPNEGO session setup when it was not "
1416 "negotiated.\n"));
1417 reply_nterror(req, nt_status_squash(
1418 NT_STATUS_LOGON_FAILURE));
1419 END_PROFILE(SMBsesssetupX);
1420 return;
1423 if (SVAL(req->vwv+4, 0) == 0) {
1424 setup_new_vc_session();
1427 reply_sesssetup_and_X_spnego(req);
1428 END_PROFILE(SMBsesssetupX);
1429 return;
1432 smb_bufsize = SVAL(req->vwv+2, 0);
1434 if (get_Protocol() < PROTOCOL_NT1) {
1435 uint16 passlen1 = SVAL(req->vwv+7, 0);
1437 /* Never do NT status codes with protocols before NT1 as we
1438 * don't get client caps. */
1439 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1441 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1442 reply_nterror(req, nt_status_squash(
1443 NT_STATUS_INVALID_PARAMETER));
1444 END_PROFILE(SMBsesssetupX);
1445 return;
1448 if (doencrypt) {
1449 lm_resp = data_blob(req->buf, passlen1);
1450 } else {
1451 plaintext_password = data_blob(req->buf, passlen1+1);
1452 /* Ensure null termination */
1453 plaintext_password.data[passlen1] = 0;
1456 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1457 req->buf + passlen1, STR_TERMINATE);
1458 user = tmp ? tmp : "";
1460 domain = "";
1462 } else {
1463 uint16 passlen1 = SVAL(req->vwv+7, 0);
1464 uint16 passlen2 = SVAL(req->vwv+8, 0);
1465 enum remote_arch_types ra_type = get_remote_arch();
1466 const uint8_t *p = req->buf;
1467 const uint8_t *save_p = req->buf;
1468 uint16 byte_count;
1471 if(global_client_caps == 0) {
1472 global_client_caps = IVAL(req->vwv+11, 0);
1474 if (!(global_client_caps & CAP_STATUS32)) {
1475 remove_from_common_flags2(
1476 FLAGS2_32_BIT_ERROR_CODES);
1479 /* client_caps is used as final determination if
1480 * client is NT or Win95. This is needed to return
1481 * the correct error codes in some circumstances.
1484 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1485 ra_type == RA_WIN95) {
1486 if(!(global_client_caps & (CAP_NT_SMBS|
1487 CAP_STATUS32))) {
1488 set_remote_arch( RA_WIN95);
1493 if (!doencrypt) {
1494 /* both Win95 and WinNT stuff up the password
1495 * lengths for non-encrypting systems. Uggh.
1497 if passlen1==24 its a win95 system, and its setting
1498 the password length incorrectly. Luckily it still
1499 works with the default code because Win95 will null
1500 terminate the password anyway
1502 if passlen1>0 and passlen2>0 then maybe its a NT box
1503 and its setting passlen2 to some random value which
1504 really stuffs things up. we need to fix that one. */
1506 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1507 passlen2 != 1) {
1508 passlen2 = 0;
1512 /* check for nasty tricks */
1513 if (passlen1 > MAX_PASS_LEN
1514 || passlen1 > smbreq_bufrem(req, p)) {
1515 reply_nterror(req, nt_status_squash(
1516 NT_STATUS_INVALID_PARAMETER));
1517 END_PROFILE(SMBsesssetupX);
1518 return;
1521 if (passlen2 > MAX_PASS_LEN
1522 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1523 reply_nterror(req, nt_status_squash(
1524 NT_STATUS_INVALID_PARAMETER));
1525 END_PROFILE(SMBsesssetupX);
1526 return;
1529 /* Save the lanman2 password and the NT md4 password. */
1531 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1532 doencrypt = False;
1535 if (doencrypt) {
1536 lm_resp = data_blob(p, passlen1);
1537 nt_resp = data_blob(p+passlen1, passlen2);
1538 } else if (lp_security() != SEC_SHARE) {
1540 * In share level we should ignore any passwords, so
1541 * only read them if we're not.
1543 char *pass = NULL;
1544 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1546 if (unic && (passlen2 == 0) && passlen1) {
1547 /* Only a ascii plaintext password was sent. */
1548 (void)srvstr_pull_talloc(talloc_tos(),
1549 req->inbuf,
1550 req->flags2,
1551 &pass,
1552 req->buf,
1553 passlen1,
1554 STR_TERMINATE|STR_ASCII);
1555 } else {
1556 (void)srvstr_pull_talloc(talloc_tos(),
1557 req->inbuf,
1558 req->flags2,
1559 &pass,
1560 req->buf,
1561 unic ? passlen2 : passlen1,
1562 STR_TERMINATE);
1564 if (!pass) {
1565 reply_nterror(req, nt_status_squash(
1566 NT_STATUS_INVALID_PARAMETER));
1567 END_PROFILE(SMBsesssetupX);
1568 return;
1570 plaintext_password = data_blob(pass, strlen(pass)+1);
1573 p += passlen1 + passlen2;
1575 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1576 STR_TERMINATE);
1577 user = tmp ? tmp : "";
1579 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1580 STR_TERMINATE);
1581 domain = tmp ? tmp : "";
1583 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1584 STR_TERMINATE);
1585 native_os = tmp ? tmp : "";
1587 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1588 STR_TERMINATE);
1589 native_lanman = tmp ? tmp : "";
1591 /* not documented or decoded by Ethereal but there is one more
1592 * string in the extra bytes which is the same as the
1593 * PrimaryDomain when using extended security. Windows NT 4
1594 * and 2003 use this string to store the native lanman string.
1595 * Windows 9x does not include a string here at all so we have
1596 * to check if we have any extra bytes left */
1598 byte_count = SVAL(req->vwv+13, 0);
1599 if ( PTR_DIFF(p, save_p) < byte_count) {
1600 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1601 STR_TERMINATE);
1602 primary_domain = tmp ? tmp : "";
1603 } else {
1604 primary_domain = talloc_strdup(talloc_tos(), "null");
1607 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1608 "PrimaryDomain=[%s]\n",
1609 domain, native_os, native_lanman, primary_domain));
1611 if ( ra_type == RA_WIN2K ) {
1612 if ( strlen(native_lanman) == 0 )
1613 ra_lanman_string( primary_domain );
1614 else
1615 ra_lanman_string( native_lanman );
1620 if (SVAL(req->vwv+4, 0) == 0) {
1621 setup_new_vc_session();
1624 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1625 domain, user, get_remote_machine_name()));
1627 if (*user) {
1628 if (sconn->smb1.negprot.spnego) {
1630 /* This has to be here, because this is a perfectly
1631 * valid behaviour for guest logons :-( */
1633 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1634 "at 'normal' session setup after "
1635 "negotiating spnego.\n"));
1636 reply_nterror(req, nt_status_squash(
1637 NT_STATUS_LOGON_FAILURE));
1638 END_PROFILE(SMBsesssetupX);
1639 return;
1641 fstrcpy(sub_user, user);
1642 } else {
1643 fstrcpy(sub_user, lp_guestaccount());
1646 sub_set_smb_name(sub_user);
1648 reload_services(True);
1650 if (lp_security() == SEC_SHARE) {
1651 /* In share level we should ignore any passwords */
1653 data_blob_free(&lm_resp);
1654 data_blob_free(&nt_resp);
1655 data_blob_clear_free(&plaintext_password);
1657 map_username(sconn, sub_user);
1658 add_session_user(sconn, sub_user);
1659 add_session_workgroup(sconn, domain);
1660 /* Then force it to null for the benfit of the code below */
1661 user = "";
1664 if (!*user) {
1666 nt_status = check_guest_password(&server_info);
1668 } else if (doencrypt) {
1669 struct auth_context *negprot_auth_context = NULL;
1670 negprot_auth_context = sconn->smb1.negprot.auth_context;
1671 if (!negprot_auth_context) {
1672 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1673 "session setup without negprot denied!\n"));
1674 reply_nterror(req, nt_status_squash(
1675 NT_STATUS_LOGON_FAILURE));
1676 END_PROFILE(SMBsesssetupX);
1677 return;
1679 nt_status = make_user_info_for_reply_enc(&user_info, user,
1680 domain,
1681 lm_resp, nt_resp);
1682 if (NT_STATUS_IS_OK(nt_status)) {
1683 nt_status = negprot_auth_context->check_ntlm_password(
1684 negprot_auth_context,
1685 user_info,
1686 &server_info);
1688 } else {
1689 struct auth_context *plaintext_auth_context = NULL;
1691 nt_status = make_auth_context_subsystem(
1692 &plaintext_auth_context);
1694 if (NT_STATUS_IS_OK(nt_status)) {
1695 uint8_t chal[8];
1697 plaintext_auth_context->get_ntlm_challenge(
1698 plaintext_auth_context, chal);
1700 if (!make_user_info_for_reply(&user_info,
1701 user, domain, chal,
1702 plaintext_password)) {
1703 nt_status = NT_STATUS_NO_MEMORY;
1706 if (NT_STATUS_IS_OK(nt_status)) {
1707 nt_status = plaintext_auth_context->check_ntlm_password(
1708 plaintext_auth_context,
1709 user_info,
1710 &server_info);
1712 (plaintext_auth_context->free)(
1713 &plaintext_auth_context);
1718 free_user_info(&user_info);
1720 if (!NT_STATUS_IS_OK(nt_status)) {
1721 nt_status = do_map_to_guest(nt_status, &server_info,
1722 user, domain);
1725 if (!NT_STATUS_IS_OK(nt_status)) {
1726 data_blob_free(&nt_resp);
1727 data_blob_free(&lm_resp);
1728 data_blob_clear_free(&plaintext_password);
1729 reply_nterror(req, nt_status_squash(nt_status));
1730 END_PROFILE(SMBsesssetupX);
1731 return;
1734 /* Ensure we can't possible take a code path leading to a
1735 * null defref. */
1736 if (!server_info) {
1737 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1738 END_PROFILE(SMBsesssetupX);
1739 return;
1742 if (!server_info->ptok) {
1743 nt_status = create_local_token(server_info);
1745 if (!NT_STATUS_IS_OK(nt_status)) {
1746 DEBUG(10, ("create_local_token failed: %s\n",
1747 nt_errstr(nt_status)));
1748 data_blob_free(&nt_resp);
1749 data_blob_free(&lm_resp);
1750 data_blob_clear_free(&plaintext_password);
1751 reply_nterror(req, nt_status_squash(nt_status));
1752 END_PROFILE(SMBsesssetupX);
1753 return;
1757 data_blob_clear_free(&plaintext_password);
1759 /* it's ok - setup a reply */
1760 reply_outbuf(req, 3, 0);
1761 if (get_Protocol() >= PROTOCOL_NT1) {
1762 push_signature(&req->outbuf);
1763 /* perhaps grab OS version here?? */
1766 if (server_info->guest) {
1767 SSVAL(req->outbuf,smb_vwv2,1);
1770 /* register the name and uid as being validated, so further connections
1771 to a uid can get through without a password, on the same VC */
1773 if (lp_security() == SEC_SHARE) {
1774 sess_vuid = UID_FIELD_INVALID;
1775 TALLOC_FREE(server_info);
1776 } else {
1777 /* Ignore the initial vuid. */
1778 sess_vuid = register_initial_vuid(sconn);
1779 if (sess_vuid == UID_FIELD_INVALID) {
1780 data_blob_free(&nt_resp);
1781 data_blob_free(&lm_resp);
1782 reply_nterror(req, nt_status_squash(
1783 NT_STATUS_LOGON_FAILURE));
1784 END_PROFILE(SMBsesssetupX);
1785 return;
1787 /* register_existing_vuid keeps the server info */
1788 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1789 server_info,
1790 nt_resp.data ? nt_resp : lm_resp,
1791 sub_user);
1792 if (sess_vuid == UID_FIELD_INVALID) {
1793 data_blob_free(&nt_resp);
1794 data_blob_free(&lm_resp);
1795 reply_nterror(req, nt_status_squash(
1796 NT_STATUS_LOGON_FAILURE));
1797 END_PROFILE(SMBsesssetupX);
1798 return;
1801 /* current_user_info is changed on new vuid */
1802 reload_services( True );
1805 data_blob_free(&nt_resp);
1806 data_blob_free(&lm_resp);
1808 SSVAL(req->outbuf,smb_uid,sess_vuid);
1809 SSVAL(req->inbuf,smb_uid,sess_vuid);
1810 req->vuid = sess_vuid;
1812 if (!sconn->smb1.sessions.done_sesssetup) {
1813 sconn->smb1.sessions.max_send =
1814 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1816 sconn->smb1.sessions.done_sesssetup = true;
1818 END_PROFILE(SMBsesssetupX);
1819 chain_reply(req);
1820 return;