s3: Fix Coverity ID 2582: FORWARD_NULL
[Samba.git] / source3 / smbd / sesssetup.c
blobdda4ef296e47e802c56cb6df8edaa9d44d0a1b3b
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", lp_netbios_name(), 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 *session_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_session_info_krb5(mem_ctx,
375 user, domain, real_username, pw,
376 logon_info, map_domainuser_to_guest,
377 username_was_mapped,
378 &session_key,
379 &session_info);
380 data_blob_free(&session_key);
381 if (!NT_STATUS_IS_OK(ret)) {
382 DEBUG(1, ("make_server_info_krb5 failed!\n"));
383 data_blob_free(&ap_rep);
384 TALLOC_FREE(mem_ctx);
385 reply_nterror(req, nt_status_squash(ret));
386 return;
389 if (!is_partial_auth_vuid(sconn, sess_vuid)) {
390 sess_vuid = register_initial_vuid(sconn);
393 /* register_existing_vuid keeps the server info */
394 /* register_existing_vuid takes ownership of session_key on success,
395 * no need to free after this on success. A better interface would copy
396 * it.... */
398 sess_vuid = register_existing_vuid(sconn, sess_vuid,
399 session_info, nullblob, user);
401 reply_outbuf(req, 4, 0);
402 SSVAL(req->outbuf,smb_uid,sess_vuid);
404 if (sess_vuid == UID_FIELD_INVALID ) {
405 ret = NT_STATUS_LOGON_FAILURE;
406 } else {
407 /* current_user_info is changed on new vuid */
408 reload_services(sconn->msg_ctx, sconn->sock, True);
410 SSVAL(req->outbuf, smb_vwv3, 0);
412 if (session_info->guest) {
413 SSVAL(req->outbuf,smb_vwv2,1);
416 SSVAL(req->outbuf, smb_uid, sess_vuid);
418 /* Successful logon. Keep this vuid. */
419 *p_invalidate_vuid = False;
422 /* wrap that up in a nice GSS-API wrapping */
423 if (NT_STATUS_IS_OK(ret)) {
424 ap_rep_wrapped = spnego_gen_krb5_wrap(talloc_tos(), ap_rep,
425 TOK_ID_KRB_AP_REP);
426 } else {
427 ap_rep_wrapped = data_blob_null;
429 response = spnego_gen_auth_response(talloc_tos(), &ap_rep_wrapped, ret,
430 mechOID);
431 reply_sesssetup_blob(req, response, ret);
433 data_blob_free(&ap_rep);
434 data_blob_free(&ap_rep_wrapped);
435 data_blob_free(&response);
436 TALLOC_FREE(mem_ctx);
439 #endif
441 /****************************************************************************
442 Send a session setup reply, wrapped in SPNEGO.
443 Get vuid and check first.
444 End the NTLMSSP exchange context if we are OK/complete fail
445 This should be split into two functions, one to handle each
446 leg of the NTLM auth steps.
447 ***************************************************************************/
449 static void reply_spnego_ntlmssp(struct smb_request *req,
450 uint16 vuid,
451 struct auth_ntlmssp_state **auth_ntlmssp_state,
452 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
453 const char *OID,
454 bool wrap)
456 bool do_invalidate = true;
457 DATA_BLOB response;
458 struct auth_serversupplied_info *session_info = NULL;
459 struct smbd_server_connection *sconn = req->sconn;
461 if (NT_STATUS_IS_OK(nt_status)) {
462 nt_status = auth_ntlmssp_steal_session_info(talloc_tos(),
463 (*auth_ntlmssp_state), &session_info);
464 } else {
465 /* Note that this session_info won't have a session
466 * key. But for map to guest, that's exactly the right
467 * thing - we can't reasonably guess the key the
468 * client wants, as the password was wrong */
469 nt_status = do_map_to_guest(nt_status,
470 &session_info,
471 auth_ntlmssp_get_username(*auth_ntlmssp_state),
472 auth_ntlmssp_get_domain(*auth_ntlmssp_state));
475 reply_outbuf(req, 4, 0);
477 SSVAL(req->outbuf, smb_uid, vuid);
479 if (NT_STATUS_IS_OK(nt_status)) {
480 DATA_BLOB nullblob = data_blob_null;
482 if (!is_partial_auth_vuid(sconn, vuid)) {
483 nt_status = NT_STATUS_LOGON_FAILURE;
484 goto out;
487 /* register_existing_vuid keeps the server info */
488 if (register_existing_vuid(sconn, vuid,
489 session_info, nullblob,
490 auth_ntlmssp_get_username(*auth_ntlmssp_state)) !=
491 vuid) {
492 /* The problem is, *auth_ntlmssp_state points
493 * into the vuser this will have
494 * talloc_free()'ed in
495 * register_existing_vuid() */
496 do_invalidate = false;
497 nt_status = NT_STATUS_LOGON_FAILURE;
498 goto out;
501 /* current_user_info is changed on new vuid */
502 reload_services(sconn->msg_ctx, sconn->sock, True);
504 SSVAL(req->outbuf, smb_vwv3, 0);
506 if (session_info->guest) {
507 SSVAL(req->outbuf,smb_vwv2,1);
511 out:
513 if (wrap) {
514 response = spnego_gen_auth_response(talloc_tos(),
515 ntlmssp_blob,
516 nt_status, OID);
517 } else {
518 response = *ntlmssp_blob;
521 reply_sesssetup_blob(req, response, nt_status);
522 if (wrap) {
523 data_blob_free(&response);
526 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
527 and the other end, that we are not finished yet. */
529 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
530 /* NB. This is *NOT* an error case. JRA */
531 if (do_invalidate) {
532 TALLOC_FREE(*auth_ntlmssp_state);
533 if (!NT_STATUS_IS_OK(nt_status)) {
534 /* Kill the intermediate vuid */
535 invalidate_vuid(sconn, vuid);
541 /****************************************************************************
542 Is this a krb5 mechanism ?
543 ****************************************************************************/
545 NTSTATUS parse_spnego_mechanisms(TALLOC_CTX *ctx,
546 DATA_BLOB blob_in,
547 DATA_BLOB *pblob_out,
548 char **kerb_mechOID)
550 char *OIDs[ASN1_MAX_OIDS];
551 int i;
552 NTSTATUS ret = NT_STATUS_OK;
554 *kerb_mechOID = NULL;
556 /* parse out the OIDs and the first sec blob */
557 if (!spnego_parse_negTokenInit(ctx, blob_in, OIDs, NULL, pblob_out) ||
558 (OIDs[0] == NULL)) {
559 return NT_STATUS_LOGON_FAILURE;
562 /* only look at the first OID for determining the mechToken --
563 according to RFC2478, we should choose the one we want
564 and renegotiate, but i smell a client bug here..
566 Problem observed when connecting to a member (samba box)
567 of an AD domain as a user in a Samba domain. Samba member
568 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
569 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
570 NTLMSSP mechtoken. --jerry */
572 #ifdef HAVE_KRB5
573 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
574 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
575 *kerb_mechOID = talloc_strdup(ctx, OIDs[0]);
576 if (*kerb_mechOID == NULL) {
577 ret = NT_STATUS_NO_MEMORY;
580 #endif
582 for (i=0;OIDs[i];i++) {
583 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
584 talloc_free(OIDs[i]);
586 return ret;
589 /****************************************************************************
590 Fall back from krb5 to NTLMSSP.
591 ****************************************************************************/
593 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
594 uint16 vuid)
596 DATA_BLOB response;
598 reply_outbuf(req, 4, 0);
599 SSVAL(req->outbuf,smb_uid,vuid);
601 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
602 "but set to downgrade to NTLMSSP\n"));
604 response = spnego_gen_auth_response(talloc_tos(), NULL,
605 NT_STATUS_MORE_PROCESSING_REQUIRED,
606 OID_NTLMSSP);
607 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
608 data_blob_free(&response);
611 /****************************************************************************
612 Reply to a session setup spnego negotiate packet.
613 ****************************************************************************/
615 static void reply_spnego_negotiate(struct smb_request *req,
616 uint16 vuid,
617 DATA_BLOB blob1,
618 struct auth_ntlmssp_state **auth_ntlmssp_state)
620 DATA_BLOB secblob;
621 DATA_BLOB chal;
622 char *kerb_mech = NULL;
623 NTSTATUS status;
624 struct smbd_server_connection *sconn = req->sconn;
626 status = parse_spnego_mechanisms(talloc_tos(),
627 blob1, &secblob, &kerb_mech);
628 if (!NT_STATUS_IS_OK(status)) {
629 /* Kill the intermediate vuid */
630 invalidate_vuid(sconn, vuid);
631 reply_nterror(req, nt_status_squash(status));
632 return;
635 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
636 (unsigned long)secblob.length));
638 #ifdef HAVE_KRB5
639 if (kerb_mech && ((lp_security()==SEC_ADS) ||
640 USE_KERBEROS_KEYTAB) ) {
641 bool destroy_vuid = True;
642 reply_spnego_kerberos(req, &secblob, kerb_mech,
643 vuid, &destroy_vuid);
644 data_blob_free(&secblob);
645 if (destroy_vuid) {
646 /* Kill the intermediate vuid */
647 invalidate_vuid(sconn, vuid);
649 TALLOC_FREE(kerb_mech);
650 return;
652 #endif
654 TALLOC_FREE(*auth_ntlmssp_state);
656 if (kerb_mech) {
657 data_blob_free(&secblob);
658 /* The mechtoken is a krb5 ticket, but
659 * we need to fall back to NTLM. */
660 reply_spnego_downgrade_to_ntlmssp(req, vuid);
661 TALLOC_FREE(kerb_mech);
662 return;
665 status = auth_ntlmssp_start(auth_ntlmssp_state);
666 if (!NT_STATUS_IS_OK(status)) {
667 /* Kill the intermediate vuid */
668 invalidate_vuid(sconn, vuid);
669 reply_nterror(req, nt_status_squash(status));
670 return;
673 status = auth_ntlmssp_update(*auth_ntlmssp_state,
674 secblob, &chal);
676 data_blob_free(&secblob);
678 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
679 &chal, status, OID_NTLMSSP, true);
681 data_blob_free(&chal);
683 /* already replied */
684 return;
687 /****************************************************************************
688 Reply to a session setup spnego auth packet.
689 ****************************************************************************/
691 static void reply_spnego_auth(struct smb_request *req,
692 uint16 vuid,
693 DATA_BLOB blob1,
694 struct auth_ntlmssp_state **auth_ntlmssp_state)
696 DATA_BLOB auth = data_blob_null;
697 DATA_BLOB auth_reply = data_blob_null;
698 DATA_BLOB secblob = data_blob_null;
699 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
700 struct smbd_server_connection *sconn = req->sconn;
702 if (!spnego_parse_auth(talloc_tos(), blob1, &auth)) {
703 #if 0
704 file_save("auth.dat", blob1.data, blob1.length);
705 #endif
706 /* Kill the intermediate vuid */
707 invalidate_vuid(sconn, vuid);
709 reply_nterror(req, nt_status_squash(
710 NT_STATUS_LOGON_FAILURE));
711 return;
714 if (auth.data[0] == ASN1_APPLICATION(0)) {
715 /* Might be a second negTokenTarg packet */
716 char *kerb_mech = NULL;
718 status = parse_spnego_mechanisms(talloc_tos(),
719 auth, &secblob, &kerb_mech);
721 if (!NT_STATUS_IS_OK(status)) {
722 /* Kill the intermediate vuid */
723 invalidate_vuid(sconn, vuid);
724 reply_nterror(req, nt_status_squash(status));
725 return;
728 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
729 (unsigned long)secblob.length));
730 #ifdef HAVE_KRB5
731 if (kerb_mech && ((lp_security()==SEC_ADS) ||
732 USE_KERBEROS_KEYTAB)) {
733 bool destroy_vuid = True;
734 reply_spnego_kerberos(req, &secblob, kerb_mech,
735 vuid, &destroy_vuid);
736 data_blob_free(&secblob);
737 data_blob_free(&auth);
738 if (destroy_vuid) {
739 /* Kill the intermediate vuid */
740 invalidate_vuid(sconn, vuid);
742 TALLOC_FREE(kerb_mech);
743 return;
745 #endif
746 /* Can't blunder into NTLMSSP auth if we have
747 * a krb5 ticket. */
749 if (kerb_mech) {
750 /* Kill the intermediate vuid */
751 invalidate_vuid(sconn, vuid);
752 DEBUG(3,("reply_spnego_auth: network "
753 "misconfiguration, client sent us a "
754 "krb5 ticket and kerberos security "
755 "not enabled\n"));
756 reply_nterror(req, nt_status_squash(
757 NT_STATUS_LOGON_FAILURE));
758 TALLOC_FREE(kerb_mech);
762 /* If we get here it wasn't a negTokenTarg auth packet. */
763 data_blob_free(&secblob);
765 if (!*auth_ntlmssp_state) {
766 status = auth_ntlmssp_start(auth_ntlmssp_state);
767 if (!NT_STATUS_IS_OK(status)) {
768 /* Kill the intermediate vuid */
769 invalidate_vuid(sconn, vuid);
770 reply_nterror(req, nt_status_squash(status));
771 return;
775 status = auth_ntlmssp_update(*auth_ntlmssp_state,
776 auth, &auth_reply);
778 data_blob_free(&auth);
780 /* Don't send the mechid as we've already sent this (RFC4178). */
782 reply_spnego_ntlmssp(req, vuid,
783 auth_ntlmssp_state,
784 &auth_reply, status, NULL, true);
786 data_blob_free(&auth_reply);
788 /* and tell smbd that we have already replied to this packet */
789 return;
792 /****************************************************************************
793 Delete an entry on the list.
794 ****************************************************************************/
796 static void delete_partial_auth(struct smbd_server_connection *sconn,
797 struct pending_auth_data *pad)
799 if (!pad) {
800 return;
802 DLIST_REMOVE(sconn->smb1.pd_list, pad);
803 data_blob_free(&pad->partial_data);
804 SAFE_FREE(pad);
807 /****************************************************************************
808 Search for a partial SPNEGO auth fragment matching an smbpid.
809 ****************************************************************************/
811 static struct pending_auth_data *get_pending_auth_data(
812 struct smbd_server_connection *sconn,
813 uint16_t smbpid)
815 struct pending_auth_data *pad;
817 * NOTE: using the smbpid here is completely wrong...
818 * see [MS-SMB]
819 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
821 for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
822 if (pad->smbpid == smbpid) {
823 break;
826 return pad;
829 /****************************************************************************
830 Check the size of an SPNEGO blob. If we need more return
831 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
832 the blob to be more than 64k.
833 ****************************************************************************/
835 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
836 uint16 smbpid, uint16 vuid,
837 DATA_BLOB *pblob)
839 struct pending_auth_data *pad = NULL;
840 ASN1_DATA *data;
841 size_t needed_len = 0;
843 pad = get_pending_auth_data(sconn, smbpid);
845 /* Ensure we have some data. */
846 if (pblob->length == 0) {
847 /* Caller can cope. */
848 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
849 delete_partial_auth(sconn, pad);
850 return NT_STATUS_OK;
853 /* Were we waiting for more data ? */
854 if (pad) {
855 DATA_BLOB tmp_blob;
856 size_t copy_len = MIN(65536, pblob->length);
858 /* Integer wrap paranoia.... */
860 if (pad->partial_data.length + copy_len <
861 pad->partial_data.length ||
862 pad->partial_data.length + copy_len < copy_len) {
864 DEBUG(2,("check_spnego_blob_complete: integer wrap "
865 "pad->partial_data.length = %u, "
866 "copy_len = %u\n",
867 (unsigned int)pad->partial_data.length,
868 (unsigned int)copy_len ));
870 delete_partial_auth(sconn, pad);
871 return NT_STATUS_INVALID_PARAMETER;
874 DEBUG(10,("check_spnego_blob_complete: "
875 "pad->partial_data.length = %u, "
876 "pad->needed_len = %u, "
877 "copy_len = %u, "
878 "pblob->length = %u,\n",
879 (unsigned int)pad->partial_data.length,
880 (unsigned int)pad->needed_len,
881 (unsigned int)copy_len,
882 (unsigned int)pblob->length ));
884 tmp_blob = data_blob(NULL,
885 pad->partial_data.length + copy_len);
887 /* Concatenate the two (up to copy_len) bytes. */
888 memcpy(tmp_blob.data,
889 pad->partial_data.data,
890 pad->partial_data.length);
891 memcpy(tmp_blob.data + pad->partial_data.length,
892 pblob->data,
893 copy_len);
895 /* Replace the partial data. */
896 data_blob_free(&pad->partial_data);
897 pad->partial_data = tmp_blob;
898 ZERO_STRUCT(tmp_blob);
900 /* Are we done ? */
901 if (pblob->length >= pad->needed_len) {
902 /* Yes, replace pblob. */
903 data_blob_free(pblob);
904 *pblob = pad->partial_data;
905 ZERO_STRUCT(pad->partial_data);
906 delete_partial_auth(sconn, pad);
907 return NT_STATUS_OK;
910 /* Still need more data. */
911 pad->needed_len -= copy_len;
912 return NT_STATUS_MORE_PROCESSING_REQUIRED;
915 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
916 (pblob->data[0] != ASN1_CONTEXT(1))) {
917 /* Not something we can determine the
918 * length of.
920 return NT_STATUS_OK;
923 /* This is a new SPNEGO sessionsetup - see if
924 * the data given in this blob is enough.
927 data = asn1_init(NULL);
928 if (data == NULL) {
929 return NT_STATUS_NO_MEMORY;
932 asn1_load(data, *pblob);
933 if (asn1_start_tag(data, pblob->data[0])) {
934 /* asn1_start_tag checks if the given
935 length of the blob is enough to complete
936 the tag. If it returns true we know
937 there is nothing to do - the blob is
938 complete. */
939 asn1_free(data);
940 return NT_STATUS_OK;
943 if (data->nesting == NULL) {
944 /* Incorrect tag, allocation failed,
945 or reading the tag length failed.
946 Let the caller catch. */
947 asn1_free(data);
948 return NT_STATUS_OK;
951 /* Here we know asn1_start_tag() has set data->has_error to true.
952 asn1_tag_remaining() will have failed due to the given blob
953 being too short. We need to work out how short. */
955 /* Integer wrap paranoia.... */
957 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
958 data->nesting->taglen + data->nesting->start < data->nesting->start) {
960 DEBUG(2,("check_spnego_blob_complete: integer wrap "
961 "data.nesting->taglen = %u, "
962 "data.nesting->start = %u\n",
963 (unsigned int)data->nesting->taglen,
964 (unsigned int)data->nesting->start ));
966 asn1_free(data);
967 return NT_STATUS_INVALID_PARAMETER;
970 /* Total length of the needed asn1 is the tag length
971 * plus the current offset. */
973 needed_len = data->nesting->taglen + data->nesting->start;
974 asn1_free(data);
976 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
977 "pblob->length = %u\n",
978 (unsigned int)needed_len,
979 (unsigned int)pblob->length ));
981 if (needed_len <= pblob->length) {
982 /* Nothing to do - blob is complete. */
983 /* THIS SHOULD NOT HAPPEN - asn1_start_tag()
984 above should have caught this !!! */
985 DEBUG(0,("check_spnego_blob_complete: logic "
986 "error (needed_len = %u, "
987 "pblob->length = %u).\n",
988 (unsigned int)needed_len,
989 (unsigned int)pblob->length ));
990 return NT_STATUS_OK;
993 /* Refuse the blob if it's bigger than 64k. */
994 if (needed_len > 65536) {
995 DEBUG(2,("check_spnego_blob_complete: needed_len "
996 "too large (%u)\n",
997 (unsigned int)needed_len ));
998 return NT_STATUS_INVALID_PARAMETER;
1001 /* We must store this blob until complete. */
1002 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1003 return NT_STATUS_NO_MEMORY;
1005 pad->needed_len = needed_len - pblob->length;
1006 pad->partial_data = data_blob(pblob->data, pblob->length);
1007 if (pad->partial_data.data == NULL) {
1008 SAFE_FREE(pad);
1009 return NT_STATUS_NO_MEMORY;
1011 pad->smbpid = smbpid;
1012 pad->vuid = vuid;
1013 DLIST_ADD(sconn->smb1.pd_list, pad);
1015 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1018 /****************************************************************************
1019 Reply to a session setup command.
1020 conn POINTER CAN BE NULL HERE !
1021 ****************************************************************************/
1023 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1025 const uint8 *p;
1026 DATA_BLOB blob1;
1027 size_t bufrem;
1028 char *tmp;
1029 const char *native_os;
1030 const char *native_lanman;
1031 const char *primary_domain;
1032 const char *p2;
1033 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1034 enum remote_arch_types ra_type = get_remote_arch();
1035 int vuid = req->vuid;
1036 user_struct *vuser = NULL;
1037 NTSTATUS status = NT_STATUS_OK;
1038 uint16 smbpid = req->smbpid;
1039 struct smbd_server_connection *sconn = req->sconn;
1041 DEBUG(3,("Doing spnego session setup\n"));
1043 if (global_client_caps == 0) {
1044 global_client_caps = IVAL(req->vwv+10, 0);
1046 if (!(global_client_caps & CAP_STATUS32)) {
1047 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1052 p = req->buf;
1054 if (data_blob_len == 0) {
1055 /* an invalid request */
1056 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1057 return;
1060 bufrem = smbreq_bufrem(req, p);
1061 /* pull the spnego blob */
1062 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1064 #if 0
1065 file_save("negotiate.dat", blob1.data, blob1.length);
1066 #endif
1068 p2 = (const char *)req->buf + blob1.length;
1070 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1071 STR_TERMINATE);
1072 native_os = tmp ? tmp : "";
1074 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1075 STR_TERMINATE);
1076 native_lanman = tmp ? tmp : "";
1078 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1079 STR_TERMINATE);
1080 primary_domain = tmp ? tmp : "";
1082 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1083 native_os, native_lanman, primary_domain));
1085 if ( ra_type == RA_WIN2K ) {
1086 /* Vista sets neither the OS or lanman strings */
1088 if ( !strlen(native_os) && !strlen(native_lanman) )
1089 set_remote_arch(RA_VISTA);
1091 /* Windows 2003 doesn't set the native lanman string,
1092 but does set primary domain which is a bug I think */
1094 if ( !strlen(native_lanman) ) {
1095 ra_lanman_string( primary_domain );
1096 } else {
1097 ra_lanman_string( native_lanman );
1099 } else if ( ra_type == RA_VISTA ) {
1100 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
1101 set_remote_arch(RA_OSX);
1105 /* Did we get a valid vuid ? */
1106 if (!is_partial_auth_vuid(sconn, vuid)) {
1107 /* No, then try and see if this is an intermediate sessionsetup
1108 * for a large SPNEGO packet. */
1109 struct pending_auth_data *pad;
1110 pad = get_pending_auth_data(sconn, smbpid);
1111 if (pad) {
1112 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1113 "pending vuid %u\n",
1114 (unsigned int)pad->vuid ));
1115 vuid = pad->vuid;
1119 /* Do we have a valid vuid now ? */
1120 if (!is_partial_auth_vuid(sconn, vuid)) {
1121 /* No, start a new authentication setup. */
1122 vuid = register_initial_vuid(sconn);
1123 if (vuid == UID_FIELD_INVALID) {
1124 data_blob_free(&blob1);
1125 reply_nterror(req, nt_status_squash(
1126 NT_STATUS_INVALID_PARAMETER));
1127 return;
1131 vuser = get_partial_auth_user_struct(sconn, vuid);
1132 /* This MUST be valid. */
1133 if (!vuser) {
1134 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1137 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1138 * sessionsetup requests as the Windows limit on the security blob
1139 * field is 4k. Bug #4400. JRA.
1142 status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1143 if (!NT_STATUS_IS_OK(status)) {
1144 if (!NT_STATUS_EQUAL(status,
1145 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1146 /* Real error - kill the intermediate vuid */
1147 invalidate_vuid(sconn, vuid);
1149 data_blob_free(&blob1);
1150 reply_nterror(req, nt_status_squash(status));
1151 return;
1154 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1156 /* its a negTokenTarg packet */
1158 reply_spnego_negotiate(req, vuid, blob1,
1159 &vuser->auth_ntlmssp_state);
1160 data_blob_free(&blob1);
1161 return;
1164 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1166 /* its a auth packet */
1168 reply_spnego_auth(req, vuid, blob1,
1169 &vuser->auth_ntlmssp_state);
1170 data_blob_free(&blob1);
1171 return;
1174 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1175 DATA_BLOB chal;
1177 if (!vuser->auth_ntlmssp_state) {
1178 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1179 if (!NT_STATUS_IS_OK(status)) {
1180 /* Kill the intermediate vuid */
1181 invalidate_vuid(sconn, vuid);
1182 data_blob_free(&blob1);
1183 reply_nterror(req, nt_status_squash(status));
1184 return;
1188 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1189 blob1, &chal);
1191 data_blob_free(&blob1);
1193 reply_spnego_ntlmssp(req, vuid,
1194 &vuser->auth_ntlmssp_state,
1195 &chal, status, OID_NTLMSSP, false);
1196 data_blob_free(&chal);
1197 return;
1200 /* what sort of packet is this? */
1201 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1203 data_blob_free(&blob1);
1205 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1208 /****************************************************************************
1209 On new VC == 0, shutdown *all* old connections and users.
1210 It seems that only NT4.x does this. At W2K and above (XP etc.).
1211 a new session setup with VC==0 is ignored.
1212 ****************************************************************************/
1214 struct shutdown_state {
1215 const char *ip;
1216 struct messaging_context *msg_ctx;
1219 static int shutdown_other_smbds(const struct connections_key *key,
1220 const struct connections_data *crec,
1221 void *private_data)
1223 struct shutdown_state *state = (struct shutdown_state *)private_data;
1225 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
1226 server_id_str(talloc_tos(), &crec->pid), crec->addr));
1228 if (!process_exists(crec->pid)) {
1229 DEBUG(10, ("process does not exist\n"));
1230 return 0;
1233 if (procid_is_me(&crec->pid)) {
1234 DEBUG(10, ("It's me\n"));
1235 return 0;
1238 if (strcmp(state->ip, crec->addr) != 0) {
1239 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
1240 return 0;
1243 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
1244 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
1245 state->ip));
1247 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
1248 &data_blob_null);
1249 return 0;
1252 static void setup_new_vc_session(struct smbd_server_connection *sconn)
1254 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1255 "compatible we would close all old resources.\n"));
1256 #if 0
1257 conn_close_all();
1258 invalidate_all_vuids();
1259 #endif
1260 if (lp_reset_on_zero_vc()) {
1261 char *addr;
1262 struct shutdown_state state;
1264 addr = tsocket_address_inet_addr_string(
1265 sconn->remote_address, talloc_tos());
1266 if (addr == NULL) {
1267 return;
1269 state.ip = addr;
1270 state.msg_ctx = sconn->msg_ctx;
1271 connections_forall_read(shutdown_other_smbds, &state);
1272 TALLOC_FREE(addr);
1276 /****************************************************************************
1277 Reply to a session setup command.
1278 ****************************************************************************/
1280 void reply_sesssetup_and_X(struct smb_request *req)
1282 int sess_vuid;
1283 int smb_bufsize;
1284 DATA_BLOB lm_resp;
1285 DATA_BLOB nt_resp;
1286 DATA_BLOB plaintext_password;
1287 char *tmp;
1288 const char *user;
1289 fstring sub_user; /* Sanitised username for substituion */
1290 const char *domain;
1291 const char *native_os;
1292 const char *native_lanman;
1293 const char *primary_domain;
1294 struct auth_usersupplied_info *user_info = NULL;
1295 struct auth_serversupplied_info *server_info = NULL;
1296 struct auth_serversupplied_info *session_info = NULL;
1297 uint16 smb_flag2 = req->flags2;
1299 NTSTATUS nt_status;
1300 struct smbd_server_connection *sconn = req->sconn;
1302 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1304 START_PROFILE(SMBsesssetupX);
1306 ZERO_STRUCT(lm_resp);
1307 ZERO_STRUCT(nt_resp);
1308 ZERO_STRUCT(plaintext_password);
1310 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1312 /* a SPNEGO session setup has 12 command words, whereas a normal
1313 NT1 session setup has 13. See the cifs spec. */
1314 if (req->wct == 12 &&
1315 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1317 if (!sconn->smb1.negprot.spnego) {
1318 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1319 "at SPNEGO session setup when it was not "
1320 "negotiated.\n"));
1321 reply_nterror(req, nt_status_squash(
1322 NT_STATUS_LOGON_FAILURE));
1323 END_PROFILE(SMBsesssetupX);
1324 return;
1327 if (SVAL(req->vwv+4, 0) == 0) {
1328 setup_new_vc_session(req->sconn);
1331 reply_sesssetup_and_X_spnego(req);
1332 END_PROFILE(SMBsesssetupX);
1333 return;
1336 smb_bufsize = SVAL(req->vwv+2, 0);
1338 if (get_Protocol() < PROTOCOL_NT1) {
1339 uint16 passlen1 = SVAL(req->vwv+7, 0);
1341 /* Never do NT status codes with protocols before NT1 as we
1342 * don't get client caps. */
1343 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1345 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1346 reply_nterror(req, nt_status_squash(
1347 NT_STATUS_INVALID_PARAMETER));
1348 END_PROFILE(SMBsesssetupX);
1349 return;
1352 if (doencrypt) {
1353 lm_resp = data_blob(req->buf, passlen1);
1354 } else {
1355 plaintext_password = data_blob(req->buf, passlen1+1);
1356 /* Ensure null termination */
1357 plaintext_password.data[passlen1] = 0;
1360 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1361 req->buf + passlen1, STR_TERMINATE);
1362 user = tmp ? tmp : "";
1364 domain = "";
1366 } else {
1367 uint16 passlen1 = SVAL(req->vwv+7, 0);
1368 uint16 passlen2 = SVAL(req->vwv+8, 0);
1369 enum remote_arch_types ra_type = get_remote_arch();
1370 const uint8_t *p = req->buf;
1371 const uint8_t *save_p = req->buf;
1372 uint16 byte_count;
1375 if(global_client_caps == 0) {
1376 global_client_caps = IVAL(req->vwv+11, 0);
1378 if (!(global_client_caps & CAP_STATUS32)) {
1379 remove_from_common_flags2(
1380 FLAGS2_32_BIT_ERROR_CODES);
1383 /* client_caps is used as final determination if
1384 * client is NT or Win95. This is needed to return
1385 * the correct error codes in some circumstances.
1388 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1389 ra_type == RA_WIN95) {
1390 if(!(global_client_caps & (CAP_NT_SMBS|
1391 CAP_STATUS32))) {
1392 set_remote_arch( RA_WIN95);
1397 if (!doencrypt) {
1398 /* both Win95 and WinNT stuff up the password
1399 * lengths for non-encrypting systems. Uggh.
1401 if passlen1==24 its a win95 system, and its setting
1402 the password length incorrectly. Luckily it still
1403 works with the default code because Win95 will null
1404 terminate the password anyway
1406 if passlen1>0 and passlen2>0 then maybe its a NT box
1407 and its setting passlen2 to some random value which
1408 really stuffs things up. we need to fix that one. */
1410 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1411 passlen2 != 1) {
1412 passlen2 = 0;
1416 /* check for nasty tricks */
1417 if (passlen1 > MAX_PASS_LEN
1418 || passlen1 > smbreq_bufrem(req, p)) {
1419 reply_nterror(req, nt_status_squash(
1420 NT_STATUS_INVALID_PARAMETER));
1421 END_PROFILE(SMBsesssetupX);
1422 return;
1425 if (passlen2 > MAX_PASS_LEN
1426 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1427 reply_nterror(req, nt_status_squash(
1428 NT_STATUS_INVALID_PARAMETER));
1429 END_PROFILE(SMBsesssetupX);
1430 return;
1433 /* Save the lanman2 password and the NT md4 password. */
1435 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1436 doencrypt = False;
1439 if (doencrypt) {
1440 lm_resp = data_blob(p, passlen1);
1441 nt_resp = data_blob(p+passlen1, passlen2);
1442 } else if (lp_security() != SEC_SHARE) {
1444 * In share level we should ignore any passwords, so
1445 * only read them if we're not.
1447 char *pass = NULL;
1448 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1450 if (unic && (passlen2 == 0) && passlen1) {
1451 /* Only a ascii plaintext password was sent. */
1452 (void)srvstr_pull_talloc(talloc_tos(),
1453 req->inbuf,
1454 req->flags2,
1455 &pass,
1456 req->buf,
1457 passlen1,
1458 STR_TERMINATE|STR_ASCII);
1459 } else {
1460 (void)srvstr_pull_talloc(talloc_tos(),
1461 req->inbuf,
1462 req->flags2,
1463 &pass,
1464 req->buf,
1465 unic ? passlen2 : passlen1,
1466 STR_TERMINATE);
1468 if (!pass) {
1469 reply_nterror(req, nt_status_squash(
1470 NT_STATUS_INVALID_PARAMETER));
1471 END_PROFILE(SMBsesssetupX);
1472 return;
1474 plaintext_password = data_blob(pass, strlen(pass)+1);
1477 p += passlen1 + passlen2;
1479 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1480 STR_TERMINATE);
1481 user = tmp ? tmp : "";
1483 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1484 STR_TERMINATE);
1485 domain = tmp ? tmp : "";
1487 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1488 STR_TERMINATE);
1489 native_os = tmp ? tmp : "";
1491 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1492 STR_TERMINATE);
1493 native_lanman = tmp ? tmp : "";
1495 /* not documented or decoded by Ethereal but there is one more
1496 * string in the extra bytes which is the same as the
1497 * PrimaryDomain when using extended security. Windows NT 4
1498 * and 2003 use this string to store the native lanman string.
1499 * Windows 9x does not include a string here at all so we have
1500 * to check if we have any extra bytes left */
1502 byte_count = SVAL(req->vwv+13, 0);
1503 if ( PTR_DIFF(p, save_p) < byte_count) {
1504 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1505 STR_TERMINATE);
1506 primary_domain = tmp ? tmp : "";
1507 } else {
1508 primary_domain = talloc_strdup(talloc_tos(), "null");
1511 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1512 "PrimaryDomain=[%s]\n",
1513 domain, native_os, native_lanman, primary_domain));
1515 if ( ra_type == RA_WIN2K ) {
1516 if ( strlen(native_lanman) == 0 )
1517 ra_lanman_string( primary_domain );
1518 else
1519 ra_lanman_string( native_lanman );
1524 if (SVAL(req->vwv+4, 0) == 0) {
1525 setup_new_vc_session(req->sconn);
1528 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1529 domain, user, get_remote_machine_name()));
1531 if (*user) {
1532 if (sconn->smb1.negprot.spnego) {
1534 /* This has to be here, because this is a perfectly
1535 * valid behaviour for guest logons :-( */
1537 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1538 "at 'normal' session setup after "
1539 "negotiating spnego.\n"));
1540 reply_nterror(req, nt_status_squash(
1541 NT_STATUS_LOGON_FAILURE));
1542 END_PROFILE(SMBsesssetupX);
1543 return;
1545 fstrcpy(sub_user, user);
1546 } else {
1547 fstrcpy(sub_user, lp_guestaccount());
1550 sub_set_smb_name(sub_user);
1552 reload_services(sconn->msg_ctx, sconn->sock, True);
1554 if (lp_security() == SEC_SHARE) {
1555 char *sub_user_mapped = NULL;
1556 /* In share level we should ignore any passwords */
1558 data_blob_free(&lm_resp);
1559 data_blob_free(&nt_resp);
1560 data_blob_clear_free(&plaintext_password);
1562 (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
1563 if (!sub_user_mapped) {
1564 reply_nterror(req, NT_STATUS_NO_MEMORY);
1565 END_PROFILE(SMBsesssetupX);
1566 return;
1568 fstrcpy(sub_user, sub_user_mapped);
1569 add_session_user(sconn, sub_user);
1570 add_session_workgroup(sconn, domain);
1571 /* Then force it to null for the benfit of the code below */
1572 user = "";
1575 if (!*user) {
1577 nt_status = check_guest_password(&server_info);
1579 } else if (doencrypt) {
1580 struct auth_context *negprot_auth_context = NULL;
1581 negprot_auth_context = sconn->smb1.negprot.auth_context;
1582 if (!negprot_auth_context) {
1583 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1584 "session setup without negprot denied!\n"));
1585 reply_nterror(req, nt_status_squash(
1586 NT_STATUS_LOGON_FAILURE));
1587 END_PROFILE(SMBsesssetupX);
1588 return;
1590 nt_status = make_user_info_for_reply_enc(&user_info, user,
1591 domain,
1592 lm_resp, nt_resp);
1593 if (NT_STATUS_IS_OK(nt_status)) {
1594 nt_status = negprot_auth_context->check_ntlm_password(
1595 negprot_auth_context,
1596 user_info,
1597 &server_info);
1599 } else {
1600 struct auth_context *plaintext_auth_context = NULL;
1602 nt_status = make_auth_context_subsystem(
1603 talloc_tos(), &plaintext_auth_context);
1605 if (NT_STATUS_IS_OK(nt_status)) {
1606 uint8_t chal[8];
1608 plaintext_auth_context->get_ntlm_challenge(
1609 plaintext_auth_context, chal);
1611 if (!make_user_info_for_reply(&user_info,
1612 user, domain, chal,
1613 plaintext_password)) {
1614 nt_status = NT_STATUS_NO_MEMORY;
1617 if (NT_STATUS_IS_OK(nt_status)) {
1618 nt_status = plaintext_auth_context->check_ntlm_password(
1619 plaintext_auth_context,
1620 user_info,
1621 &server_info);
1623 TALLOC_FREE(plaintext_auth_context);
1628 free_user_info(&user_info);
1630 if (!NT_STATUS_IS_OK(nt_status)) {
1631 nt_status = do_map_to_guest(nt_status, &server_info,
1632 user, domain);
1635 if (!NT_STATUS_IS_OK(nt_status)) {
1636 data_blob_free(&nt_resp);
1637 data_blob_free(&lm_resp);
1638 data_blob_clear_free(&plaintext_password);
1639 reply_nterror(req, nt_status_squash(nt_status));
1640 END_PROFILE(SMBsesssetupX);
1641 return;
1644 nt_status = create_local_token(req, server_info, NULL, &session_info);
1645 TALLOC_FREE(server_info);
1647 if (!NT_STATUS_IS_OK(nt_status)) {
1648 DEBUG(10, ("create_local_token failed: %s\n",
1649 nt_errstr(nt_status)));
1650 data_blob_free(&nt_resp);
1651 data_blob_free(&lm_resp);
1652 data_blob_clear_free(&plaintext_password);
1653 reply_nterror(req, nt_status_squash(nt_status));
1654 END_PROFILE(SMBsesssetupX);
1655 return;
1658 data_blob_clear_free(&plaintext_password);
1660 /* it's ok - setup a reply */
1661 reply_outbuf(req, 3, 0);
1662 if (get_Protocol() >= PROTOCOL_NT1) {
1663 push_signature(&req->outbuf);
1664 /* perhaps grab OS version here?? */
1667 if (session_info->guest) {
1668 SSVAL(req->outbuf,smb_vwv2,1);
1671 /* register the name and uid as being validated, so further connections
1672 to a uid can get through without a password, on the same VC */
1674 if (lp_security() == SEC_SHARE) {
1675 sess_vuid = UID_FIELD_INVALID;
1676 TALLOC_FREE(session_info);
1677 } else {
1678 /* Ignore the initial vuid. */
1679 sess_vuid = register_initial_vuid(sconn);
1680 if (sess_vuid == UID_FIELD_INVALID) {
1681 data_blob_free(&nt_resp);
1682 data_blob_free(&lm_resp);
1683 reply_nterror(req, nt_status_squash(
1684 NT_STATUS_LOGON_FAILURE));
1685 END_PROFILE(SMBsesssetupX);
1686 return;
1688 /* register_existing_vuid keeps the session_info */
1689 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1690 session_info,
1691 nt_resp.data ? nt_resp : lm_resp,
1692 sub_user);
1693 if (sess_vuid == UID_FIELD_INVALID) {
1694 data_blob_free(&nt_resp);
1695 data_blob_free(&lm_resp);
1696 reply_nterror(req, nt_status_squash(
1697 NT_STATUS_LOGON_FAILURE));
1698 END_PROFILE(SMBsesssetupX);
1699 return;
1702 /* current_user_info is changed on new vuid */
1703 reload_services(sconn->msg_ctx, sconn->sock, True);
1706 data_blob_free(&nt_resp);
1707 data_blob_free(&lm_resp);
1709 SSVAL(req->outbuf,smb_uid,sess_vuid);
1710 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1711 req->vuid = sess_vuid;
1713 if (!sconn->smb1.sessions.done_sesssetup) {
1714 sconn->smb1.sessions.max_send =
1715 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1717 sconn->smb1.sessions.done_sesssetup = true;
1719 END_PROFILE(SMBsesssetupX);
1720 chain_reply(req);
1721 return;