s3-torture/denytest.c: replace cli_read_old() with cli_read()
[Samba/gebeck_regimport.git] / source3 / smbd / sesssetup.c
blob2df8b435e56df6617838628a272589ef0d1f5ed6
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"
38 #include "../libcli/security/security.h"
40 /* For split krb5 SPNEGO blobs. */
41 struct pending_auth_data {
42 struct pending_auth_data *prev, *next;
43 uint16 vuid; /* Tag for this entry. */
44 uint16 smbpid; /* Alternate tag for this entry. */
45 size_t needed_len;
46 DATA_BLOB partial_data;
50 on a logon error possibly map the error to success if "map to guest"
51 is set approriately
53 static NTSTATUS do_map_to_guest_server_info(NTSTATUS status,
54 struct auth_serversupplied_info **server_info,
55 const char *user, const char *domain)
57 user = user ? user : "";
58 domain = domain ? domain : "";
60 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
61 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
62 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
63 DEBUG(3,("No such user %s [%s] - using guest account\n",
64 user, domain));
65 status = make_server_info_guest(NULL, server_info);
69 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
70 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
71 DEBUG(3,("Registered username %s for guest access\n",
72 user));
73 status = make_server_info_guest(NULL, server_info);
77 return status;
81 on a logon error possibly map the error to success if "map to guest"
82 is set approriately
84 NTSTATUS do_map_to_guest(NTSTATUS status,
85 struct auth_session_info **session_info,
86 const char *user, const char *domain)
88 user = user ? user : "";
89 domain = domain ? domain : "";
91 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
92 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
93 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
94 DEBUG(3,("No such user %s [%s] - using guest account\n",
95 user, domain));
96 status = make_session_info_guest(NULL, session_info);
100 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
101 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
102 DEBUG(3,("Registered username %s for guest access\n",
103 user));
104 status = make_session_info_guest(NULL, session_info);
108 return status;
111 /****************************************************************************
112 Add the standard 'Samba' signature to the end of the session setup.
113 ****************************************************************************/
115 static int push_signature(uint8 **outbuf)
117 char *lanman;
118 int result, tmp;
120 result = 0;
122 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
124 if (tmp == -1) return -1;
125 result += tmp;
127 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
128 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
129 SAFE_FREE(lanman);
131 else {
132 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
135 if (tmp == -1) return -1;
136 result += tmp;
138 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
140 if (tmp == -1) return -1;
141 result += tmp;
143 return result;
146 /****************************************************************************
147 Send a security blob via a session setup reply.
148 ****************************************************************************/
150 static void reply_sesssetup_blob(struct smb_request *req,
151 DATA_BLOB blob,
152 NTSTATUS nt_status)
154 if (!NT_STATUS_IS_OK(nt_status) &&
155 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
156 reply_nterror(req, nt_status_squash(nt_status));
157 return;
160 nt_status = nt_status_squash(nt_status);
161 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
162 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
163 SSVAL(req->outbuf, smb_vwv3, blob.length);
165 if ((message_push_blob(&req->outbuf, blob) == -1)
166 || (push_signature(&req->outbuf) == -1)) {
167 reply_nterror(req, NT_STATUS_NO_MEMORY);
171 /****************************************************************************
172 Do a 'guest' logon, getting back the
173 ****************************************************************************/
175 static NTSTATUS check_guest_password(const struct tsocket_address *remote_address,
176 struct auth_serversupplied_info **server_info)
178 struct auth_context *auth_context;
179 struct auth_usersupplied_info *user_info = NULL;
181 NTSTATUS nt_status;
182 static unsigned char chal[8] = { 0, };
184 DEBUG(3,("Got anonymous request\n"));
186 nt_status = make_auth_context_fixed(talloc_tos(), &auth_context, chal);
187 if (!NT_STATUS_IS_OK(nt_status)) {
188 return nt_status;
191 if (!make_user_info_guest(remote_address, &user_info)) {
192 TALLOC_FREE(auth_context);
193 return NT_STATUS_NO_MEMORY;
196 nt_status = auth_context->check_ntlm_password(auth_context,
197 user_info,
198 server_info);
199 TALLOC_FREE(auth_context);
200 free_user_info(&user_info);
201 return nt_status;
205 #ifdef HAVE_KRB5
207 #if 0
208 /* Experiment that failed. See "only happens with a KDC" comment below. */
209 /****************************************************************************
210 Cerate a clock skew error blob for a Windows client.
211 ****************************************************************************/
213 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
215 krb5_context context = NULL;
216 krb5_error_code kerr = 0;
217 krb5_data reply;
218 krb5_principal host_princ = NULL;
219 char *host_princ_s = NULL;
220 bool ret = False;
222 *pblob_out = data_blob_null;
224 initialize_krb5_error_table();
225 kerr = krb5_init_context(&context);
226 if (kerr) {
227 return False;
229 /* Create server principal. */
230 asprintf(&host_princ_s, "%s$@%s", lp_netbios_name(), lp_realm());
231 if (!host_princ_s) {
232 goto out;
234 strlower_m(host_princ_s);
236 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
237 if (kerr) {
238 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
239 "for name %s: Error %s\n",
240 host_princ_s, error_message(kerr) ));
241 goto out;
244 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
245 host_princ, &reply);
246 if (kerr) {
247 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
248 "failed: Error %s\n",
249 error_message(kerr) ));
250 goto out;
253 *pblob_out = data_blob(reply.data, reply.length);
254 kerberos_free_data_contents(context,&reply);
255 ret = True;
257 out:
259 if (host_princ_s) {
260 SAFE_FREE(host_princ_s);
262 if (host_princ) {
263 krb5_free_principal(context, host_princ);
265 krb5_free_context(context);
266 return ret;
268 #endif
270 /****************************************************************************
271 Reply to a session setup spnego negotiate packet for kerberos.
272 ****************************************************************************/
274 static void reply_spnego_kerberos(struct smb_request *req,
275 DATA_BLOB *secblob,
276 const char *mechOID,
277 uint16 vuid,
278 bool *p_invalidate_vuid)
280 TALLOC_CTX *mem_ctx;
281 DATA_BLOB ticket;
282 struct passwd *pw;
283 int sess_vuid = req->vuid;
284 NTSTATUS ret = NT_STATUS_OK;
285 DATA_BLOB ap_rep, ap_rep_wrapped, response;
286 struct auth_session_info *session_info = NULL;
287 DATA_BLOB session_key = data_blob_null;
288 uint8 tok_id[2];
289 DATA_BLOB nullblob = data_blob_null;
290 bool map_domainuser_to_guest = False;
291 bool username_was_mapped;
292 struct PAC_LOGON_INFO *logon_info = NULL;
293 struct smbd_server_connection *sconn = req->sconn;
294 char *principal;
295 char *user;
296 char *domain;
297 char *real_username;
299 ZERO_STRUCT(ticket);
300 ZERO_STRUCT(ap_rep);
301 ZERO_STRUCT(ap_rep_wrapped);
302 ZERO_STRUCT(response);
304 /* Normally we will always invalidate the intermediate vuid. */
305 *p_invalidate_vuid = True;
307 mem_ctx = talloc_init("reply_spnego_kerberos");
308 if (mem_ctx == NULL) {
309 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
310 return;
313 if (!spnego_parse_krb5_wrap(mem_ctx, *secblob, &ticket, tok_id)) {
314 talloc_destroy(mem_ctx);
315 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
316 return;
319 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
320 &principal, &logon_info, &ap_rep,
321 &session_key, True);
323 data_blob_free(&ticket);
325 if (!NT_STATUS_IS_OK(ret)) {
326 #if 0
327 /* Experiment that failed.
328 * See "only happens with a KDC" comment below. */
330 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
333 * Windows in this case returns
334 * NT_STATUS_MORE_PROCESSING_REQUIRED
335 * with a negTokenTarg blob containing an krb5_error
336 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
337 * The client then fixes its clock and continues rather
338 * than giving an error. JRA.
339 * -- Looks like this only happens with a KDC. JRA.
342 bool ok = make_krb5_skew_error(&ap_rep);
343 if (!ok) {
344 talloc_destroy(mem_ctx);
345 return ERROR_NT(nt_status_squash(
346 NT_STATUS_LOGON_FAILURE));
348 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
349 TOK_ID_KRB_ERROR);
350 response = spnego_gen_auth_response(&ap_rep_wrapped,
351 ret, OID_KERBEROS5_OLD);
352 reply_sesssetup_blob(conn, inbuf, outbuf, response,
353 NT_STATUS_MORE_PROCESSING_REQUIRED);
356 * In this one case we don't invalidate the
357 * intermediate vuid as we're expecting the client
358 * to re-use it for the next sessionsetupX packet. JRA.
361 *p_invalidate_vuid = False;
363 data_blob_free(&ap_rep);
364 data_blob_free(&ap_rep_wrapped);
365 data_blob_free(&response);
366 talloc_destroy(mem_ctx);
367 return -1; /* already replied */
369 #else
370 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
371 ret = NT_STATUS_LOGON_FAILURE;
373 #endif
374 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
375 nt_errstr(ret)));
376 talloc_destroy(mem_ctx);
377 reply_nterror(req, nt_status_squash(ret));
378 return;
381 ret = get_user_from_kerberos_info(talloc_tos(),
382 sconn->remote_hostname,
383 principal, logon_info,
384 &username_was_mapped,
385 &map_domainuser_to_guest,
386 &user, &domain,
387 &real_username, &pw);
388 if (!NT_STATUS_IS_OK(ret)) {
389 data_blob_free(&ap_rep);
390 data_blob_free(&session_key);
391 talloc_destroy(mem_ctx);
392 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
393 return;
396 /* save the PAC data if we have it */
397 if (logon_info) {
398 netsamlogon_cache_store(user, &logon_info->info3);
401 /* setup the string used by %U */
402 sub_set_smb_name(real_username);
404 /* reload services so that the new %U is taken into account */
405 reload_services(sconn->msg_ctx, sconn->sock, True);
407 ret = make_session_info_krb5(mem_ctx,
408 user, domain, real_username, pw,
409 logon_info, map_domainuser_to_guest,
410 username_was_mapped,
411 &session_key,
412 &session_info);
413 data_blob_free(&session_key);
414 if (!NT_STATUS_IS_OK(ret)) {
415 DEBUG(1, ("make_server_info_krb5 failed!\n"));
416 data_blob_free(&ap_rep);
417 TALLOC_FREE(mem_ctx);
418 reply_nterror(req, nt_status_squash(ret));
419 return;
422 if (!is_partial_auth_vuid(sconn, sess_vuid)) {
423 sess_vuid = register_initial_vuid(sconn);
426 /* register_existing_vuid keeps the server info */
427 /* register_existing_vuid takes ownership of session_key on success,
428 * no need to free after this on success. A better interface would copy
429 * it.... */
431 sess_vuid = register_existing_vuid(sconn, sess_vuid,
432 session_info, nullblob, user);
434 reply_outbuf(req, 4, 0);
435 SSVAL(req->outbuf,smb_uid,sess_vuid);
437 if (sess_vuid == UID_FIELD_INVALID ) {
438 ret = NT_STATUS_LOGON_FAILURE;
439 } else {
440 /* current_user_info is changed on new vuid */
441 reload_services(sconn->msg_ctx, sconn->sock, True);
443 SSVAL(req->outbuf, smb_vwv3, 0);
445 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
446 SSVAL(req->outbuf,smb_vwv2,1);
449 SSVAL(req->outbuf, smb_uid, sess_vuid);
451 /* Successful logon. Keep this vuid. */
452 *p_invalidate_vuid = False;
455 /* wrap that up in a nice GSS-API wrapping */
456 if (NT_STATUS_IS_OK(ret)) {
457 ap_rep_wrapped = spnego_gen_krb5_wrap(talloc_tos(), ap_rep,
458 TOK_ID_KRB_AP_REP);
459 } else {
460 ap_rep_wrapped = data_blob_null;
462 response = spnego_gen_auth_response(talloc_tos(), &ap_rep_wrapped, ret,
463 mechOID);
464 reply_sesssetup_blob(req, response, ret);
466 data_blob_free(&ap_rep);
467 data_blob_free(&ap_rep_wrapped);
468 data_blob_free(&response);
469 TALLOC_FREE(mem_ctx);
472 #endif
474 /****************************************************************************
475 Send a session setup reply, wrapped in SPNEGO.
476 Get vuid and check first.
477 End the NTLMSSP exchange context if we are OK/complete fail
478 This should be split into two functions, one to handle each
479 leg of the NTLM auth steps.
480 ***************************************************************************/
482 static void reply_spnego_ntlmssp(struct smb_request *req,
483 uint16 vuid,
484 struct auth_ntlmssp_state **auth_ntlmssp_state,
485 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
486 const char *OID,
487 bool wrap)
489 bool do_invalidate = true;
490 DATA_BLOB response;
491 struct auth_session_info *session_info = NULL;
492 struct smbd_server_connection *sconn = req->sconn;
494 if (NT_STATUS_IS_OK(nt_status)) {
495 nt_status = auth_ntlmssp_steal_session_info(talloc_tos(),
496 (*auth_ntlmssp_state), &session_info);
497 } else {
498 /* Note that this session_info won't have a session
499 * key. But for map to guest, that's exactly the right
500 * thing - we can't reasonably guess the key the
501 * client wants, as the password was wrong */
502 nt_status = do_map_to_guest(nt_status,
503 &session_info,
504 auth_ntlmssp_get_username(*auth_ntlmssp_state),
505 auth_ntlmssp_get_domain(*auth_ntlmssp_state));
508 reply_outbuf(req, 4, 0);
510 SSVAL(req->outbuf, smb_uid, vuid);
512 if (NT_STATUS_IS_OK(nt_status)) {
513 DATA_BLOB nullblob = data_blob_null;
515 if (!is_partial_auth_vuid(sconn, vuid)) {
516 nt_status = NT_STATUS_LOGON_FAILURE;
517 goto out;
520 /* register_existing_vuid keeps the server info */
521 if (register_existing_vuid(sconn, vuid,
522 session_info, nullblob,
523 auth_ntlmssp_get_username(*auth_ntlmssp_state)) !=
524 vuid) {
525 /* The problem is, *auth_ntlmssp_state points
526 * into the vuser this will have
527 * talloc_free()'ed in
528 * register_existing_vuid() */
529 do_invalidate = false;
530 nt_status = NT_STATUS_LOGON_FAILURE;
531 goto out;
534 /* current_user_info is changed on new vuid */
535 reload_services(sconn->msg_ctx, sconn->sock, True);
537 SSVAL(req->outbuf, smb_vwv3, 0);
539 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
540 SSVAL(req->outbuf,smb_vwv2,1);
544 out:
546 if (wrap) {
547 response = spnego_gen_auth_response(talloc_tos(),
548 ntlmssp_blob,
549 nt_status, OID);
550 } else {
551 response = *ntlmssp_blob;
554 reply_sesssetup_blob(req, response, nt_status);
555 if (wrap) {
556 data_blob_free(&response);
559 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
560 and the other end, that we are not finished yet. */
562 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
563 /* NB. This is *NOT* an error case. JRA */
564 if (do_invalidate) {
565 TALLOC_FREE(*auth_ntlmssp_state);
566 if (!NT_STATUS_IS_OK(nt_status)) {
567 /* Kill the intermediate vuid */
568 invalidate_vuid(sconn, vuid);
574 /****************************************************************************
575 Is this a krb5 mechanism ?
576 ****************************************************************************/
578 NTSTATUS parse_spnego_mechanisms(TALLOC_CTX *ctx,
579 DATA_BLOB blob_in,
580 DATA_BLOB *pblob_out,
581 char **kerb_mechOID)
583 char *OIDs[ASN1_MAX_OIDS];
584 int i;
585 NTSTATUS ret = NT_STATUS_OK;
587 *kerb_mechOID = NULL;
589 /* parse out the OIDs and the first sec blob */
590 if (!spnego_parse_negTokenInit(ctx, blob_in, OIDs, NULL, pblob_out) ||
591 (OIDs[0] == NULL)) {
592 return NT_STATUS_LOGON_FAILURE;
595 /* only look at the first OID for determining the mechToken --
596 according to RFC2478, we should choose the one we want
597 and renegotiate, but i smell a client bug here..
599 Problem observed when connecting to a member (samba box)
600 of an AD domain as a user in a Samba domain. Samba member
601 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
602 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
603 NTLMSSP mechtoken. --jerry */
605 #ifdef HAVE_KRB5
606 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
607 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
608 *kerb_mechOID = talloc_strdup(ctx, OIDs[0]);
609 if (*kerb_mechOID == NULL) {
610 ret = NT_STATUS_NO_MEMORY;
613 #endif
615 for (i=0;OIDs[i];i++) {
616 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
617 talloc_free(OIDs[i]);
619 return ret;
622 /****************************************************************************
623 Fall back from krb5 to NTLMSSP.
624 ****************************************************************************/
626 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
627 uint16 vuid)
629 DATA_BLOB response;
631 reply_outbuf(req, 4, 0);
632 SSVAL(req->outbuf,smb_uid,vuid);
634 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
635 "but set to downgrade to NTLMSSP\n"));
637 response = spnego_gen_auth_response(talloc_tos(), NULL,
638 NT_STATUS_MORE_PROCESSING_REQUIRED,
639 OID_NTLMSSP);
640 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
641 data_blob_free(&response);
644 /****************************************************************************
645 Reply to a session setup spnego negotiate packet.
646 ****************************************************************************/
648 static void reply_spnego_negotiate(struct smb_request *req,
649 uint16 vuid,
650 DATA_BLOB blob1,
651 struct auth_ntlmssp_state **auth_ntlmssp_state)
653 DATA_BLOB secblob;
654 DATA_BLOB chal;
655 char *kerb_mech = NULL;
656 NTSTATUS status;
657 struct smbd_server_connection *sconn = req->sconn;
659 status = parse_spnego_mechanisms(talloc_tos(),
660 blob1, &secblob, &kerb_mech);
661 if (!NT_STATUS_IS_OK(status)) {
662 /* Kill the intermediate vuid */
663 invalidate_vuid(sconn, vuid);
664 reply_nterror(req, nt_status_squash(status));
665 return;
668 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
669 (unsigned long)secblob.length));
671 #ifdef HAVE_KRB5
672 if (kerb_mech && ((lp_security()==SEC_ADS) ||
673 USE_KERBEROS_KEYTAB) ) {
674 bool destroy_vuid = True;
675 reply_spnego_kerberos(req, &secblob, kerb_mech,
676 vuid, &destroy_vuid);
677 data_blob_free(&secblob);
678 if (destroy_vuid) {
679 /* Kill the intermediate vuid */
680 invalidate_vuid(sconn, vuid);
682 TALLOC_FREE(kerb_mech);
683 return;
685 #endif
687 TALLOC_FREE(*auth_ntlmssp_state);
689 if (kerb_mech) {
690 data_blob_free(&secblob);
691 /* The mechtoken is a krb5 ticket, but
692 * we need to fall back to NTLM. */
693 reply_spnego_downgrade_to_ntlmssp(req, vuid);
694 TALLOC_FREE(kerb_mech);
695 return;
698 status = auth_ntlmssp_start(sconn->remote_address,
699 auth_ntlmssp_state);
700 if (!NT_STATUS_IS_OK(status)) {
701 /* Kill the intermediate vuid */
702 invalidate_vuid(sconn, vuid);
703 reply_nterror(req, nt_status_squash(status));
704 return;
707 status = auth_ntlmssp_update(*auth_ntlmssp_state,
708 secblob, &chal);
710 data_blob_free(&secblob);
712 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
713 &chal, status, OID_NTLMSSP, true);
715 data_blob_free(&chal);
717 /* already replied */
718 return;
721 /****************************************************************************
722 Reply to a session setup spnego auth packet.
723 ****************************************************************************/
725 static void reply_spnego_auth(struct smb_request *req,
726 uint16 vuid,
727 DATA_BLOB blob1,
728 struct auth_ntlmssp_state **auth_ntlmssp_state)
730 DATA_BLOB auth = data_blob_null;
731 DATA_BLOB auth_reply = data_blob_null;
732 DATA_BLOB secblob = data_blob_null;
733 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
734 struct smbd_server_connection *sconn = req->sconn;
736 if (!spnego_parse_auth(talloc_tos(), blob1, &auth)) {
737 #if 0
738 file_save("auth.dat", blob1.data, blob1.length);
739 #endif
740 /* Kill the intermediate vuid */
741 invalidate_vuid(sconn, vuid);
743 reply_nterror(req, nt_status_squash(
744 NT_STATUS_LOGON_FAILURE));
745 return;
748 if (auth.data[0] == ASN1_APPLICATION(0)) {
749 /* Might be a second negTokenTarg packet */
750 char *kerb_mech = NULL;
752 status = parse_spnego_mechanisms(talloc_tos(),
753 auth, &secblob, &kerb_mech);
755 if (!NT_STATUS_IS_OK(status)) {
756 /* Kill the intermediate vuid */
757 invalidate_vuid(sconn, vuid);
758 reply_nterror(req, nt_status_squash(status));
759 return;
762 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
763 (unsigned long)secblob.length));
764 #ifdef HAVE_KRB5
765 if (kerb_mech && ((lp_security()==SEC_ADS) ||
766 USE_KERBEROS_KEYTAB)) {
767 bool destroy_vuid = True;
768 reply_spnego_kerberos(req, &secblob, kerb_mech,
769 vuid, &destroy_vuid);
770 data_blob_free(&secblob);
771 data_blob_free(&auth);
772 if (destroy_vuid) {
773 /* Kill the intermediate vuid */
774 invalidate_vuid(sconn, vuid);
776 TALLOC_FREE(kerb_mech);
777 return;
779 #endif
780 /* Can't blunder into NTLMSSP auth if we have
781 * a krb5 ticket. */
783 if (kerb_mech) {
784 /* Kill the intermediate vuid */
785 invalidate_vuid(sconn, vuid);
786 DEBUG(3,("reply_spnego_auth: network "
787 "misconfiguration, client sent us a "
788 "krb5 ticket and kerberos security "
789 "not enabled\n"));
790 reply_nterror(req, nt_status_squash(
791 NT_STATUS_LOGON_FAILURE));
792 TALLOC_FREE(kerb_mech);
796 /* If we get here it wasn't a negTokenTarg auth packet. */
797 data_blob_free(&secblob);
799 if (!*auth_ntlmssp_state) {
800 status = auth_ntlmssp_start(sconn->remote_address,
801 auth_ntlmssp_state);
802 if (!NT_STATUS_IS_OK(status)) {
803 /* Kill the intermediate vuid */
804 invalidate_vuid(sconn, vuid);
805 reply_nterror(req, nt_status_squash(status));
806 return;
810 status = auth_ntlmssp_update(*auth_ntlmssp_state,
811 auth, &auth_reply);
813 data_blob_free(&auth);
815 /* Don't send the mechid as we've already sent this (RFC4178). */
817 reply_spnego_ntlmssp(req, vuid,
818 auth_ntlmssp_state,
819 &auth_reply, status, NULL, true);
821 data_blob_free(&auth_reply);
823 /* and tell smbd that we have already replied to this packet */
824 return;
827 /****************************************************************************
828 Delete an entry on the list.
829 ****************************************************************************/
831 static void delete_partial_auth(struct smbd_server_connection *sconn,
832 struct pending_auth_data *pad)
834 if (!pad) {
835 return;
837 DLIST_REMOVE(sconn->smb1.pd_list, pad);
838 data_blob_free(&pad->partial_data);
839 SAFE_FREE(pad);
842 /****************************************************************************
843 Search for a partial SPNEGO auth fragment matching an smbpid.
844 ****************************************************************************/
846 static struct pending_auth_data *get_pending_auth_data(
847 struct smbd_server_connection *sconn,
848 uint16_t smbpid)
850 struct pending_auth_data *pad;
852 * NOTE: using the smbpid here is completely wrong...
853 * see [MS-SMB]
854 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
856 for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
857 if (pad->smbpid == smbpid) {
858 break;
861 return pad;
864 /****************************************************************************
865 Check the size of an SPNEGO blob. If we need more return
866 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
867 the blob to be more than 64k.
868 ****************************************************************************/
870 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
871 uint16 smbpid, uint16 vuid,
872 DATA_BLOB *pblob)
874 struct pending_auth_data *pad = NULL;
875 ASN1_DATA *data;
876 size_t needed_len = 0;
878 pad = get_pending_auth_data(sconn, smbpid);
880 /* Ensure we have some data. */
881 if (pblob->length == 0) {
882 /* Caller can cope. */
883 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
884 delete_partial_auth(sconn, pad);
885 return NT_STATUS_OK;
888 /* Were we waiting for more data ? */
889 if (pad) {
890 DATA_BLOB tmp_blob;
891 size_t copy_len = MIN(65536, pblob->length);
893 /* Integer wrap paranoia.... */
895 if (pad->partial_data.length + copy_len <
896 pad->partial_data.length ||
897 pad->partial_data.length + copy_len < copy_len) {
899 DEBUG(2,("check_spnego_blob_complete: integer wrap "
900 "pad->partial_data.length = %u, "
901 "copy_len = %u\n",
902 (unsigned int)pad->partial_data.length,
903 (unsigned int)copy_len ));
905 delete_partial_auth(sconn, pad);
906 return NT_STATUS_INVALID_PARAMETER;
909 DEBUG(10,("check_spnego_blob_complete: "
910 "pad->partial_data.length = %u, "
911 "pad->needed_len = %u, "
912 "copy_len = %u, "
913 "pblob->length = %u,\n",
914 (unsigned int)pad->partial_data.length,
915 (unsigned int)pad->needed_len,
916 (unsigned int)copy_len,
917 (unsigned int)pblob->length ));
919 tmp_blob = data_blob(NULL,
920 pad->partial_data.length + copy_len);
922 /* Concatenate the two (up to copy_len) bytes. */
923 memcpy(tmp_blob.data,
924 pad->partial_data.data,
925 pad->partial_data.length);
926 memcpy(tmp_blob.data + pad->partial_data.length,
927 pblob->data,
928 copy_len);
930 /* Replace the partial data. */
931 data_blob_free(&pad->partial_data);
932 pad->partial_data = tmp_blob;
933 ZERO_STRUCT(tmp_blob);
935 /* Are we done ? */
936 if (pblob->length >= pad->needed_len) {
937 /* Yes, replace pblob. */
938 data_blob_free(pblob);
939 *pblob = pad->partial_data;
940 ZERO_STRUCT(pad->partial_data);
941 delete_partial_auth(sconn, pad);
942 return NT_STATUS_OK;
945 /* Still need more data. */
946 pad->needed_len -= copy_len;
947 return NT_STATUS_MORE_PROCESSING_REQUIRED;
950 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
951 (pblob->data[0] != ASN1_CONTEXT(1))) {
952 /* Not something we can determine the
953 * length of.
955 return NT_STATUS_OK;
958 /* This is a new SPNEGO sessionsetup - see if
959 * the data given in this blob is enough.
962 data = asn1_init(NULL);
963 if (data == NULL) {
964 return NT_STATUS_NO_MEMORY;
967 asn1_load(data, *pblob);
968 if (asn1_start_tag(data, pblob->data[0])) {
969 /* asn1_start_tag checks if the given
970 length of the blob is enough to complete
971 the tag. If it returns true we know
972 there is nothing to do - the blob is
973 complete. */
974 asn1_free(data);
975 return NT_STATUS_OK;
978 if (data->nesting == NULL) {
979 /* Incorrect tag, allocation failed,
980 or reading the tag length failed.
981 Let the caller catch. */
982 asn1_free(data);
983 return NT_STATUS_OK;
986 /* Here we know asn1_start_tag() has set data->has_error to true.
987 asn1_tag_remaining() will have failed due to the given blob
988 being too short. We need to work out how short. */
990 /* Integer wrap paranoia.... */
992 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
993 data->nesting->taglen + data->nesting->start < data->nesting->start) {
995 DEBUG(2,("check_spnego_blob_complete: integer wrap "
996 "data.nesting->taglen = %u, "
997 "data.nesting->start = %u\n",
998 (unsigned int)data->nesting->taglen,
999 (unsigned int)data->nesting->start ));
1001 asn1_free(data);
1002 return NT_STATUS_INVALID_PARAMETER;
1005 /* Total length of the needed asn1 is the tag length
1006 * plus the current offset. */
1008 needed_len = data->nesting->taglen + data->nesting->start;
1009 asn1_free(data);
1011 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1012 "pblob->length = %u\n",
1013 (unsigned int)needed_len,
1014 (unsigned int)pblob->length ));
1016 if (needed_len <= pblob->length) {
1017 /* Nothing to do - blob is complete. */
1018 /* THIS SHOULD NOT HAPPEN - asn1_start_tag()
1019 above should have caught this !!! */
1020 DEBUG(0,("check_spnego_blob_complete: logic "
1021 "error (needed_len = %u, "
1022 "pblob->length = %u).\n",
1023 (unsigned int)needed_len,
1024 (unsigned int)pblob->length ));
1025 return NT_STATUS_OK;
1028 /* Refuse the blob if it's bigger than 64k. */
1029 if (needed_len > 65536) {
1030 DEBUG(2,("check_spnego_blob_complete: needed_len "
1031 "too large (%u)\n",
1032 (unsigned int)needed_len ));
1033 return NT_STATUS_INVALID_PARAMETER;
1036 /* We must store this blob until complete. */
1037 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1038 return NT_STATUS_NO_MEMORY;
1040 pad->needed_len = needed_len - pblob->length;
1041 pad->partial_data = data_blob(pblob->data, pblob->length);
1042 if (pad->partial_data.data == NULL) {
1043 SAFE_FREE(pad);
1044 return NT_STATUS_NO_MEMORY;
1046 pad->smbpid = smbpid;
1047 pad->vuid = vuid;
1048 DLIST_ADD(sconn->smb1.pd_list, pad);
1050 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1053 /****************************************************************************
1054 Reply to a session setup command.
1055 conn POINTER CAN BE NULL HERE !
1056 ****************************************************************************/
1058 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1060 const uint8 *p;
1061 DATA_BLOB blob1;
1062 size_t bufrem;
1063 char *tmp;
1064 const char *native_os;
1065 const char *native_lanman;
1066 const char *primary_domain;
1067 const char *p2;
1068 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1069 enum remote_arch_types ra_type = get_remote_arch();
1070 int vuid = req->vuid;
1071 user_struct *vuser = NULL;
1072 NTSTATUS status = NT_STATUS_OK;
1073 uint16 smbpid = req->smbpid;
1074 struct smbd_server_connection *sconn = req->sconn;
1076 DEBUG(3,("Doing spnego session setup\n"));
1078 if (global_client_caps == 0) {
1079 global_client_caps = IVAL(req->vwv+10, 0);
1081 if (!(global_client_caps & CAP_STATUS32)) {
1082 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1087 p = req->buf;
1089 if (data_blob_len == 0) {
1090 /* an invalid request */
1091 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1092 return;
1095 bufrem = smbreq_bufrem(req, p);
1096 /* pull the spnego blob */
1097 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1099 #if 0
1100 file_save("negotiate.dat", blob1.data, blob1.length);
1101 #endif
1103 p2 = (const char *)req->buf + blob1.length;
1105 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1106 STR_TERMINATE);
1107 native_os = tmp ? tmp : "";
1109 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1110 STR_TERMINATE);
1111 native_lanman = tmp ? tmp : "";
1113 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1114 STR_TERMINATE);
1115 primary_domain = tmp ? tmp : "";
1117 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1118 native_os, native_lanman, primary_domain));
1120 if ( ra_type == RA_WIN2K ) {
1121 /* Vista sets neither the OS or lanman strings */
1123 if ( !strlen(native_os) && !strlen(native_lanman) )
1124 set_remote_arch(RA_VISTA);
1126 /* Windows 2003 doesn't set the native lanman string,
1127 but does set primary domain which is a bug I think */
1129 if ( !strlen(native_lanman) ) {
1130 ra_lanman_string( primary_domain );
1131 } else {
1132 ra_lanman_string( native_lanman );
1134 } else if ( ra_type == RA_VISTA ) {
1135 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
1136 set_remote_arch(RA_OSX);
1140 /* Did we get a valid vuid ? */
1141 if (!is_partial_auth_vuid(sconn, vuid)) {
1142 /* No, then try and see if this is an intermediate sessionsetup
1143 * for a large SPNEGO packet. */
1144 struct pending_auth_data *pad;
1145 pad = get_pending_auth_data(sconn, smbpid);
1146 if (pad) {
1147 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1148 "pending vuid %u\n",
1149 (unsigned int)pad->vuid ));
1150 vuid = pad->vuid;
1154 /* Do we have a valid vuid now ? */
1155 if (!is_partial_auth_vuid(sconn, vuid)) {
1156 /* No, start a new authentication setup. */
1157 vuid = register_initial_vuid(sconn);
1158 if (vuid == UID_FIELD_INVALID) {
1159 data_blob_free(&blob1);
1160 reply_nterror(req, nt_status_squash(
1161 NT_STATUS_INVALID_PARAMETER));
1162 return;
1166 vuser = get_partial_auth_user_struct(sconn, vuid);
1167 /* This MUST be valid. */
1168 if (!vuser) {
1169 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1172 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1173 * sessionsetup requests as the Windows limit on the security blob
1174 * field is 4k. Bug #4400. JRA.
1177 status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1178 if (!NT_STATUS_IS_OK(status)) {
1179 if (!NT_STATUS_EQUAL(status,
1180 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1181 /* Real error - kill the intermediate vuid */
1182 invalidate_vuid(sconn, vuid);
1184 data_blob_free(&blob1);
1185 reply_nterror(req, nt_status_squash(status));
1186 return;
1189 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1191 /* its a negTokenTarg packet */
1193 reply_spnego_negotiate(req, vuid, blob1,
1194 &vuser->auth_ntlmssp_state);
1195 data_blob_free(&blob1);
1196 return;
1199 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1201 /* its a auth packet */
1203 reply_spnego_auth(req, vuid, blob1,
1204 &vuser->auth_ntlmssp_state);
1205 data_blob_free(&blob1);
1206 return;
1209 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1210 DATA_BLOB chal;
1212 if (!vuser->auth_ntlmssp_state) {
1213 status = auth_ntlmssp_start(sconn->remote_address,
1214 &vuser->auth_ntlmssp_state);
1215 if (!NT_STATUS_IS_OK(status)) {
1216 /* Kill the intermediate vuid */
1217 invalidate_vuid(sconn, vuid);
1218 data_blob_free(&blob1);
1219 reply_nterror(req, nt_status_squash(status));
1220 return;
1224 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1225 blob1, &chal);
1227 data_blob_free(&blob1);
1229 reply_spnego_ntlmssp(req, vuid,
1230 &vuser->auth_ntlmssp_state,
1231 &chal, status, OID_NTLMSSP, false);
1232 data_blob_free(&chal);
1233 return;
1236 /* what sort of packet is this? */
1237 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1239 data_blob_free(&blob1);
1241 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1244 /****************************************************************************
1245 On new VC == 0, shutdown *all* old connections and users.
1246 It seems that only NT4.x does this. At W2K and above (XP etc.).
1247 a new session setup with VC==0 is ignored.
1248 ****************************************************************************/
1250 struct shutdown_state {
1251 const char *ip;
1252 struct messaging_context *msg_ctx;
1255 static int shutdown_other_smbds(const struct connections_key *key,
1256 const struct connections_data *crec,
1257 void *private_data)
1259 struct shutdown_state *state = (struct shutdown_state *)private_data;
1261 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
1262 server_id_str(talloc_tos(), &crec->pid), crec->addr));
1264 if (!process_exists(crec->pid)) {
1265 DEBUG(10, ("process does not exist\n"));
1266 return 0;
1269 if (procid_is_me(&crec->pid)) {
1270 DEBUG(10, ("It's me\n"));
1271 return 0;
1274 if (strcmp(state->ip, crec->addr) != 0) {
1275 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
1276 return 0;
1279 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
1280 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
1281 state->ip));
1283 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
1284 &data_blob_null);
1285 return 0;
1288 static void setup_new_vc_session(struct smbd_server_connection *sconn)
1290 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1291 "compatible we would close all old resources.\n"));
1292 #if 0
1293 conn_close_all();
1294 invalidate_all_vuids();
1295 #endif
1296 if (lp_reset_on_zero_vc()) {
1297 char *addr;
1298 struct shutdown_state state;
1300 addr = tsocket_address_inet_addr_string(
1301 sconn->remote_address, talloc_tos());
1302 if (addr == NULL) {
1303 return;
1305 state.ip = addr;
1306 state.msg_ctx = sconn->msg_ctx;
1307 connections_forall_read(shutdown_other_smbds, &state);
1308 TALLOC_FREE(addr);
1312 /****************************************************************************
1313 Reply to a session setup command.
1314 ****************************************************************************/
1316 void reply_sesssetup_and_X(struct smb_request *req)
1318 int sess_vuid;
1319 int smb_bufsize;
1320 DATA_BLOB lm_resp;
1321 DATA_BLOB nt_resp;
1322 DATA_BLOB plaintext_password;
1323 char *tmp;
1324 const char *user;
1325 fstring sub_user; /* Sanitised username for substituion */
1326 const char *domain;
1327 const char *native_os;
1328 const char *native_lanman;
1329 const char *primary_domain;
1330 struct auth_usersupplied_info *user_info = NULL;
1331 struct auth_serversupplied_info *server_info = NULL;
1332 struct auth_session_info *session_info = NULL;
1333 uint16 smb_flag2 = req->flags2;
1335 NTSTATUS nt_status;
1336 struct smbd_server_connection *sconn = req->sconn;
1338 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1340 START_PROFILE(SMBsesssetupX);
1342 ZERO_STRUCT(lm_resp);
1343 ZERO_STRUCT(nt_resp);
1344 ZERO_STRUCT(plaintext_password);
1346 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1348 /* a SPNEGO session setup has 12 command words, whereas a normal
1349 NT1 session setup has 13. See the cifs spec. */
1350 if (req->wct == 12 &&
1351 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1353 if (!sconn->smb1.negprot.spnego) {
1354 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1355 "at SPNEGO session setup when it was not "
1356 "negotiated.\n"));
1357 reply_nterror(req, nt_status_squash(
1358 NT_STATUS_LOGON_FAILURE));
1359 END_PROFILE(SMBsesssetupX);
1360 return;
1363 if (SVAL(req->vwv+4, 0) == 0) {
1364 setup_new_vc_session(req->sconn);
1367 reply_sesssetup_and_X_spnego(req);
1368 END_PROFILE(SMBsesssetupX);
1369 return;
1372 smb_bufsize = SVAL(req->vwv+2, 0);
1374 if (get_Protocol() < PROTOCOL_NT1) {
1375 uint16 passlen1 = SVAL(req->vwv+7, 0);
1377 /* Never do NT status codes with protocols before NT1 as we
1378 * don't get client caps. */
1379 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1381 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1382 reply_nterror(req, nt_status_squash(
1383 NT_STATUS_INVALID_PARAMETER));
1384 END_PROFILE(SMBsesssetupX);
1385 return;
1388 if (doencrypt) {
1389 lm_resp = data_blob(req->buf, passlen1);
1390 } else {
1391 plaintext_password = data_blob(req->buf, passlen1+1);
1392 /* Ensure null termination */
1393 plaintext_password.data[passlen1] = 0;
1396 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1397 req->buf + passlen1, STR_TERMINATE);
1398 user = tmp ? tmp : "";
1400 domain = "";
1402 } else {
1403 uint16 passlen1 = SVAL(req->vwv+7, 0);
1404 uint16 passlen2 = SVAL(req->vwv+8, 0);
1405 enum remote_arch_types ra_type = get_remote_arch();
1406 const uint8_t *p = req->buf;
1407 const uint8_t *save_p = req->buf;
1408 uint16 byte_count;
1411 if(global_client_caps == 0) {
1412 global_client_caps = IVAL(req->vwv+11, 0);
1414 if (!(global_client_caps & CAP_STATUS32)) {
1415 remove_from_common_flags2(
1416 FLAGS2_32_BIT_ERROR_CODES);
1419 /* client_caps is used as final determination if
1420 * client is NT or Win95. This is needed to return
1421 * the correct error codes in some circumstances.
1424 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1425 ra_type == RA_WIN95) {
1426 if(!(global_client_caps & (CAP_NT_SMBS|
1427 CAP_STATUS32))) {
1428 set_remote_arch( RA_WIN95);
1433 if (!doencrypt) {
1434 /* both Win95 and WinNT stuff up the password
1435 * lengths for non-encrypting systems. Uggh.
1437 if passlen1==24 its a win95 system, and its setting
1438 the password length incorrectly. Luckily it still
1439 works with the default code because Win95 will null
1440 terminate the password anyway
1442 if passlen1>0 and passlen2>0 then maybe its a NT box
1443 and its setting passlen2 to some random value which
1444 really stuffs things up. we need to fix that one. */
1446 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1447 passlen2 != 1) {
1448 passlen2 = 0;
1452 /* check for nasty tricks */
1453 if (passlen1 > MAX_PASS_LEN
1454 || passlen1 > smbreq_bufrem(req, p)) {
1455 reply_nterror(req, nt_status_squash(
1456 NT_STATUS_INVALID_PARAMETER));
1457 END_PROFILE(SMBsesssetupX);
1458 return;
1461 if (passlen2 > MAX_PASS_LEN
1462 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1463 reply_nterror(req, nt_status_squash(
1464 NT_STATUS_INVALID_PARAMETER));
1465 END_PROFILE(SMBsesssetupX);
1466 return;
1469 /* Save the lanman2 password and the NT md4 password. */
1471 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1472 doencrypt = False;
1475 if (doencrypt) {
1476 lm_resp = data_blob(p, passlen1);
1477 nt_resp = data_blob(p+passlen1, passlen2);
1478 } else if (lp_security() != SEC_SHARE) {
1480 * In share level we should ignore any passwords, so
1481 * only read them if we're not.
1483 char *pass = NULL;
1484 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1486 if (unic && (passlen2 == 0) && passlen1) {
1487 /* Only a ascii plaintext password was sent. */
1488 (void)srvstr_pull_talloc(talloc_tos(),
1489 req->inbuf,
1490 req->flags2,
1491 &pass,
1492 req->buf,
1493 passlen1,
1494 STR_TERMINATE|STR_ASCII);
1495 } else {
1496 (void)srvstr_pull_talloc(talloc_tos(),
1497 req->inbuf,
1498 req->flags2,
1499 &pass,
1500 req->buf,
1501 unic ? passlen2 : passlen1,
1502 STR_TERMINATE);
1504 if (!pass) {
1505 reply_nterror(req, nt_status_squash(
1506 NT_STATUS_INVALID_PARAMETER));
1507 END_PROFILE(SMBsesssetupX);
1508 return;
1510 plaintext_password = data_blob(pass, strlen(pass)+1);
1513 p += passlen1 + passlen2;
1515 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1516 STR_TERMINATE);
1517 user = tmp ? tmp : "";
1519 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1520 STR_TERMINATE);
1521 domain = tmp ? tmp : "";
1523 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1524 STR_TERMINATE);
1525 native_os = tmp ? tmp : "";
1527 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1528 STR_TERMINATE);
1529 native_lanman = tmp ? tmp : "";
1531 /* not documented or decoded by Ethereal but there is one more
1532 * string in the extra bytes which is the same as the
1533 * PrimaryDomain when using extended security. Windows NT 4
1534 * and 2003 use this string to store the native lanman string.
1535 * Windows 9x does not include a string here at all so we have
1536 * to check if we have any extra bytes left */
1538 byte_count = SVAL(req->vwv+13, 0);
1539 if ( PTR_DIFF(p, save_p) < byte_count) {
1540 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1541 STR_TERMINATE);
1542 primary_domain = tmp ? tmp : "";
1543 } else {
1544 primary_domain = talloc_strdup(talloc_tos(), "null");
1547 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1548 "PrimaryDomain=[%s]\n",
1549 domain, native_os, native_lanman, primary_domain));
1551 if ( ra_type == RA_WIN2K ) {
1552 if ( strlen(native_lanman) == 0 )
1553 ra_lanman_string( primary_domain );
1554 else
1555 ra_lanman_string( native_lanman );
1560 if (SVAL(req->vwv+4, 0) == 0) {
1561 setup_new_vc_session(req->sconn);
1564 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1565 domain, user, get_remote_machine_name()));
1567 if (*user) {
1568 if (sconn->smb1.negprot.spnego) {
1570 /* This has to be here, because this is a perfectly
1571 * valid behaviour for guest logons :-( */
1573 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1574 "at 'normal' session setup after "
1575 "negotiating spnego.\n"));
1576 reply_nterror(req, nt_status_squash(
1577 NT_STATUS_LOGON_FAILURE));
1578 END_PROFILE(SMBsesssetupX);
1579 return;
1581 fstrcpy(sub_user, user);
1582 } else {
1583 fstrcpy(sub_user, lp_guestaccount());
1586 sub_set_smb_name(sub_user);
1588 reload_services(sconn->msg_ctx, sconn->sock, True);
1590 if (lp_security() == SEC_SHARE) {
1591 char *sub_user_mapped = NULL;
1592 /* In share level we should ignore any passwords */
1594 data_blob_free(&lm_resp);
1595 data_blob_free(&nt_resp);
1596 data_blob_clear_free(&plaintext_password);
1598 (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
1599 if (!sub_user_mapped) {
1600 reply_nterror(req, NT_STATUS_NO_MEMORY);
1601 END_PROFILE(SMBsesssetupX);
1602 return;
1604 fstrcpy(sub_user, sub_user_mapped);
1605 add_session_user(sconn, sub_user);
1606 add_session_workgroup(sconn, domain);
1607 /* Then force it to null for the benfit of the code below */
1608 user = "";
1611 if (!*user) {
1613 nt_status = check_guest_password(sconn->remote_address, &server_info);
1615 } else if (doencrypt) {
1616 struct auth_context *negprot_auth_context = NULL;
1617 negprot_auth_context = sconn->smb1.negprot.auth_context;
1618 if (!negprot_auth_context) {
1619 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1620 "session setup without negprot denied!\n"));
1621 reply_nterror(req, nt_status_squash(
1622 NT_STATUS_LOGON_FAILURE));
1623 END_PROFILE(SMBsesssetupX);
1624 return;
1626 nt_status = make_user_info_for_reply_enc(&user_info, user,
1627 domain,
1628 sconn->remote_address,
1629 lm_resp, nt_resp);
1630 if (NT_STATUS_IS_OK(nt_status)) {
1631 nt_status = negprot_auth_context->check_ntlm_password(
1632 negprot_auth_context,
1633 user_info,
1634 &server_info);
1636 } else {
1637 struct auth_context *plaintext_auth_context = NULL;
1639 nt_status = make_auth_context_subsystem(
1640 talloc_tos(), &plaintext_auth_context);
1642 if (NT_STATUS_IS_OK(nt_status)) {
1643 uint8_t chal[8];
1645 plaintext_auth_context->get_ntlm_challenge(
1646 plaintext_auth_context, chal);
1648 if (!make_user_info_for_reply(&user_info,
1649 user, domain,
1650 sconn->remote_address,
1651 chal,
1652 plaintext_password)) {
1653 nt_status = NT_STATUS_NO_MEMORY;
1656 if (NT_STATUS_IS_OK(nt_status)) {
1657 nt_status = plaintext_auth_context->check_ntlm_password(
1658 plaintext_auth_context,
1659 user_info,
1660 &server_info);
1662 TALLOC_FREE(plaintext_auth_context);
1667 free_user_info(&user_info);
1669 if (!NT_STATUS_IS_OK(nt_status)) {
1670 nt_status = do_map_to_guest_server_info(nt_status, &server_info,
1671 user, domain);
1674 if (!NT_STATUS_IS_OK(nt_status)) {
1675 data_blob_free(&nt_resp);
1676 data_blob_free(&lm_resp);
1677 data_blob_clear_free(&plaintext_password);
1678 reply_nterror(req, nt_status_squash(nt_status));
1679 END_PROFILE(SMBsesssetupX);
1680 return;
1683 nt_status = create_local_token(req, server_info, NULL, &session_info);
1684 TALLOC_FREE(server_info);
1686 if (!NT_STATUS_IS_OK(nt_status)) {
1687 DEBUG(10, ("create_local_token failed: %s\n",
1688 nt_errstr(nt_status)));
1689 data_blob_free(&nt_resp);
1690 data_blob_free(&lm_resp);
1691 data_blob_clear_free(&plaintext_password);
1692 reply_nterror(req, nt_status_squash(nt_status));
1693 END_PROFILE(SMBsesssetupX);
1694 return;
1697 data_blob_clear_free(&plaintext_password);
1699 /* it's ok - setup a reply */
1700 reply_outbuf(req, 3, 0);
1701 if (get_Protocol() >= PROTOCOL_NT1) {
1702 push_signature(&req->outbuf);
1703 /* perhaps grab OS version here?? */
1706 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
1707 SSVAL(req->outbuf,smb_vwv2,1);
1710 /* register the name and uid as being validated, so further connections
1711 to a uid can get through without a password, on the same VC */
1713 if (lp_security() == SEC_SHARE) {
1714 sess_vuid = UID_FIELD_INVALID;
1715 TALLOC_FREE(session_info);
1716 } else {
1717 /* Ignore the initial vuid. */
1718 sess_vuid = register_initial_vuid(sconn);
1719 if (sess_vuid == UID_FIELD_INVALID) {
1720 data_blob_free(&nt_resp);
1721 data_blob_free(&lm_resp);
1722 reply_nterror(req, nt_status_squash(
1723 NT_STATUS_LOGON_FAILURE));
1724 END_PROFILE(SMBsesssetupX);
1725 return;
1727 /* register_existing_vuid keeps the session_info */
1728 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1729 session_info,
1730 nt_resp.data ? nt_resp : lm_resp,
1731 sub_user);
1732 if (sess_vuid == UID_FIELD_INVALID) {
1733 data_blob_free(&nt_resp);
1734 data_blob_free(&lm_resp);
1735 reply_nterror(req, nt_status_squash(
1736 NT_STATUS_LOGON_FAILURE));
1737 END_PROFILE(SMBsesssetupX);
1738 return;
1741 /* current_user_info is changed on new vuid */
1742 reload_services(sconn->msg_ctx, sconn->sock, True);
1745 data_blob_free(&nt_resp);
1746 data_blob_free(&lm_resp);
1748 SSVAL(req->outbuf,smb_uid,sess_vuid);
1749 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1750 req->vuid = sess_vuid;
1752 if (!sconn->smb1.sessions.done_sesssetup) {
1753 sconn->smb1.sessions.max_send =
1754 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1756 sconn->smb1.sessions.done_sesssetup = true;
1758 END_PROFILE(SMBsesssetupX);
1759 chain_reply(req);
1760 return;