talloc: setup the new 'tc' before TC_UNDEFINE_GROW_CHUNK() _talloc_realloc()
[Samba.git] / source3 / smbd / sesssetup.c
blobcfbffc0af09961a186c547b79a9837d8a0c99d0d
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 "../lib/tsocket/tsocket.h"
27 #include "smbd/smbd.h"
28 #include "smbd/globals.h"
29 #include "../libcli/auth/spnego.h"
30 #include "../libcli/auth/ntlmssp.h"
31 #include "ntlmssp_wrap.h"
32 #include "../librpc/gen_ndr/krb5pac.h"
33 #include "libads/kerberos_proto.h"
34 #include "../lib/util/asn1.h"
35 #include "auth.h"
36 #include "messages.h"
37 #include "smbprofile.h"
39 /* For split krb5 SPNEGO blobs. */
40 struct pending_auth_data {
41 struct pending_auth_data *prev, *next;
42 uint16 vuid; /* Tag for this entry. */
43 uint16 smbpid; /* Alternate tag for this entry. */
44 size_t needed_len;
45 DATA_BLOB partial_data;
49 on a logon error possibly map the error to success if "map to guest"
50 is set approriately
52 NTSTATUS do_map_to_guest(NTSTATUS status,
53 struct auth_serversupplied_info **server_info,
54 const char *user, const char *domain)
56 user = user ? user : "";
57 domain = domain ? domain : "";
59 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
60 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
61 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
62 DEBUG(3,("No such user %s [%s] - using guest account\n",
63 user, domain));
64 status = make_server_info_guest(NULL, server_info);
68 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
69 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
70 DEBUG(3,("Registered username %s for guest access\n",
71 user));
72 status = make_server_info_guest(NULL, server_info);
76 return status;
79 /****************************************************************************
80 Add the standard 'Samba' signature to the end of the session setup.
81 ****************************************************************************/
83 static int push_signature(uint8 **outbuf)
85 char *lanman;
86 int result, tmp;
88 result = 0;
90 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
92 if (tmp == -1) return -1;
93 result += tmp;
95 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
96 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
97 SAFE_FREE(lanman);
99 else {
100 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
103 if (tmp == -1) return -1;
104 result += tmp;
106 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
108 if (tmp == -1) return -1;
109 result += tmp;
111 return result;
114 /****************************************************************************
115 Send a security blob via a session setup reply.
116 ****************************************************************************/
118 static void reply_sesssetup_blob(struct smb_request *req,
119 DATA_BLOB blob,
120 NTSTATUS nt_status)
122 if (!NT_STATUS_IS_OK(nt_status) &&
123 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
124 reply_nterror(req, nt_status_squash(nt_status));
125 return;
128 nt_status = nt_status_squash(nt_status);
129 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
130 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
131 SSVAL(req->outbuf, smb_vwv3, blob.length);
133 if ((message_push_blob(&req->outbuf, blob) == -1)
134 || (push_signature(&req->outbuf) == -1)) {
135 reply_nterror(req, NT_STATUS_NO_MEMORY);
139 /****************************************************************************
140 Do a 'guest' logon, getting back the
141 ****************************************************************************/
143 static NTSTATUS check_guest_password(struct auth_serversupplied_info **server_info)
145 struct auth_context *auth_context;
146 struct auth_usersupplied_info *user_info = NULL;
148 NTSTATUS nt_status;
149 static unsigned char chal[8] = { 0, };
151 DEBUG(3,("Got anonymous request\n"));
153 nt_status = make_auth_context_fixed(talloc_tos(), &auth_context, chal);
154 if (!NT_STATUS_IS_OK(nt_status)) {
155 return nt_status;
158 if (!make_user_info_guest(&user_info)) {
159 TALLOC_FREE(auth_context);
160 return NT_STATUS_NO_MEMORY;
163 nt_status = auth_context->check_ntlm_password(auth_context,
164 user_info,
165 server_info);
166 TALLOC_FREE(auth_context);
167 free_user_info(&user_info);
168 return nt_status;
172 #ifdef HAVE_KRB5
174 #if 0
175 /* Experiment that failed. See "only happens with a KDC" comment below. */
176 /****************************************************************************
177 Cerate a clock skew error blob for a Windows client.
178 ****************************************************************************/
180 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
182 krb5_context context = NULL;
183 krb5_error_code kerr = 0;
184 krb5_data reply;
185 krb5_principal host_princ = NULL;
186 char *host_princ_s = NULL;
187 bool ret = False;
189 *pblob_out = data_blob_null;
191 initialize_krb5_error_table();
192 kerr = krb5_init_context(&context);
193 if (kerr) {
194 return False;
196 /* Create server principal. */
197 asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
198 if (!host_princ_s) {
199 goto out;
201 strlower_m(host_princ_s);
203 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
204 if (kerr) {
205 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
206 "for name %s: Error %s\n",
207 host_princ_s, error_message(kerr) ));
208 goto out;
211 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
212 host_princ, &reply);
213 if (kerr) {
214 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
215 "failed: Error %s\n",
216 error_message(kerr) ));
217 goto out;
220 *pblob_out = data_blob(reply.data, reply.length);
221 kerberos_free_data_contents(context,&reply);
222 ret = True;
224 out:
226 if (host_princ_s) {
227 SAFE_FREE(host_princ_s);
229 if (host_princ) {
230 krb5_free_principal(context, host_princ);
232 krb5_free_context(context);
233 return ret;
235 #endif
237 /****************************************************************************
238 Reply to a session setup spnego negotiate packet for kerberos.
239 ****************************************************************************/
241 static void reply_spnego_kerberos(struct smb_request *req,
242 DATA_BLOB *secblob,
243 const char *mechOID,
244 uint16 vuid,
245 bool *p_invalidate_vuid)
247 TALLOC_CTX *mem_ctx;
248 DATA_BLOB ticket;
249 struct passwd *pw;
250 int sess_vuid = req->vuid;
251 NTSTATUS ret = NT_STATUS_OK;
252 DATA_BLOB ap_rep, ap_rep_wrapped, response;
253 struct auth_serversupplied_info *server_info = NULL;
254 DATA_BLOB session_key = data_blob_null;
255 uint8 tok_id[2];
256 DATA_BLOB nullblob = data_blob_null;
257 bool map_domainuser_to_guest = False;
258 bool username_was_mapped;
259 struct PAC_LOGON_INFO *logon_info = NULL;
260 struct smbd_server_connection *sconn = req->sconn;
261 char *principal;
262 char *user;
263 char *domain;
264 char *real_username;
266 ZERO_STRUCT(ticket);
267 ZERO_STRUCT(ap_rep);
268 ZERO_STRUCT(ap_rep_wrapped);
269 ZERO_STRUCT(response);
271 /* Normally we will always invalidate the intermediate vuid. */
272 *p_invalidate_vuid = True;
274 mem_ctx = talloc_init("reply_spnego_kerberos");
275 if (mem_ctx == NULL) {
276 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
277 return;
280 if (!spnego_parse_krb5_wrap(mem_ctx, *secblob, &ticket, tok_id)) {
281 talloc_destroy(mem_ctx);
282 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
283 return;
286 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
287 &principal, &logon_info, &ap_rep,
288 &session_key, True);
290 data_blob_free(&ticket);
292 if (!NT_STATUS_IS_OK(ret)) {
293 #if 0
294 /* Experiment that failed.
295 * See "only happens with a KDC" comment below. */
297 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
300 * Windows in this case returns
301 * NT_STATUS_MORE_PROCESSING_REQUIRED
302 * with a negTokenTarg blob containing an krb5_error
303 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
304 * The client then fixes its clock and continues rather
305 * than giving an error. JRA.
306 * -- Looks like this only happens with a KDC. JRA.
309 bool ok = make_krb5_skew_error(&ap_rep);
310 if (!ok) {
311 talloc_destroy(mem_ctx);
312 return ERROR_NT(nt_status_squash(
313 NT_STATUS_LOGON_FAILURE));
315 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
316 TOK_ID_KRB_ERROR);
317 response = spnego_gen_auth_response(&ap_rep_wrapped,
318 ret, OID_KERBEROS5_OLD);
319 reply_sesssetup_blob(conn, inbuf, outbuf, response,
320 NT_STATUS_MORE_PROCESSING_REQUIRED);
323 * In this one case we don't invalidate the
324 * intermediate vuid as we're expecting the client
325 * to re-use it for the next sessionsetupX packet. JRA.
328 *p_invalidate_vuid = False;
330 data_blob_free(&ap_rep);
331 data_blob_free(&ap_rep_wrapped);
332 data_blob_free(&response);
333 talloc_destroy(mem_ctx);
334 return -1; /* already replied */
336 #else
337 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
338 ret = NT_STATUS_LOGON_FAILURE;
340 #endif
341 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
342 nt_errstr(ret)));
343 talloc_destroy(mem_ctx);
344 reply_nterror(req, nt_status_squash(ret));
345 return;
348 ret = get_user_from_kerberos_info(talloc_tos(),
349 sconn->client_id.name,
350 principal, logon_info,
351 &username_was_mapped,
352 &map_domainuser_to_guest,
353 &user, &domain,
354 &real_username, &pw);
355 if (!NT_STATUS_IS_OK(ret)) {
356 data_blob_free(&ap_rep);
357 data_blob_free(&session_key);
358 talloc_destroy(mem_ctx);
359 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
360 return;
363 /* save the PAC data if we have it */
364 if (logon_info) {
365 netsamlogon_cache_store(user, &logon_info->info3);
368 /* setup the string used by %U */
369 sub_set_smb_name(real_username);
371 /* reload services so that the new %U is taken into account */
372 reload_services(sconn->msg_ctx, sconn->sock, True);
374 ret = make_server_info_krb5(mem_ctx,
375 user, domain, real_username, pw,
376 logon_info, map_domainuser_to_guest,
377 &server_info);
378 if (!NT_STATUS_IS_OK(ret)) {
379 DEBUG(1, ("make_server_info_krb5 failed!\n"));
380 data_blob_free(&ap_rep);
381 data_blob_free(&session_key);
382 TALLOC_FREE(mem_ctx);
383 reply_nterror(req, nt_status_squash(ret));
384 return;
387 server_info->nss_token |= username_was_mapped;
389 /* we need to build the token for the user. make_server_info_guest()
390 already does this */
392 if ( !server_info->security_token ) {
393 ret = create_local_token( server_info );
394 if ( !NT_STATUS_IS_OK(ret) ) {
395 DEBUG(10,("failed to create local token: %s\n",
396 nt_errstr(ret)));
397 data_blob_free(&ap_rep);
398 data_blob_free(&session_key);
399 TALLOC_FREE( mem_ctx );
400 TALLOC_FREE( server_info );
401 reply_nterror(req, nt_status_squash(ret));
402 return;
406 if (!is_partial_auth_vuid(sconn, sess_vuid)) {
407 sess_vuid = register_initial_vuid(sconn);
410 data_blob_free(&server_info->user_session_key);
411 /* Set the kerberos-derived session key onto the server_info */
412 server_info->user_session_key = session_key;
413 talloc_steal(server_info, session_key.data);
415 session_key = data_blob_null;
417 /* register_existing_vuid keeps the server info */
418 /* register_existing_vuid takes ownership of session_key on success,
419 * no need to free after this on success. A better interface would copy
420 * it.... */
422 sess_vuid = register_existing_vuid(sconn, sess_vuid,
423 server_info, nullblob, user);
425 reply_outbuf(req, 4, 0);
426 SSVAL(req->outbuf,smb_uid,sess_vuid);
428 if (sess_vuid == UID_FIELD_INVALID ) {
429 ret = NT_STATUS_LOGON_FAILURE;
430 } else {
431 /* current_user_info is changed on new vuid */
432 reload_services(sconn->msg_ctx, sconn->sock, True);
434 SSVAL(req->outbuf, smb_vwv3, 0);
436 if (server_info->guest) {
437 SSVAL(req->outbuf,smb_vwv2,1);
440 SSVAL(req->outbuf, smb_uid, sess_vuid);
442 /* Successful logon. Keep this vuid. */
443 *p_invalidate_vuid = False;
446 /* wrap that up in a nice GSS-API wrapping */
447 if (NT_STATUS_IS_OK(ret)) {
448 ap_rep_wrapped = spnego_gen_krb5_wrap(talloc_tos(), ap_rep,
449 TOK_ID_KRB_AP_REP);
450 } else {
451 ap_rep_wrapped = data_blob_null;
453 response = spnego_gen_auth_response(talloc_tos(), &ap_rep_wrapped, ret,
454 mechOID);
455 reply_sesssetup_blob(req, response, ret);
457 data_blob_free(&ap_rep);
458 data_blob_free(&ap_rep_wrapped);
459 data_blob_free(&response);
460 TALLOC_FREE(mem_ctx);
463 #endif
465 /****************************************************************************
466 Send a session setup reply, wrapped in SPNEGO.
467 Get vuid and check first.
468 End the NTLMSSP exchange context if we are OK/complete fail
469 This should be split into two functions, one to handle each
470 leg of the NTLM auth steps.
471 ***************************************************************************/
473 static void reply_spnego_ntlmssp(struct smb_request *req,
474 uint16 vuid,
475 struct auth_ntlmssp_state **auth_ntlmssp_state,
476 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
477 const char *OID,
478 bool wrap)
480 bool do_invalidate = true;
481 DATA_BLOB response;
482 struct auth_serversupplied_info *session_info = NULL;
483 struct smbd_server_connection *sconn = req->sconn;
485 if (NT_STATUS_IS_OK(nt_status)) {
486 nt_status = auth_ntlmssp_steal_session_info(talloc_tos(),
487 (*auth_ntlmssp_state), &session_info);
488 } else {
489 /* Note that this session_info won't have a session
490 * key. But for map to guest, that's exactly the right
491 * thing - we can't reasonably guess the key the
492 * client wants, as the password was wrong */
493 nt_status = do_map_to_guest(nt_status,
494 &session_info,
495 auth_ntlmssp_get_username(*auth_ntlmssp_state),
496 auth_ntlmssp_get_domain(*auth_ntlmssp_state));
499 reply_outbuf(req, 4, 0);
501 SSVAL(req->outbuf, smb_uid, vuid);
503 if (NT_STATUS_IS_OK(nt_status)) {
504 DATA_BLOB nullblob = data_blob_null;
506 if (!is_partial_auth_vuid(sconn, vuid)) {
507 nt_status = NT_STATUS_LOGON_FAILURE;
508 goto out;
511 /* register_existing_vuid keeps the server info */
512 if (register_existing_vuid(sconn, vuid,
513 session_info, nullblob,
514 auth_ntlmssp_get_username(*auth_ntlmssp_state)) !=
515 vuid) {
516 /* The problem is, *auth_ntlmssp_state points
517 * into the vuser this will have
518 * talloc_free()'ed in
519 * register_existing_vuid() */
520 do_invalidate = false;
521 nt_status = NT_STATUS_LOGON_FAILURE;
522 goto out;
525 /* current_user_info is changed on new vuid */
526 reload_services(sconn->msg_ctx, sconn->sock, True);
528 SSVAL(req->outbuf, smb_vwv3, 0);
530 if (session_info->guest) {
531 SSVAL(req->outbuf,smb_vwv2,1);
535 out:
537 if (wrap) {
538 response = spnego_gen_auth_response(talloc_tos(),
539 ntlmssp_blob,
540 nt_status, OID);
541 } else {
542 response = *ntlmssp_blob;
545 reply_sesssetup_blob(req, response, nt_status);
546 if (wrap) {
547 data_blob_free(&response);
550 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
551 and the other end, that we are not finished yet. */
553 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
554 /* NB. This is *NOT* an error case. JRA */
555 if (do_invalidate) {
556 TALLOC_FREE(*auth_ntlmssp_state);
557 if (!NT_STATUS_IS_OK(nt_status)) {
558 /* Kill the intermediate vuid */
559 invalidate_vuid(sconn, vuid);
565 /****************************************************************************
566 Is this a krb5 mechanism ?
567 ****************************************************************************/
569 NTSTATUS parse_spnego_mechanisms(TALLOC_CTX *ctx,
570 DATA_BLOB blob_in,
571 DATA_BLOB *pblob_out,
572 char **kerb_mechOID)
574 char *OIDs[ASN1_MAX_OIDS];
575 int i;
576 NTSTATUS ret = NT_STATUS_OK;
578 *kerb_mechOID = NULL;
580 /* parse out the OIDs and the first sec blob */
581 if (!spnego_parse_negTokenInit(ctx, blob_in, OIDs, NULL, pblob_out) ||
582 (OIDs[0] == NULL)) {
583 return NT_STATUS_LOGON_FAILURE;
586 /* only look at the first OID for determining the mechToken --
587 according to RFC2478, we should choose the one we want
588 and renegotiate, but i smell a client bug here..
590 Problem observed when connecting to a member (samba box)
591 of an AD domain as a user in a Samba domain. Samba member
592 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
593 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
594 NTLMSSP mechtoken. --jerry */
596 #ifdef HAVE_KRB5
597 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
598 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
599 *kerb_mechOID = talloc_strdup(ctx, OIDs[0]);
600 if (*kerb_mechOID == NULL) {
601 ret = NT_STATUS_NO_MEMORY;
604 #endif
606 for (i=0;OIDs[i];i++) {
607 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
608 talloc_free(OIDs[i]);
610 return ret;
613 /****************************************************************************
614 Fall back from krb5 to NTLMSSP.
615 ****************************************************************************/
617 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
618 uint16 vuid)
620 DATA_BLOB response;
622 reply_outbuf(req, 4, 0);
623 SSVAL(req->outbuf,smb_uid,vuid);
625 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
626 "but set to downgrade to NTLMSSP\n"));
628 response = spnego_gen_auth_response(talloc_tos(), NULL,
629 NT_STATUS_MORE_PROCESSING_REQUIRED,
630 OID_NTLMSSP);
631 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
632 data_blob_free(&response);
635 /****************************************************************************
636 Reply to a session setup spnego negotiate packet.
637 ****************************************************************************/
639 static void reply_spnego_negotiate(struct smb_request *req,
640 uint16 vuid,
641 DATA_BLOB blob1,
642 struct auth_ntlmssp_state **auth_ntlmssp_state)
644 DATA_BLOB secblob;
645 DATA_BLOB chal;
646 char *kerb_mech = NULL;
647 NTSTATUS status;
648 struct smbd_server_connection *sconn = req->sconn;
650 status = parse_spnego_mechanisms(talloc_tos(),
651 blob1, &secblob, &kerb_mech);
652 if (!NT_STATUS_IS_OK(status)) {
653 /* Kill the intermediate vuid */
654 invalidate_vuid(sconn, vuid);
655 reply_nterror(req, nt_status_squash(status));
656 return;
659 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
660 (unsigned long)secblob.length));
662 #ifdef HAVE_KRB5
663 if (kerb_mech && ((lp_security()==SEC_ADS) ||
664 USE_KERBEROS_KEYTAB) ) {
665 bool destroy_vuid = True;
666 reply_spnego_kerberos(req, &secblob, kerb_mech,
667 vuid, &destroy_vuid);
668 data_blob_free(&secblob);
669 if (destroy_vuid) {
670 /* Kill the intermediate vuid */
671 invalidate_vuid(sconn, vuid);
673 TALLOC_FREE(kerb_mech);
674 return;
676 #endif
678 TALLOC_FREE(*auth_ntlmssp_state);
680 if (kerb_mech) {
681 data_blob_free(&secblob);
682 /* The mechtoken is a krb5 ticket, but
683 * we need to fall back to NTLM. */
684 reply_spnego_downgrade_to_ntlmssp(req, vuid);
685 TALLOC_FREE(kerb_mech);
686 return;
689 status = auth_ntlmssp_start(auth_ntlmssp_state);
690 if (!NT_STATUS_IS_OK(status)) {
691 /* Kill the intermediate vuid */
692 invalidate_vuid(sconn, vuid);
693 reply_nterror(req, nt_status_squash(status));
694 return;
697 status = auth_ntlmssp_update(*auth_ntlmssp_state,
698 secblob, &chal);
700 data_blob_free(&secblob);
702 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
703 &chal, status, OID_NTLMSSP, true);
705 data_blob_free(&chal);
707 /* already replied */
708 return;
711 /****************************************************************************
712 Reply to a session setup spnego auth packet.
713 ****************************************************************************/
715 static void reply_spnego_auth(struct smb_request *req,
716 uint16 vuid,
717 DATA_BLOB blob1,
718 struct auth_ntlmssp_state **auth_ntlmssp_state)
720 DATA_BLOB auth = data_blob_null;
721 DATA_BLOB auth_reply = data_blob_null;
722 DATA_BLOB secblob = data_blob_null;
723 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
724 struct smbd_server_connection *sconn = req->sconn;
726 if (!spnego_parse_auth(talloc_tos(), blob1, &auth)) {
727 #if 0
728 file_save("auth.dat", blob1.data, blob1.length);
729 #endif
730 /* Kill the intermediate vuid */
731 invalidate_vuid(sconn, vuid);
733 reply_nterror(req, nt_status_squash(
734 NT_STATUS_LOGON_FAILURE));
735 return;
738 if (auth.data[0] == ASN1_APPLICATION(0)) {
739 /* Might be a second negTokenTarg packet */
740 char *kerb_mech = NULL;
742 status = parse_spnego_mechanisms(talloc_tos(),
743 auth, &secblob, &kerb_mech);
745 if (!NT_STATUS_IS_OK(status)) {
746 /* Kill the intermediate vuid */
747 invalidate_vuid(sconn, vuid);
748 reply_nterror(req, nt_status_squash(status));
749 return;
752 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
753 (unsigned long)secblob.length));
754 #ifdef HAVE_KRB5
755 if (kerb_mech && ((lp_security()==SEC_ADS) ||
756 USE_KERBEROS_KEYTAB)) {
757 bool destroy_vuid = True;
758 reply_spnego_kerberos(req, &secblob, kerb_mech,
759 vuid, &destroy_vuid);
760 data_blob_free(&secblob);
761 data_blob_free(&auth);
762 if (destroy_vuid) {
763 /* Kill the intermediate vuid */
764 invalidate_vuid(sconn, vuid);
766 TALLOC_FREE(kerb_mech);
767 return;
769 #endif
770 /* Can't blunder into NTLMSSP auth if we have
771 * a krb5 ticket. */
773 if (kerb_mech) {
774 /* Kill the intermediate vuid */
775 invalidate_vuid(sconn, vuid);
776 DEBUG(3,("reply_spnego_auth: network "
777 "misconfiguration, client sent us a "
778 "krb5 ticket and kerberos security "
779 "not enabled\n"));
780 reply_nterror(req, nt_status_squash(
781 NT_STATUS_LOGON_FAILURE));
782 TALLOC_FREE(kerb_mech);
786 /* If we get here it wasn't a negTokenTarg auth packet. */
787 data_blob_free(&secblob);
789 if (!*auth_ntlmssp_state) {
790 status = auth_ntlmssp_start(auth_ntlmssp_state);
791 if (!NT_STATUS_IS_OK(status)) {
792 /* Kill the intermediate vuid */
793 invalidate_vuid(sconn, vuid);
794 reply_nterror(req, nt_status_squash(status));
795 return;
799 status = auth_ntlmssp_update(*auth_ntlmssp_state,
800 auth, &auth_reply);
802 data_blob_free(&auth);
804 /* Don't send the mechid as we've already sent this (RFC4178). */
806 reply_spnego_ntlmssp(req, vuid,
807 auth_ntlmssp_state,
808 &auth_reply, status, NULL, true);
810 data_blob_free(&auth_reply);
812 /* and tell smbd that we have already replied to this packet */
813 return;
816 /****************************************************************************
817 Delete an entry on the list.
818 ****************************************************************************/
820 static void delete_partial_auth(struct smbd_server_connection *sconn,
821 struct pending_auth_data *pad)
823 if (!pad) {
824 return;
826 DLIST_REMOVE(sconn->smb1.pd_list, pad);
827 data_blob_free(&pad->partial_data);
828 SAFE_FREE(pad);
831 /****************************************************************************
832 Search for a partial SPNEGO auth fragment matching an smbpid.
833 ****************************************************************************/
835 static struct pending_auth_data *get_pending_auth_data(
836 struct smbd_server_connection *sconn,
837 uint16_t smbpid)
839 struct pending_auth_data *pad;
841 * NOTE: using the smbpid here is completely wrong...
842 * see [MS-SMB]
843 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
845 for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
846 if (pad->smbpid == smbpid) {
847 break;
850 return pad;
853 /****************************************************************************
854 Check the size of an SPNEGO blob. If we need more return
855 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
856 the blob to be more than 64k.
857 ****************************************************************************/
859 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
860 uint16 smbpid, uint16 vuid,
861 DATA_BLOB *pblob)
863 struct pending_auth_data *pad = NULL;
864 ASN1_DATA *data;
865 size_t needed_len = 0;
867 pad = get_pending_auth_data(sconn, smbpid);
869 /* Ensure we have some data. */
870 if (pblob->length == 0) {
871 /* Caller can cope. */
872 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
873 delete_partial_auth(sconn, pad);
874 return NT_STATUS_OK;
877 /* Were we waiting for more data ? */
878 if (pad) {
879 DATA_BLOB tmp_blob;
880 size_t copy_len = MIN(65536, pblob->length);
882 /* Integer wrap paranoia.... */
884 if (pad->partial_data.length + copy_len <
885 pad->partial_data.length ||
886 pad->partial_data.length + copy_len < copy_len) {
888 DEBUG(2,("check_spnego_blob_complete: integer wrap "
889 "pad->partial_data.length = %u, "
890 "copy_len = %u\n",
891 (unsigned int)pad->partial_data.length,
892 (unsigned int)copy_len ));
894 delete_partial_auth(sconn, pad);
895 return NT_STATUS_INVALID_PARAMETER;
898 DEBUG(10,("check_spnego_blob_complete: "
899 "pad->partial_data.length = %u, "
900 "pad->needed_len = %u, "
901 "copy_len = %u, "
902 "pblob->length = %u,\n",
903 (unsigned int)pad->partial_data.length,
904 (unsigned int)pad->needed_len,
905 (unsigned int)copy_len,
906 (unsigned int)pblob->length ));
908 tmp_blob = data_blob(NULL,
909 pad->partial_data.length + copy_len);
911 /* Concatenate the two (up to copy_len) bytes. */
912 memcpy(tmp_blob.data,
913 pad->partial_data.data,
914 pad->partial_data.length);
915 memcpy(tmp_blob.data + pad->partial_data.length,
916 pblob->data,
917 copy_len);
919 /* Replace the partial data. */
920 data_blob_free(&pad->partial_data);
921 pad->partial_data = tmp_blob;
922 ZERO_STRUCT(tmp_blob);
924 /* Are we done ? */
925 if (pblob->length >= pad->needed_len) {
926 /* Yes, replace pblob. */
927 data_blob_free(pblob);
928 *pblob = pad->partial_data;
929 ZERO_STRUCT(pad->partial_data);
930 delete_partial_auth(sconn, pad);
931 return NT_STATUS_OK;
934 /* Still need more data. */
935 pad->needed_len -= copy_len;
936 return NT_STATUS_MORE_PROCESSING_REQUIRED;
939 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
940 (pblob->data[0] != ASN1_CONTEXT(1))) {
941 /* Not something we can determine the
942 * length of.
944 return NT_STATUS_OK;
947 /* This is a new SPNEGO sessionsetup - see if
948 * the data given in this blob is enough.
951 data = asn1_init(NULL);
952 if (data == NULL) {
953 return NT_STATUS_NO_MEMORY;
956 asn1_load(data, *pblob);
957 asn1_start_tag(data, pblob->data[0]);
958 if (data->has_error || data->nesting == NULL) {
959 asn1_free(data);
960 /* Let caller catch. */
961 return NT_STATUS_OK;
964 /* Integer wrap paranoia.... */
966 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
967 data->nesting->taglen + data->nesting->start < data->nesting->start) {
969 DEBUG(2,("check_spnego_blob_complete: integer wrap "
970 "data.nesting->taglen = %u, "
971 "data.nesting->start = %u\n",
972 (unsigned int)data->nesting->taglen,
973 (unsigned int)data->nesting->start ));
975 asn1_free(data);
976 return NT_STATUS_INVALID_PARAMETER;
979 /* Total length of the needed asn1 is the tag length
980 * plus the current offset. */
982 needed_len = data->nesting->taglen + data->nesting->start;
983 asn1_free(data);
985 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
986 "pblob->length = %u\n",
987 (unsigned int)needed_len,
988 (unsigned int)pblob->length ));
990 if (needed_len <= pblob->length) {
991 /* Nothing to do - blob is complete. */
992 return NT_STATUS_OK;
995 /* Refuse the blob if it's bigger than 64k. */
996 if (needed_len > 65536) {
997 DEBUG(2,("check_spnego_blob_complete: needed_len "
998 "too large (%u)\n",
999 (unsigned int)needed_len ));
1000 return NT_STATUS_INVALID_PARAMETER;
1003 /* We must store this blob until complete. */
1004 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1005 return NT_STATUS_NO_MEMORY;
1007 pad->needed_len = needed_len - pblob->length;
1008 pad->partial_data = data_blob(pblob->data, pblob->length);
1009 if (pad->partial_data.data == NULL) {
1010 SAFE_FREE(pad);
1011 return NT_STATUS_NO_MEMORY;
1013 pad->smbpid = smbpid;
1014 pad->vuid = vuid;
1015 DLIST_ADD(sconn->smb1.pd_list, pad);
1017 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1020 /****************************************************************************
1021 Reply to a session setup command.
1022 conn POINTER CAN BE NULL HERE !
1023 ****************************************************************************/
1025 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1027 const uint8 *p;
1028 DATA_BLOB blob1;
1029 size_t bufrem;
1030 char *tmp;
1031 const char *native_os;
1032 const char *native_lanman;
1033 const char *primary_domain;
1034 const char *p2;
1035 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1036 enum remote_arch_types ra_type = get_remote_arch();
1037 int vuid = req->vuid;
1038 user_struct *vuser = NULL;
1039 NTSTATUS status = NT_STATUS_OK;
1040 uint16 smbpid = req->smbpid;
1041 struct smbd_server_connection *sconn = req->sconn;
1043 DEBUG(3,("Doing spnego session setup\n"));
1045 if (global_client_caps == 0) {
1046 global_client_caps = IVAL(req->vwv+10, 0);
1048 if (!(global_client_caps & CAP_STATUS32)) {
1049 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1054 p = req->buf;
1056 if (data_blob_len == 0) {
1057 /* an invalid request */
1058 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1059 return;
1062 bufrem = smbreq_bufrem(req, p);
1063 /* pull the spnego blob */
1064 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1066 #if 0
1067 file_save("negotiate.dat", blob1.data, blob1.length);
1068 #endif
1070 p2 = (char *)req->buf + blob1.length;
1072 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1073 STR_TERMINATE);
1074 native_os = tmp ? tmp : "";
1076 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1077 STR_TERMINATE);
1078 native_lanman = tmp ? tmp : "";
1080 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1081 STR_TERMINATE);
1082 primary_domain = tmp ? tmp : "";
1084 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1085 native_os, native_lanman, primary_domain));
1087 if ( ra_type == RA_WIN2K ) {
1088 /* Vista sets neither the OS or lanman strings */
1090 if ( !strlen(native_os) && !strlen(native_lanman) )
1091 set_remote_arch(RA_VISTA);
1093 /* Windows 2003 doesn't set the native lanman string,
1094 but does set primary domain which is a bug I think */
1096 if ( !strlen(native_lanman) ) {
1097 ra_lanman_string( primary_domain );
1098 } else {
1099 ra_lanman_string( native_lanman );
1101 } else if ( ra_type == RA_VISTA ) {
1102 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
1103 set_remote_arch(RA_OSX);
1107 /* Did we get a valid vuid ? */
1108 if (!is_partial_auth_vuid(sconn, vuid)) {
1109 /* No, then try and see if this is an intermediate sessionsetup
1110 * for a large SPNEGO packet. */
1111 struct pending_auth_data *pad;
1112 pad = get_pending_auth_data(sconn, smbpid);
1113 if (pad) {
1114 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1115 "pending vuid %u\n",
1116 (unsigned int)pad->vuid ));
1117 vuid = pad->vuid;
1121 /* Do we have a valid vuid now ? */
1122 if (!is_partial_auth_vuid(sconn, vuid)) {
1123 /* No, start a new authentication setup. */
1124 vuid = register_initial_vuid(sconn);
1125 if (vuid == UID_FIELD_INVALID) {
1126 data_blob_free(&blob1);
1127 reply_nterror(req, nt_status_squash(
1128 NT_STATUS_INVALID_PARAMETER));
1129 return;
1133 vuser = get_partial_auth_user_struct(sconn, vuid);
1134 /* This MUST be valid. */
1135 if (!vuser) {
1136 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1139 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1140 * sessionsetup requests as the Windows limit on the security blob
1141 * field is 4k. Bug #4400. JRA.
1144 status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1145 if (!NT_STATUS_IS_OK(status)) {
1146 if (!NT_STATUS_EQUAL(status,
1147 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1148 /* Real error - kill the intermediate vuid */
1149 invalidate_vuid(sconn, vuid);
1151 data_blob_free(&blob1);
1152 reply_nterror(req, nt_status_squash(status));
1153 return;
1156 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1158 /* its a negTokenTarg packet */
1160 reply_spnego_negotiate(req, vuid, blob1,
1161 &vuser->auth_ntlmssp_state);
1162 data_blob_free(&blob1);
1163 return;
1166 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1168 /* its a auth packet */
1170 reply_spnego_auth(req, vuid, blob1,
1171 &vuser->auth_ntlmssp_state);
1172 data_blob_free(&blob1);
1173 return;
1176 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1177 DATA_BLOB chal;
1179 if (!vuser->auth_ntlmssp_state) {
1180 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1181 if (!NT_STATUS_IS_OK(status)) {
1182 /* Kill the intermediate vuid */
1183 invalidate_vuid(sconn, vuid);
1184 data_blob_free(&blob1);
1185 reply_nterror(req, nt_status_squash(status));
1186 return;
1190 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1191 blob1, &chal);
1193 data_blob_free(&blob1);
1195 reply_spnego_ntlmssp(req, vuid,
1196 &vuser->auth_ntlmssp_state,
1197 &chal, status, OID_NTLMSSP, false);
1198 data_blob_free(&chal);
1199 return;
1202 /* what sort of packet is this? */
1203 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1205 data_blob_free(&blob1);
1207 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1210 /****************************************************************************
1211 On new VC == 0, shutdown *all* old connections and users.
1212 It seems that only NT4.x does this. At W2K and above (XP etc.).
1213 a new session setup with VC==0 is ignored.
1214 ****************************************************************************/
1216 struct shutdown_state {
1217 const char *ip;
1218 struct messaging_context *msg_ctx;
1221 static int shutdown_other_smbds(const struct connections_key *key,
1222 const struct connections_data *crec,
1223 void *private_data)
1225 struct shutdown_state *state = (struct shutdown_state *)private_data;
1227 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
1228 procid_str(talloc_tos(), &crec->pid), crec->addr));
1230 if (!process_exists(crec->pid)) {
1231 DEBUG(10, ("process does not exist\n"));
1232 return 0;
1235 if (procid_is_me(&crec->pid)) {
1236 DEBUG(10, ("It's me\n"));
1237 return 0;
1240 if (strcmp(state->ip, crec->addr) != 0) {
1241 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
1242 return 0;
1245 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
1246 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
1247 state->ip));
1249 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
1250 &data_blob_null);
1251 return 0;
1254 static void setup_new_vc_session(struct smbd_server_connection *sconn)
1256 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1257 "compatible we would close all old resources.\n"));
1258 #if 0
1259 conn_close_all();
1260 invalidate_all_vuids();
1261 #endif
1262 if (lp_reset_on_zero_vc()) {
1263 char *addr;
1264 struct shutdown_state state;
1266 addr = tsocket_address_inet_addr_string(
1267 sconn->remote_address, talloc_tos());
1268 if (addr == NULL) {
1269 return;
1271 state.ip = addr;
1272 state.msg_ctx = sconn->msg_ctx;
1273 connections_forall_read(shutdown_other_smbds, &state);
1274 TALLOC_FREE(addr);
1278 /****************************************************************************
1279 Reply to a session setup command.
1280 ****************************************************************************/
1282 void reply_sesssetup_and_X(struct smb_request *req)
1284 int sess_vuid;
1285 int smb_bufsize;
1286 DATA_BLOB lm_resp;
1287 DATA_BLOB nt_resp;
1288 DATA_BLOB plaintext_password;
1289 char *tmp;
1290 const char *user;
1291 fstring sub_user; /* Sanitised username for substituion */
1292 const char *domain;
1293 const char *native_os;
1294 const char *native_lanman;
1295 const char *primary_domain;
1296 struct auth_usersupplied_info *user_info = NULL;
1297 struct auth_serversupplied_info *server_info = NULL;
1298 uint16 smb_flag2 = req->flags2;
1300 NTSTATUS nt_status;
1301 struct smbd_server_connection *sconn = req->sconn;
1303 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1305 START_PROFILE(SMBsesssetupX);
1307 ZERO_STRUCT(lm_resp);
1308 ZERO_STRUCT(nt_resp);
1309 ZERO_STRUCT(plaintext_password);
1311 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1313 /* a SPNEGO session setup has 12 command words, whereas a normal
1314 NT1 session setup has 13. See the cifs spec. */
1315 if (req->wct == 12 &&
1316 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1318 if (!sconn->smb1.negprot.spnego) {
1319 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1320 "at SPNEGO session setup when it was not "
1321 "negotiated.\n"));
1322 reply_nterror(req, nt_status_squash(
1323 NT_STATUS_LOGON_FAILURE));
1324 END_PROFILE(SMBsesssetupX);
1325 return;
1328 if (SVAL(req->vwv+4, 0) == 0) {
1329 setup_new_vc_session(req->sconn);
1332 reply_sesssetup_and_X_spnego(req);
1333 END_PROFILE(SMBsesssetupX);
1334 return;
1337 smb_bufsize = SVAL(req->vwv+2, 0);
1339 if (get_Protocol() < PROTOCOL_NT1) {
1340 uint16 passlen1 = SVAL(req->vwv+7, 0);
1342 /* Never do NT status codes with protocols before NT1 as we
1343 * don't get client caps. */
1344 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1346 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1347 reply_nterror(req, nt_status_squash(
1348 NT_STATUS_INVALID_PARAMETER));
1349 END_PROFILE(SMBsesssetupX);
1350 return;
1353 if (doencrypt) {
1354 lm_resp = data_blob(req->buf, passlen1);
1355 } else {
1356 plaintext_password = data_blob(req->buf, passlen1+1);
1357 /* Ensure null termination */
1358 plaintext_password.data[passlen1] = 0;
1361 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1362 req->buf + passlen1, STR_TERMINATE);
1363 user = tmp ? tmp : "";
1365 domain = "";
1367 } else {
1368 uint16 passlen1 = SVAL(req->vwv+7, 0);
1369 uint16 passlen2 = SVAL(req->vwv+8, 0);
1370 enum remote_arch_types ra_type = get_remote_arch();
1371 const uint8_t *p = req->buf;
1372 const uint8_t *save_p = req->buf;
1373 uint16 byte_count;
1376 if(global_client_caps == 0) {
1377 global_client_caps = IVAL(req->vwv+11, 0);
1379 if (!(global_client_caps & CAP_STATUS32)) {
1380 remove_from_common_flags2(
1381 FLAGS2_32_BIT_ERROR_CODES);
1384 /* client_caps is used as final determination if
1385 * client is NT or Win95. This is needed to return
1386 * the correct error codes in some circumstances.
1389 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1390 ra_type == RA_WIN95) {
1391 if(!(global_client_caps & (CAP_NT_SMBS|
1392 CAP_STATUS32))) {
1393 set_remote_arch( RA_WIN95);
1398 if (!doencrypt) {
1399 /* both Win95 and WinNT stuff up the password
1400 * lengths for non-encrypting systems. Uggh.
1402 if passlen1==24 its a win95 system, and its setting
1403 the password length incorrectly. Luckily it still
1404 works with the default code because Win95 will null
1405 terminate the password anyway
1407 if passlen1>0 and passlen2>0 then maybe its a NT box
1408 and its setting passlen2 to some random value which
1409 really stuffs things up. we need to fix that one. */
1411 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1412 passlen2 != 1) {
1413 passlen2 = 0;
1417 /* check for nasty tricks */
1418 if (passlen1 > MAX_PASS_LEN
1419 || passlen1 > smbreq_bufrem(req, p)) {
1420 reply_nterror(req, nt_status_squash(
1421 NT_STATUS_INVALID_PARAMETER));
1422 END_PROFILE(SMBsesssetupX);
1423 return;
1426 if (passlen2 > MAX_PASS_LEN
1427 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1428 reply_nterror(req, nt_status_squash(
1429 NT_STATUS_INVALID_PARAMETER));
1430 END_PROFILE(SMBsesssetupX);
1431 return;
1434 /* Save the lanman2 password and the NT md4 password. */
1436 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1437 doencrypt = False;
1440 if (doencrypt) {
1441 lm_resp = data_blob(p, passlen1);
1442 nt_resp = data_blob(p+passlen1, passlen2);
1443 } else if (lp_security() != SEC_SHARE) {
1445 * In share level we should ignore any passwords, so
1446 * only read them if we're not.
1448 char *pass = NULL;
1449 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1451 if (unic && (passlen2 == 0) && passlen1) {
1452 /* Only a ascii plaintext password was sent. */
1453 (void)srvstr_pull_talloc(talloc_tos(),
1454 req->inbuf,
1455 req->flags2,
1456 &pass,
1457 req->buf,
1458 passlen1,
1459 STR_TERMINATE|STR_ASCII);
1460 } else {
1461 (void)srvstr_pull_talloc(talloc_tos(),
1462 req->inbuf,
1463 req->flags2,
1464 &pass,
1465 req->buf,
1466 unic ? passlen2 : passlen1,
1467 STR_TERMINATE);
1469 if (!pass) {
1470 reply_nterror(req, nt_status_squash(
1471 NT_STATUS_INVALID_PARAMETER));
1472 END_PROFILE(SMBsesssetupX);
1473 return;
1475 plaintext_password = data_blob(pass, strlen(pass)+1);
1478 p += passlen1 + passlen2;
1480 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1481 STR_TERMINATE);
1482 user = tmp ? tmp : "";
1484 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1485 STR_TERMINATE);
1486 domain = tmp ? tmp : "";
1488 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1489 STR_TERMINATE);
1490 native_os = tmp ? tmp : "";
1492 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1493 STR_TERMINATE);
1494 native_lanman = tmp ? tmp : "";
1496 /* not documented or decoded by Ethereal but there is one more
1497 * string in the extra bytes which is the same as the
1498 * PrimaryDomain when using extended security. Windows NT 4
1499 * and 2003 use this string to store the native lanman string.
1500 * Windows 9x does not include a string here at all so we have
1501 * to check if we have any extra bytes left */
1503 byte_count = SVAL(req->vwv+13, 0);
1504 if ( PTR_DIFF(p, save_p) < byte_count) {
1505 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1506 STR_TERMINATE);
1507 primary_domain = tmp ? tmp : "";
1508 } else {
1509 primary_domain = talloc_strdup(talloc_tos(), "null");
1512 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1513 "PrimaryDomain=[%s]\n",
1514 domain, native_os, native_lanman, primary_domain));
1516 if ( ra_type == RA_WIN2K ) {
1517 if ( strlen(native_lanman) == 0 )
1518 ra_lanman_string( primary_domain );
1519 else
1520 ra_lanman_string( native_lanman );
1525 if (SVAL(req->vwv+4, 0) == 0) {
1526 setup_new_vc_session(req->sconn);
1529 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1530 domain, user, get_remote_machine_name()));
1532 if (*user) {
1533 if (sconn->smb1.negprot.spnego) {
1535 /* This has to be here, because this is a perfectly
1536 * valid behaviour for guest logons :-( */
1538 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1539 "at 'normal' session setup after "
1540 "negotiating spnego.\n"));
1541 reply_nterror(req, nt_status_squash(
1542 NT_STATUS_LOGON_FAILURE));
1543 END_PROFILE(SMBsesssetupX);
1544 return;
1546 fstrcpy(sub_user, user);
1547 } else {
1548 fstrcpy(sub_user, lp_guestaccount());
1551 sub_set_smb_name(sub_user);
1553 reload_services(sconn->msg_ctx, sconn->sock, True);
1555 if (lp_security() == SEC_SHARE) {
1556 char *sub_user_mapped = NULL;
1557 /* In share level we should ignore any passwords */
1559 data_blob_free(&lm_resp);
1560 data_blob_free(&nt_resp);
1561 data_blob_clear_free(&plaintext_password);
1563 (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
1564 if (!sub_user_mapped) {
1565 reply_nterror(req, NT_STATUS_NO_MEMORY);
1566 END_PROFILE(SMBsesssetupX);
1567 return;
1569 fstrcpy(sub_user, sub_user_mapped);
1570 add_session_user(sconn, sub_user);
1571 add_session_workgroup(sconn, domain);
1572 /* Then force it to null for the benfit of the code below */
1573 user = "";
1576 if (!*user) {
1578 nt_status = check_guest_password(&server_info);
1580 } else if (doencrypt) {
1581 struct auth_context *negprot_auth_context = NULL;
1582 negprot_auth_context = sconn->smb1.negprot.auth_context;
1583 if (!negprot_auth_context) {
1584 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1585 "session setup without negprot denied!\n"));
1586 reply_nterror(req, nt_status_squash(
1587 NT_STATUS_LOGON_FAILURE));
1588 END_PROFILE(SMBsesssetupX);
1589 return;
1591 nt_status = make_user_info_for_reply_enc(&user_info, user,
1592 domain,
1593 lm_resp, nt_resp);
1594 if (NT_STATUS_IS_OK(nt_status)) {
1595 nt_status = negprot_auth_context->check_ntlm_password(
1596 negprot_auth_context,
1597 user_info,
1598 &server_info);
1600 } else {
1601 struct auth_context *plaintext_auth_context = NULL;
1603 nt_status = make_auth_context_subsystem(
1604 talloc_tos(), &plaintext_auth_context);
1606 if (NT_STATUS_IS_OK(nt_status)) {
1607 uint8_t chal[8];
1609 plaintext_auth_context->get_ntlm_challenge(
1610 plaintext_auth_context, chal);
1612 if (!make_user_info_for_reply(&user_info,
1613 user, domain, chal,
1614 plaintext_password)) {
1615 nt_status = NT_STATUS_NO_MEMORY;
1618 if (NT_STATUS_IS_OK(nt_status)) {
1619 nt_status = plaintext_auth_context->check_ntlm_password(
1620 plaintext_auth_context,
1621 user_info,
1622 &server_info);
1624 TALLOC_FREE(plaintext_auth_context);
1629 free_user_info(&user_info);
1631 if (!NT_STATUS_IS_OK(nt_status)) {
1632 nt_status = do_map_to_guest(nt_status, &server_info,
1633 user, domain);
1636 if (!NT_STATUS_IS_OK(nt_status)) {
1637 data_blob_free(&nt_resp);
1638 data_blob_free(&lm_resp);
1639 data_blob_clear_free(&plaintext_password);
1640 reply_nterror(req, nt_status_squash(nt_status));
1641 END_PROFILE(SMBsesssetupX);
1642 return;
1645 /* Ensure we can't possible take a code path leading to a
1646 * null defref. */
1647 if (!server_info) {
1648 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1649 END_PROFILE(SMBsesssetupX);
1650 return;
1653 if (!server_info->security_token) {
1654 nt_status = create_local_token(server_info);
1656 if (!NT_STATUS_IS_OK(nt_status)) {
1657 DEBUG(10, ("create_local_token failed: %s\n",
1658 nt_errstr(nt_status)));
1659 data_blob_free(&nt_resp);
1660 data_blob_free(&lm_resp);
1661 data_blob_clear_free(&plaintext_password);
1662 reply_nterror(req, nt_status_squash(nt_status));
1663 END_PROFILE(SMBsesssetupX);
1664 return;
1668 data_blob_clear_free(&plaintext_password);
1670 /* it's ok - setup a reply */
1671 reply_outbuf(req, 3, 0);
1672 if (get_Protocol() >= PROTOCOL_NT1) {
1673 push_signature(&req->outbuf);
1674 /* perhaps grab OS version here?? */
1677 if (server_info->guest) {
1678 SSVAL(req->outbuf,smb_vwv2,1);
1681 /* register the name and uid as being validated, so further connections
1682 to a uid can get through without a password, on the same VC */
1684 if (lp_security() == SEC_SHARE) {
1685 sess_vuid = UID_FIELD_INVALID;
1686 TALLOC_FREE(server_info);
1687 } else {
1688 /* Ignore the initial vuid. */
1689 sess_vuid = register_initial_vuid(sconn);
1690 if (sess_vuid == UID_FIELD_INVALID) {
1691 data_blob_free(&nt_resp);
1692 data_blob_free(&lm_resp);
1693 reply_nterror(req, nt_status_squash(
1694 NT_STATUS_LOGON_FAILURE));
1695 END_PROFILE(SMBsesssetupX);
1696 return;
1698 /* register_existing_vuid keeps the server info */
1699 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1700 server_info,
1701 nt_resp.data ? nt_resp : lm_resp,
1702 sub_user);
1703 if (sess_vuid == UID_FIELD_INVALID) {
1704 data_blob_free(&nt_resp);
1705 data_blob_free(&lm_resp);
1706 reply_nterror(req, nt_status_squash(
1707 NT_STATUS_LOGON_FAILURE));
1708 END_PROFILE(SMBsesssetupX);
1709 return;
1712 /* current_user_info is changed on new vuid */
1713 reload_services(sconn->msg_ctx, sconn->sock, True);
1716 data_blob_free(&nt_resp);
1717 data_blob_free(&lm_resp);
1719 SSVAL(req->outbuf,smb_uid,sess_vuid);
1720 SSVAL(req->inbuf,smb_uid,sess_vuid);
1721 req->vuid = sess_vuid;
1723 if (!sconn->smb1.sessions.done_sesssetup) {
1724 sconn->smb1.sessions.max_send =
1725 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1727 sconn->smb1.sessions.done_sesssetup = true;
1729 END_PROFILE(SMBsesssetupX);
1730 chain_reply(req);
1731 return;