s3-docs: Fix typos.
[Samba/gbeck.git] / source3 / smbd / sesssetup.c
blob28ae24e95f8698a448f63382b7ae0982beed3f18
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"
39 #include "auth/gensec/gensec.h"
41 /* For split krb5 SPNEGO blobs. */
42 struct pending_auth_data {
43 struct pending_auth_data *prev, *next;
44 uint16 vuid; /* Tag for this entry. */
45 uint16 smbpid; /* Alternate tag for this entry. */
46 size_t needed_len;
47 DATA_BLOB partial_data;
50 /****************************************************************************
51 Add the standard 'Samba' signature to the end of the session setup.
52 ****************************************************************************/
54 static int push_signature(uint8 **outbuf)
56 char *lanman;
57 int result, tmp;
59 result = 0;
61 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
63 if (tmp == -1) return -1;
64 result += tmp;
66 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
67 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
68 SAFE_FREE(lanman);
70 else {
71 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
74 if (tmp == -1) return -1;
75 result += tmp;
77 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
79 if (tmp == -1) return -1;
80 result += tmp;
82 return result;
85 /****************************************************************************
86 Send a security blob via a session setup reply.
87 ****************************************************************************/
89 static void reply_sesssetup_blob(struct smb_request *req,
90 DATA_BLOB blob,
91 NTSTATUS nt_status)
93 if (!NT_STATUS_IS_OK(nt_status) &&
94 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
95 reply_nterror(req, nt_status_squash(nt_status));
96 return;
99 nt_status = nt_status_squash(nt_status);
100 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
101 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
102 SSVAL(req->outbuf, smb_vwv3, blob.length);
104 if ((message_push_blob(&req->outbuf, blob) == -1)
105 || (push_signature(&req->outbuf) == -1)) {
106 reply_nterror(req, NT_STATUS_NO_MEMORY);
110 /****************************************************************************
111 Do a 'guest' logon, getting back the
112 ****************************************************************************/
114 static NTSTATUS check_guest_password(const struct tsocket_address *remote_address,
115 struct auth_serversupplied_info **server_info)
117 struct auth_context *auth_context;
118 struct auth_usersupplied_info *user_info = NULL;
120 NTSTATUS nt_status;
121 static unsigned char chal[8] = { 0, };
123 DEBUG(3,("Got anonymous request\n"));
125 nt_status = make_auth_context_fixed(talloc_tos(), &auth_context, chal);
126 if (!NT_STATUS_IS_OK(nt_status)) {
127 return nt_status;
130 if (!make_user_info_guest(remote_address, &user_info)) {
131 TALLOC_FREE(auth_context);
132 return NT_STATUS_NO_MEMORY;
135 nt_status = auth_context->check_ntlm_password(auth_context,
136 user_info,
137 server_info);
138 TALLOC_FREE(auth_context);
139 free_user_info(&user_info);
140 return nt_status;
144 #ifdef HAVE_KRB5
146 #if 0
147 /* Experiment that failed. See "only happens with a KDC" comment below. */
148 /****************************************************************************
149 Cerate a clock skew error blob for a Windows client.
150 ****************************************************************************/
152 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
154 krb5_context context = NULL;
155 krb5_error_code kerr = 0;
156 krb5_data reply;
157 krb5_principal host_princ = NULL;
158 char *host_princ_s = NULL;
159 bool ret = False;
161 *pblob_out = data_blob_null;
163 initialize_krb5_error_table();
164 kerr = krb5_init_context(&context);
165 if (kerr) {
166 return False;
168 /* Create server principal. */
169 asprintf(&host_princ_s, "%s$@%s", lp_netbios_name(), lp_realm());
170 if (!host_princ_s) {
171 goto out;
173 strlower_m(host_princ_s);
175 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
176 if (kerr) {
177 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
178 "for name %s: Error %s\n",
179 host_princ_s, error_message(kerr) ));
180 goto out;
183 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
184 host_princ, &reply);
185 if (kerr) {
186 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
187 "failed: Error %s\n",
188 error_message(kerr) ));
189 goto out;
192 *pblob_out = data_blob(reply.data, reply.length);
193 kerberos_free_data_contents(context,&reply);
194 ret = True;
196 out:
198 if (host_princ_s) {
199 SAFE_FREE(host_princ_s);
201 if (host_princ) {
202 krb5_free_principal(context, host_princ);
204 krb5_free_context(context);
205 return ret;
207 #endif
209 /****************************************************************************
210 Reply to a session setup spnego negotiate packet for kerberos.
211 ****************************************************************************/
213 static void reply_spnego_kerberos(struct smb_request *req,
214 DATA_BLOB *secblob,
215 const char *mechOID,
216 uint16 vuid,
217 bool *p_invalidate_vuid)
219 TALLOC_CTX *mem_ctx;
220 DATA_BLOB ticket;
221 struct passwd *pw;
222 int sess_vuid = req->vuid;
223 NTSTATUS ret = NT_STATUS_OK;
224 DATA_BLOB ap_rep, ap_rep_wrapped, response;
225 struct auth_session_info *session_info = NULL;
226 DATA_BLOB session_key = data_blob_null;
227 uint8 tok_id[2];
228 DATA_BLOB nullblob = data_blob_null;
229 bool map_domainuser_to_guest = False;
230 bool username_was_mapped;
231 struct PAC_LOGON_INFO *logon_info = NULL;
232 struct smbd_server_connection *sconn = req->sconn;
233 char *principal;
234 char *user;
235 char *domain;
236 char *real_username;
238 ZERO_STRUCT(ticket);
239 ZERO_STRUCT(ap_rep);
240 ZERO_STRUCT(ap_rep_wrapped);
241 ZERO_STRUCT(response);
243 /* Normally we will always invalidate the intermediate vuid. */
244 *p_invalidate_vuid = True;
246 mem_ctx = talloc_init("reply_spnego_kerberos");
247 if (mem_ctx == NULL) {
248 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
249 return;
252 if (!spnego_parse_krb5_wrap(mem_ctx, *secblob, &ticket, tok_id)) {
253 talloc_destroy(mem_ctx);
254 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
255 return;
258 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
259 &principal, &logon_info, &ap_rep,
260 &session_key, True);
262 data_blob_free(&ticket);
264 if (!NT_STATUS_IS_OK(ret)) {
265 #if 0
266 /* Experiment that failed.
267 * See "only happens with a KDC" comment below. */
269 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
272 * Windows in this case returns
273 * NT_STATUS_MORE_PROCESSING_REQUIRED
274 * with a negTokenTarg blob containing an krb5_error
275 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
276 * The client then fixes its clock and continues rather
277 * than giving an error. JRA.
278 * -- Looks like this only happens with a KDC. JRA.
281 bool ok = make_krb5_skew_error(&ap_rep);
282 if (!ok) {
283 talloc_destroy(mem_ctx);
284 return ERROR_NT(nt_status_squash(
285 NT_STATUS_LOGON_FAILURE));
287 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
288 TOK_ID_KRB_ERROR);
289 response = spnego_gen_auth_response(&ap_rep_wrapped,
290 ret, OID_KERBEROS5_OLD);
291 reply_sesssetup_blob(conn, inbuf, outbuf, response,
292 NT_STATUS_MORE_PROCESSING_REQUIRED);
295 * In this one case we don't invalidate the
296 * intermediate vuid as we're expecting the client
297 * to re-use it for the next sessionsetupX packet. JRA.
300 *p_invalidate_vuid = False;
302 data_blob_free(&ap_rep);
303 data_blob_free(&ap_rep_wrapped);
304 data_blob_free(&response);
305 talloc_destroy(mem_ctx);
306 return -1; /* already replied */
308 #else
309 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
310 ret = NT_STATUS_LOGON_FAILURE;
312 #endif
313 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
314 nt_errstr(ret)));
315 talloc_destroy(mem_ctx);
316 reply_nterror(req, nt_status_squash(ret));
317 return;
320 ret = get_user_from_kerberos_info(talloc_tos(),
321 sconn->remote_hostname,
322 principal, logon_info,
323 &username_was_mapped,
324 &map_domainuser_to_guest,
325 &user, &domain,
326 &real_username, &pw);
327 if (!NT_STATUS_IS_OK(ret)) {
328 data_blob_free(&ap_rep);
329 data_blob_free(&session_key);
330 talloc_destroy(mem_ctx);
331 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
332 return;
335 /* save the PAC data if we have it */
336 if (logon_info) {
337 netsamlogon_cache_store(user, &logon_info->info3);
340 /* setup the string used by %U */
341 sub_set_smb_name(real_username);
343 /* reload services so that the new %U is taken into account */
344 reload_services(sconn->msg_ctx, sconn->sock, True);
346 ret = make_session_info_krb5(mem_ctx,
347 user, domain, real_username, pw,
348 logon_info, map_domainuser_to_guest,
349 username_was_mapped,
350 &session_key,
351 &session_info);
352 data_blob_free(&session_key);
353 if (!NT_STATUS_IS_OK(ret)) {
354 DEBUG(1, ("make_server_info_krb5 failed!\n"));
355 data_blob_free(&ap_rep);
356 TALLOC_FREE(mem_ctx);
357 reply_nterror(req, nt_status_squash(ret));
358 return;
361 if (!is_partial_auth_vuid(sconn, sess_vuid)) {
362 sess_vuid = register_initial_vuid(sconn);
365 /* register_existing_vuid keeps the server info */
366 /* register_existing_vuid takes ownership of session_key on success,
367 * no need to free after this on success. A better interface would copy
368 * it.... */
370 sess_vuid = register_existing_vuid(sconn, sess_vuid,
371 session_info, nullblob);
373 reply_outbuf(req, 4, 0);
374 SSVAL(req->outbuf,smb_uid,sess_vuid);
376 if (sess_vuid == UID_FIELD_INVALID ) {
377 ret = NT_STATUS_LOGON_FAILURE;
378 } else {
379 /* current_user_info is changed on new vuid */
380 reload_services(sconn->msg_ctx, sconn->sock, True);
382 SSVAL(req->outbuf, smb_vwv3, 0);
384 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
385 SSVAL(req->outbuf,smb_vwv2,1);
388 SSVAL(req->outbuf, smb_uid, sess_vuid);
390 /* Successful logon. Keep this vuid. */
391 *p_invalidate_vuid = False;
394 /* wrap that up in a nice GSS-API wrapping */
395 if (NT_STATUS_IS_OK(ret)) {
396 ap_rep_wrapped = spnego_gen_krb5_wrap(talloc_tos(), ap_rep,
397 TOK_ID_KRB_AP_REP);
398 } else {
399 ap_rep_wrapped = data_blob_null;
401 response = spnego_gen_auth_response(talloc_tos(), &ap_rep_wrapped, ret,
402 mechOID);
403 reply_sesssetup_blob(req, response, ret);
405 data_blob_free(&ap_rep);
406 data_blob_free(&ap_rep_wrapped);
407 data_blob_free(&response);
408 TALLOC_FREE(mem_ctx);
411 #endif
413 /****************************************************************************
414 Send a session setup reply, wrapped in SPNEGO.
415 Get vuid and check first.
416 End the NTLMSSP exchange context if we are OK/complete fail
417 This should be split into two functions, one to handle each
418 leg of the NTLM auth steps.
419 ***************************************************************************/
421 static void reply_spnego_ntlmssp(struct smb_request *req,
422 uint16 vuid,
423 struct auth_ntlmssp_state **auth_ntlmssp_state,
424 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
425 const char *OID,
426 bool wrap)
428 bool do_invalidate = true;
429 DATA_BLOB response;
430 struct auth_session_info *session_info = NULL;
431 struct smbd_server_connection *sconn = req->sconn;
433 if (NT_STATUS_IS_OK(nt_status)) {
434 nt_status = auth_ntlmssp_session_info(talloc_tos(),
435 (*auth_ntlmssp_state), &session_info);
438 reply_outbuf(req, 4, 0);
440 SSVAL(req->outbuf, smb_uid, vuid);
442 if (NT_STATUS_IS_OK(nt_status)) {
443 DATA_BLOB nullblob = data_blob_null;
445 if (!is_partial_auth_vuid(sconn, vuid)) {
446 nt_status = NT_STATUS_LOGON_FAILURE;
447 goto out;
450 /* register_existing_vuid keeps the server info */
451 if (register_existing_vuid(sconn, vuid,
452 session_info, nullblob) !=
453 vuid) {
454 /* The problem is, *auth_ntlmssp_state points
455 * into the vuser this will have
456 * talloc_free()'ed in
457 * register_existing_vuid() */
458 do_invalidate = false;
459 nt_status = NT_STATUS_LOGON_FAILURE;
460 goto out;
463 /* current_user_info is changed on new vuid */
464 reload_services(sconn->msg_ctx, sconn->sock, True);
466 SSVAL(req->outbuf, smb_vwv3, 0);
468 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
469 SSVAL(req->outbuf,smb_vwv2,1);
473 out:
475 if (wrap) {
476 response = spnego_gen_auth_response(talloc_tos(),
477 ntlmssp_blob,
478 nt_status, OID);
479 } else {
480 response = *ntlmssp_blob;
483 reply_sesssetup_blob(req, response, nt_status);
484 if (wrap) {
485 data_blob_free(&response);
488 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
489 and the other end, that we are not finished yet. */
491 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
492 /* NB. This is *NOT* an error case. JRA */
493 if (do_invalidate) {
494 TALLOC_FREE(*auth_ntlmssp_state);
495 if (!NT_STATUS_IS_OK(nt_status)) {
496 /* Kill the intermediate vuid */
497 invalidate_vuid(sconn, vuid);
503 /****************************************************************************
504 Is this a krb5 mechanism ?
505 ****************************************************************************/
507 NTSTATUS parse_spnego_mechanisms(TALLOC_CTX *ctx,
508 DATA_BLOB blob_in,
509 DATA_BLOB *pblob_out,
510 char **kerb_mechOID)
512 char *OIDs[ASN1_MAX_OIDS];
513 int i;
514 NTSTATUS ret = NT_STATUS_OK;
516 *kerb_mechOID = NULL;
518 /* parse out the OIDs and the first sec blob */
519 if (!spnego_parse_negTokenInit(ctx, blob_in, OIDs, NULL, pblob_out) ||
520 (OIDs[0] == NULL)) {
521 return NT_STATUS_LOGON_FAILURE;
524 /* only look at the first OID for determining the mechToken --
525 according to RFC2478, we should choose the one we want
526 and renegotiate, but i smell a client bug here..
528 Problem observed when connecting to a member (samba box)
529 of an AD domain as a user in a Samba domain. Samba member
530 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
531 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
532 NTLMSSP mechtoken. --jerry */
534 #ifdef HAVE_KRB5
535 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
536 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
537 *kerb_mechOID = talloc_strdup(ctx, OIDs[0]);
538 if (*kerb_mechOID == NULL) {
539 ret = NT_STATUS_NO_MEMORY;
542 #endif
544 for (i=0;OIDs[i];i++) {
545 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
546 talloc_free(OIDs[i]);
548 return ret;
551 /****************************************************************************
552 Fall back from krb5 to NTLMSSP.
553 ****************************************************************************/
555 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
556 uint16 vuid)
558 DATA_BLOB response;
560 reply_outbuf(req, 4, 0);
561 SSVAL(req->outbuf,smb_uid,vuid);
563 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
564 "but set to downgrade to NTLMSSP\n"));
566 response = spnego_gen_auth_response(talloc_tos(), NULL,
567 NT_STATUS_MORE_PROCESSING_REQUIRED,
568 OID_NTLMSSP);
569 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
570 data_blob_free(&response);
573 /****************************************************************************
574 Reply to a session setup spnego negotiate packet.
575 ****************************************************************************/
577 static void reply_spnego_negotiate(struct smb_request *req,
578 uint16 vuid,
579 DATA_BLOB blob1,
580 struct auth_ntlmssp_state **auth_ntlmssp_state)
582 DATA_BLOB secblob;
583 DATA_BLOB chal;
584 char *kerb_mech = NULL;
585 NTSTATUS status;
586 struct smbd_server_connection *sconn = req->sconn;
588 status = parse_spnego_mechanisms(talloc_tos(),
589 blob1, &secblob, &kerb_mech);
590 if (!NT_STATUS_IS_OK(status)) {
591 /* Kill the intermediate vuid */
592 invalidate_vuid(sconn, vuid);
593 reply_nterror(req, nt_status_squash(status));
594 return;
597 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
598 (unsigned long)secblob.length));
600 #ifdef HAVE_KRB5
601 if (kerb_mech && ((lp_security()==SEC_ADS) ||
602 USE_KERBEROS_KEYTAB) ) {
603 bool destroy_vuid = True;
604 reply_spnego_kerberos(req, &secblob, kerb_mech,
605 vuid, &destroy_vuid);
606 data_blob_free(&secblob);
607 if (destroy_vuid) {
608 /* Kill the intermediate vuid */
609 invalidate_vuid(sconn, vuid);
611 TALLOC_FREE(kerb_mech);
612 return;
614 #endif
616 TALLOC_FREE(*auth_ntlmssp_state);
618 if (kerb_mech) {
619 data_blob_free(&secblob);
620 /* The mechtoken is a krb5 ticket, but
621 * we need to fall back to NTLM. */
622 reply_spnego_downgrade_to_ntlmssp(req, vuid);
623 TALLOC_FREE(kerb_mech);
624 return;
627 status = auth_ntlmssp_prepare(sconn->remote_address,
628 auth_ntlmssp_state);
629 if (!NT_STATUS_IS_OK(status)) {
630 /* Kill the intermediate vuid */
631 invalidate_vuid(sconn, vuid);
632 reply_nterror(req, nt_status_squash(status));
633 return;
636 auth_ntlmssp_want_feature(*auth_ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
638 status = auth_ntlmssp_start(*auth_ntlmssp_state);
639 if (!NT_STATUS_IS_OK(status)) {
640 /* Kill the intermediate vuid */
641 invalidate_vuid(sconn, vuid);
642 reply_nterror(req, nt_status_squash(status));
643 return;
646 status = auth_ntlmssp_update(*auth_ntlmssp_state, talloc_tos(),
647 secblob, &chal);
649 data_blob_free(&secblob);
651 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
652 &chal, status, OID_NTLMSSP, true);
654 data_blob_free(&chal);
656 /* already replied */
657 return;
660 /****************************************************************************
661 Reply to a session setup spnego auth packet.
662 ****************************************************************************/
664 static void reply_spnego_auth(struct smb_request *req,
665 uint16 vuid,
666 DATA_BLOB blob1,
667 struct auth_ntlmssp_state **auth_ntlmssp_state)
669 DATA_BLOB auth = data_blob_null;
670 DATA_BLOB auth_reply = data_blob_null;
671 DATA_BLOB secblob = data_blob_null;
672 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
673 struct smbd_server_connection *sconn = req->sconn;
675 if (!spnego_parse_auth(talloc_tos(), blob1, &auth)) {
676 #if 0
677 file_save("auth.dat", blob1.data, blob1.length);
678 #endif
679 /* Kill the intermediate vuid */
680 invalidate_vuid(sconn, vuid);
682 reply_nterror(req, nt_status_squash(
683 NT_STATUS_LOGON_FAILURE));
684 return;
687 if (auth.data[0] == ASN1_APPLICATION(0)) {
688 /* Might be a second negTokenTarg packet */
689 char *kerb_mech = NULL;
691 status = parse_spnego_mechanisms(talloc_tos(),
692 auth, &secblob, &kerb_mech);
694 if (!NT_STATUS_IS_OK(status)) {
695 /* Kill the intermediate vuid */
696 invalidate_vuid(sconn, vuid);
697 reply_nterror(req, nt_status_squash(status));
698 return;
701 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
702 (unsigned long)secblob.length));
703 #ifdef HAVE_KRB5
704 if (kerb_mech && ((lp_security()==SEC_ADS) ||
705 USE_KERBEROS_KEYTAB)) {
706 bool destroy_vuid = True;
707 reply_spnego_kerberos(req, &secblob, kerb_mech,
708 vuid, &destroy_vuid);
709 data_blob_free(&secblob);
710 data_blob_free(&auth);
711 if (destroy_vuid) {
712 /* Kill the intermediate vuid */
713 invalidate_vuid(sconn, vuid);
715 TALLOC_FREE(kerb_mech);
716 return;
718 #endif
719 /* Can't blunder into NTLMSSP auth if we have
720 * a krb5 ticket. */
722 if (kerb_mech) {
723 /* Kill the intermediate vuid */
724 invalidate_vuid(sconn, vuid);
725 DEBUG(3,("reply_spnego_auth: network "
726 "misconfiguration, client sent us a "
727 "krb5 ticket and kerberos security "
728 "not enabled\n"));
729 reply_nterror(req, nt_status_squash(
730 NT_STATUS_LOGON_FAILURE));
731 TALLOC_FREE(kerb_mech);
735 /* If we get here it wasn't a negTokenTarg auth packet. */
736 data_blob_free(&secblob);
738 if (!*auth_ntlmssp_state) {
739 status = auth_ntlmssp_prepare(sconn->remote_address,
740 auth_ntlmssp_state);
741 if (!NT_STATUS_IS_OK(status)) {
742 /* Kill the intermediate vuid */
743 invalidate_vuid(sconn, vuid);
744 reply_nterror(req, nt_status_squash(status));
745 return;
748 auth_ntlmssp_want_feature(*auth_ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
750 status = auth_ntlmssp_start(*auth_ntlmssp_state);
751 if (!NT_STATUS_IS_OK(status)) {
752 /* Kill the intermediate vuid */
753 invalidate_vuid(sconn, vuid);
754 reply_nterror(req, nt_status_squash(status));
755 return;
759 status = auth_ntlmssp_update(*auth_ntlmssp_state, talloc_tos(),
760 auth, &auth_reply);
762 data_blob_free(&auth);
764 /* Don't send the mechid as we've already sent this (RFC4178). */
766 reply_spnego_ntlmssp(req, vuid,
767 auth_ntlmssp_state,
768 &auth_reply, status, NULL, true);
770 data_blob_free(&auth_reply);
772 /* and tell smbd that we have already replied to this packet */
773 return;
776 /****************************************************************************
777 Delete an entry on the list.
778 ****************************************************************************/
780 static void delete_partial_auth(struct smbd_server_connection *sconn,
781 struct pending_auth_data *pad)
783 if (!pad) {
784 return;
786 DLIST_REMOVE(sconn->smb1.pd_list, pad);
787 data_blob_free(&pad->partial_data);
788 SAFE_FREE(pad);
791 /****************************************************************************
792 Search for a partial SPNEGO auth fragment matching an smbpid.
793 ****************************************************************************/
795 static struct pending_auth_data *get_pending_auth_data(
796 struct smbd_server_connection *sconn,
797 uint16_t smbpid)
799 struct pending_auth_data *pad;
801 * NOTE: using the smbpid here is completely wrong...
802 * see [MS-SMB]
803 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
805 for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
806 if (pad->smbpid == smbpid) {
807 break;
810 return pad;
813 /****************************************************************************
814 Check the size of an SPNEGO blob. If we need more return
815 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
816 the blob to be more than 64k.
817 ****************************************************************************/
819 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
820 uint16 smbpid, uint16 vuid,
821 DATA_BLOB *pblob)
823 struct pending_auth_data *pad = NULL;
824 ASN1_DATA *data;
825 size_t needed_len = 0;
827 pad = get_pending_auth_data(sconn, smbpid);
829 /* Ensure we have some data. */
830 if (pblob->length == 0) {
831 /* Caller can cope. */
832 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
833 delete_partial_auth(sconn, pad);
834 return NT_STATUS_OK;
837 /* Were we waiting for more data ? */
838 if (pad) {
839 DATA_BLOB tmp_blob;
840 size_t copy_len = MIN(65536, pblob->length);
842 /* Integer wrap paranoia.... */
844 if (pad->partial_data.length + copy_len <
845 pad->partial_data.length ||
846 pad->partial_data.length + copy_len < copy_len) {
848 DEBUG(2,("check_spnego_blob_complete: integer wrap "
849 "pad->partial_data.length = %u, "
850 "copy_len = %u\n",
851 (unsigned int)pad->partial_data.length,
852 (unsigned int)copy_len ));
854 delete_partial_auth(sconn, pad);
855 return NT_STATUS_INVALID_PARAMETER;
858 DEBUG(10,("check_spnego_blob_complete: "
859 "pad->partial_data.length = %u, "
860 "pad->needed_len = %u, "
861 "copy_len = %u, "
862 "pblob->length = %u,\n",
863 (unsigned int)pad->partial_data.length,
864 (unsigned int)pad->needed_len,
865 (unsigned int)copy_len,
866 (unsigned int)pblob->length ));
868 tmp_blob = data_blob(NULL,
869 pad->partial_data.length + copy_len);
871 /* Concatenate the two (up to copy_len) bytes. */
872 memcpy(tmp_blob.data,
873 pad->partial_data.data,
874 pad->partial_data.length);
875 memcpy(tmp_blob.data + pad->partial_data.length,
876 pblob->data,
877 copy_len);
879 /* Replace the partial data. */
880 data_blob_free(&pad->partial_data);
881 pad->partial_data = tmp_blob;
882 ZERO_STRUCT(tmp_blob);
884 /* Are we done ? */
885 if (pblob->length >= pad->needed_len) {
886 /* Yes, replace pblob. */
887 data_blob_free(pblob);
888 *pblob = pad->partial_data;
889 ZERO_STRUCT(pad->partial_data);
890 delete_partial_auth(sconn, pad);
891 return NT_STATUS_OK;
894 /* Still need more data. */
895 pad->needed_len -= copy_len;
896 return NT_STATUS_MORE_PROCESSING_REQUIRED;
899 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
900 (pblob->data[0] != ASN1_CONTEXT(1))) {
901 /* Not something we can determine the
902 * length of.
904 return NT_STATUS_OK;
907 /* This is a new SPNEGO sessionsetup - see if
908 * the data given in this blob is enough.
911 data = asn1_init(NULL);
912 if (data == NULL) {
913 return NT_STATUS_NO_MEMORY;
916 asn1_load(data, *pblob);
917 if (asn1_start_tag(data, pblob->data[0])) {
918 /* asn1_start_tag checks if the given
919 length of the blob is enough to complete
920 the tag. If it returns true we know
921 there is nothing to do - the blob is
922 complete. */
923 asn1_free(data);
924 return NT_STATUS_OK;
927 if (data->nesting == NULL) {
928 /* Incorrect tag, allocation failed,
929 or reading the tag length failed.
930 Let the caller catch. */
931 asn1_free(data);
932 return NT_STATUS_OK;
935 /* Here we know asn1_start_tag() has set data->has_error to true.
936 asn1_tag_remaining() will have failed due to the given blob
937 being too short. We need to work out how short. */
939 /* Integer wrap paranoia.... */
941 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
942 data->nesting->taglen + data->nesting->start < data->nesting->start) {
944 DEBUG(2,("check_spnego_blob_complete: integer wrap "
945 "data.nesting->taglen = %u, "
946 "data.nesting->start = %u\n",
947 (unsigned int)data->nesting->taglen,
948 (unsigned int)data->nesting->start ));
950 asn1_free(data);
951 return NT_STATUS_INVALID_PARAMETER;
954 /* Total length of the needed asn1 is the tag length
955 * plus the current offset. */
957 needed_len = data->nesting->taglen + data->nesting->start;
958 asn1_free(data);
960 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
961 "pblob->length = %u\n",
962 (unsigned int)needed_len,
963 (unsigned int)pblob->length ));
965 if (needed_len <= pblob->length) {
966 /* Nothing to do - blob is complete. */
967 /* THIS SHOULD NOT HAPPEN - asn1_start_tag()
968 above should have caught this !!! */
969 DEBUG(0,("check_spnego_blob_complete: logic "
970 "error (needed_len = %u, "
971 "pblob->length = %u).\n",
972 (unsigned int)needed_len,
973 (unsigned int)pblob->length ));
974 return NT_STATUS_OK;
977 /* Refuse the blob if it's bigger than 64k. */
978 if (needed_len > 65536) {
979 DEBUG(2,("check_spnego_blob_complete: needed_len "
980 "too large (%u)\n",
981 (unsigned int)needed_len ));
982 return NT_STATUS_INVALID_PARAMETER;
985 /* We must store this blob until complete. */
986 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
987 return NT_STATUS_NO_MEMORY;
989 pad->needed_len = needed_len - pblob->length;
990 pad->partial_data = data_blob(pblob->data, pblob->length);
991 if (pad->partial_data.data == NULL) {
992 SAFE_FREE(pad);
993 return NT_STATUS_NO_MEMORY;
995 pad->smbpid = smbpid;
996 pad->vuid = vuid;
997 DLIST_ADD(sconn->smb1.pd_list, pad);
999 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1002 /****************************************************************************
1003 Reply to a session setup command.
1004 conn POINTER CAN BE NULL HERE !
1005 ****************************************************************************/
1007 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1009 const uint8 *p;
1010 DATA_BLOB blob1;
1011 size_t bufrem;
1012 char *tmp;
1013 const char *native_os;
1014 const char *native_lanman;
1015 const char *primary_domain;
1016 const char *p2;
1017 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1018 enum remote_arch_types ra_type = get_remote_arch();
1019 int vuid = req->vuid;
1020 user_struct *vuser = NULL;
1021 NTSTATUS status = NT_STATUS_OK;
1022 uint16 smbpid = req->smbpid;
1023 struct smbd_server_connection *sconn = req->sconn;
1025 DEBUG(3,("Doing spnego session setup\n"));
1027 if (global_client_caps == 0) {
1028 global_client_caps = IVAL(req->vwv+10, 0);
1030 if (!(global_client_caps & CAP_STATUS32)) {
1031 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1036 p = req->buf;
1038 if (data_blob_len == 0) {
1039 /* an invalid request */
1040 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1041 return;
1044 bufrem = smbreq_bufrem(req, p);
1045 /* pull the spnego blob */
1046 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1048 #if 0
1049 file_save("negotiate.dat", blob1.data, blob1.length);
1050 #endif
1052 p2 = (const char *)req->buf + blob1.length;
1054 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1055 STR_TERMINATE);
1056 native_os = tmp ? tmp : "";
1058 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1059 STR_TERMINATE);
1060 native_lanman = tmp ? tmp : "";
1062 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1063 STR_TERMINATE);
1064 primary_domain = tmp ? tmp : "";
1066 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1067 native_os, native_lanman, primary_domain));
1069 if ( ra_type == RA_WIN2K ) {
1070 /* Vista sets neither the OS or lanman strings */
1072 if ( !strlen(native_os) && !strlen(native_lanman) )
1073 set_remote_arch(RA_VISTA);
1075 /* Windows 2003 doesn't set the native lanman string,
1076 but does set primary domain which is a bug I think */
1078 if ( !strlen(native_lanman) ) {
1079 ra_lanman_string( primary_domain );
1080 } else {
1081 ra_lanman_string( native_lanman );
1083 } else if ( ra_type == RA_VISTA ) {
1084 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
1085 set_remote_arch(RA_OSX);
1089 /* Did we get a valid vuid ? */
1090 if (!is_partial_auth_vuid(sconn, vuid)) {
1091 /* No, then try and see if this is an intermediate sessionsetup
1092 * for a large SPNEGO packet. */
1093 struct pending_auth_data *pad;
1094 pad = get_pending_auth_data(sconn, smbpid);
1095 if (pad) {
1096 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1097 "pending vuid %u\n",
1098 (unsigned int)pad->vuid ));
1099 vuid = pad->vuid;
1103 /* Do we have a valid vuid now ? */
1104 if (!is_partial_auth_vuid(sconn, vuid)) {
1105 /* No, start a new authentication setup. */
1106 vuid = register_initial_vuid(sconn);
1107 if (vuid == UID_FIELD_INVALID) {
1108 data_blob_free(&blob1);
1109 reply_nterror(req, nt_status_squash(
1110 NT_STATUS_INVALID_PARAMETER));
1111 return;
1115 vuser = get_partial_auth_user_struct(sconn, vuid);
1116 /* This MUST be valid. */
1117 if (!vuser) {
1118 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1121 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1122 * sessionsetup requests as the Windows limit on the security blob
1123 * field is 4k. Bug #4400. JRA.
1126 status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1127 if (!NT_STATUS_IS_OK(status)) {
1128 if (!NT_STATUS_EQUAL(status,
1129 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1130 /* Real error - kill the intermediate vuid */
1131 invalidate_vuid(sconn, vuid);
1133 data_blob_free(&blob1);
1134 reply_nterror(req, nt_status_squash(status));
1135 return;
1138 /* Handle either raw NTLMSSP or hand off the whole blob to
1139 * GENSEC. The processing at this layer is essentially
1140 * identical regardless. In particular, both rely only on the
1141 * status code (not the contents of the packet) and do not
1142 * wrap the result */
1143 if (sconn->use_gensec_hook || ntlmssp_blob_matches_magic(&blob1)) {
1144 DATA_BLOB chal;
1146 if (!vuser->auth_ntlmssp_state) {
1147 status = auth_ntlmssp_prepare(sconn->remote_address,
1148 &vuser->auth_ntlmssp_state);
1149 if (!NT_STATUS_IS_OK(status)) {
1150 /* Kill the intermediate vuid */
1151 invalidate_vuid(sconn, vuid);
1152 data_blob_free(&blob1);
1153 reply_nterror(req, nt_status_squash(status));
1154 return;
1157 auth_ntlmssp_want_feature(vuser->auth_ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
1159 if (sconn->use_gensec_hook) {
1160 status = auth_generic_start(vuser->auth_ntlmssp_state, GENSEC_OID_SPNEGO);
1161 } else {
1162 status = auth_ntlmssp_start(vuser->auth_ntlmssp_state);
1164 if (!NT_STATUS_IS_OK(status)) {
1165 /* Kill the intermediate vuid */
1166 invalidate_vuid(sconn, vuid);
1167 data_blob_free(&blob1);
1168 reply_nterror(req, nt_status_squash(status));
1169 return;
1173 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1174 talloc_tos(),
1175 blob1, &chal);
1177 data_blob_free(&blob1);
1179 reply_spnego_ntlmssp(req, vuid,
1180 &vuser->auth_ntlmssp_state,
1181 &chal, status, NULL, false);
1182 data_blob_free(&chal);
1183 return;
1186 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1188 /* its a negTokenTarg packet */
1190 reply_spnego_negotiate(req, vuid, blob1,
1191 &vuser->auth_ntlmssp_state);
1192 data_blob_free(&blob1);
1193 return;
1196 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1198 /* its a auth packet */
1200 reply_spnego_auth(req, vuid, blob1,
1201 &vuser->auth_ntlmssp_state);
1202 data_blob_free(&blob1);
1203 return;
1206 /* what sort of packet is this? */
1207 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1209 data_blob_free(&blob1);
1211 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1214 /****************************************************************************
1215 On new VC == 0, shutdown *all* old connections and users.
1216 It seems that only NT4.x does this. At W2K and above (XP etc.).
1217 a new session setup with VC==0 is ignored.
1218 ****************************************************************************/
1220 struct shutdown_state {
1221 const char *ip;
1222 struct messaging_context *msg_ctx;
1225 static int shutdown_other_smbds(const struct connections_key *key,
1226 const struct connections_data *crec,
1227 void *private_data)
1229 struct shutdown_state *state = (struct shutdown_state *)private_data;
1231 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
1232 server_id_str(talloc_tos(), &crec->pid), crec->addr));
1234 if (!process_exists(crec->pid)) {
1235 DEBUG(10, ("process does not exist\n"));
1236 return 0;
1239 if (procid_is_me(&crec->pid)) {
1240 DEBUG(10, ("It's me\n"));
1241 return 0;
1244 if (strcmp(state->ip, crec->addr) != 0) {
1245 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
1246 return 0;
1249 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
1250 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
1251 state->ip));
1253 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
1254 &data_blob_null);
1255 return 0;
1258 static void setup_new_vc_session(struct smbd_server_connection *sconn)
1260 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1261 "compatible we would close all old resources.\n"));
1262 #if 0
1263 conn_close_all();
1264 invalidate_all_vuids();
1265 #endif
1266 if (lp_reset_on_zero_vc()) {
1267 char *addr;
1268 struct shutdown_state state;
1270 addr = tsocket_address_inet_addr_string(
1271 sconn->remote_address, talloc_tos());
1272 if (addr == NULL) {
1273 return;
1275 state.ip = addr;
1276 state.msg_ctx = sconn->msg_ctx;
1277 connections_forall_read(shutdown_other_smbds, &state);
1278 TALLOC_FREE(addr);
1282 /****************************************************************************
1283 Reply to a session setup command.
1284 ****************************************************************************/
1286 void reply_sesssetup_and_X(struct smb_request *req)
1288 int sess_vuid;
1289 int smb_bufsize;
1290 DATA_BLOB lm_resp;
1291 DATA_BLOB nt_resp;
1292 DATA_BLOB plaintext_password;
1293 char *tmp;
1294 const char *user;
1295 fstring sub_user; /* Sanitised username for substituion */
1296 const char *domain;
1297 const char *native_os;
1298 const char *native_lanman;
1299 const char *primary_domain;
1300 struct auth_usersupplied_info *user_info = NULL;
1301 struct auth_serversupplied_info *server_info = NULL;
1302 struct auth_session_info *session_info = NULL;
1303 uint16 smb_flag2 = req->flags2;
1305 NTSTATUS nt_status;
1306 struct smbd_server_connection *sconn = req->sconn;
1308 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1309 bool signing_allowed = false;
1310 bool signing_mandatory = false;
1312 START_PROFILE(SMBsesssetupX);
1314 ZERO_STRUCT(lm_resp);
1315 ZERO_STRUCT(nt_resp);
1316 ZERO_STRUCT(plaintext_password);
1318 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1320 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
1321 signing_allowed = true;
1323 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
1324 signing_mandatory = true;
1328 * We can call srv_set_signing_negotiated() each time.
1329 * It finds out when it needs to turn into a noop
1330 * itself.
1332 srv_set_signing_negotiated(req->sconn,
1333 signing_allowed,
1334 signing_mandatory);
1336 /* a SPNEGO session setup has 12 command words, whereas a normal
1337 NT1 session setup has 13. See the cifs spec. */
1338 if (req->wct == 12 &&
1339 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1341 if (!sconn->smb1.negprot.spnego) {
1342 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1343 "at SPNEGO session setup when it was not "
1344 "negotiated.\n"));
1345 reply_nterror(req, nt_status_squash(
1346 NT_STATUS_LOGON_FAILURE));
1347 END_PROFILE(SMBsesssetupX);
1348 return;
1351 if (SVAL(req->vwv+4, 0) == 0) {
1352 setup_new_vc_session(req->sconn);
1355 reply_sesssetup_and_X_spnego(req);
1356 END_PROFILE(SMBsesssetupX);
1357 return;
1360 smb_bufsize = SVAL(req->vwv+2, 0);
1362 if (get_Protocol() < PROTOCOL_NT1) {
1363 uint16 passlen1 = SVAL(req->vwv+7, 0);
1365 /* Never do NT status codes with protocols before NT1 as we
1366 * don't get client caps. */
1367 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1369 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1370 reply_nterror(req, nt_status_squash(
1371 NT_STATUS_INVALID_PARAMETER));
1372 END_PROFILE(SMBsesssetupX);
1373 return;
1376 if (doencrypt) {
1377 lm_resp = data_blob(req->buf, passlen1);
1378 } else {
1379 plaintext_password = data_blob(req->buf, passlen1+1);
1380 /* Ensure null termination */
1381 plaintext_password.data[passlen1] = 0;
1384 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1385 req->buf + passlen1, STR_TERMINATE);
1386 user = tmp ? tmp : "";
1388 domain = "";
1390 } else {
1391 uint16 passlen1 = SVAL(req->vwv+7, 0);
1392 uint16 passlen2 = SVAL(req->vwv+8, 0);
1393 enum remote_arch_types ra_type = get_remote_arch();
1394 const uint8_t *p = req->buf;
1395 const uint8_t *save_p = req->buf;
1396 uint16 byte_count;
1399 if(global_client_caps == 0) {
1400 global_client_caps = IVAL(req->vwv+11, 0);
1402 if (!(global_client_caps & CAP_STATUS32)) {
1403 remove_from_common_flags2(
1404 FLAGS2_32_BIT_ERROR_CODES);
1407 /* client_caps is used as final determination if
1408 * client is NT or Win95. This is needed to return
1409 * the correct error codes in some circumstances.
1412 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1413 ra_type == RA_WIN95) {
1414 if(!(global_client_caps & (CAP_NT_SMBS|
1415 CAP_STATUS32))) {
1416 set_remote_arch( RA_WIN95);
1421 if (!doencrypt) {
1422 /* both Win95 and WinNT stuff up the password
1423 * lengths for non-encrypting systems. Uggh.
1425 if passlen1==24 its a win95 system, and its setting
1426 the password length incorrectly. Luckily it still
1427 works with the default code because Win95 will null
1428 terminate the password anyway
1430 if passlen1>0 and passlen2>0 then maybe its a NT box
1431 and its setting passlen2 to some random value which
1432 really stuffs things up. we need to fix that one. */
1434 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1435 passlen2 != 1) {
1436 passlen2 = 0;
1440 /* check for nasty tricks */
1441 if (passlen1 > MAX_PASS_LEN
1442 || passlen1 > smbreq_bufrem(req, p)) {
1443 reply_nterror(req, nt_status_squash(
1444 NT_STATUS_INVALID_PARAMETER));
1445 END_PROFILE(SMBsesssetupX);
1446 return;
1449 if (passlen2 > MAX_PASS_LEN
1450 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1451 reply_nterror(req, nt_status_squash(
1452 NT_STATUS_INVALID_PARAMETER));
1453 END_PROFILE(SMBsesssetupX);
1454 return;
1457 /* Save the lanman2 password and the NT md4 password. */
1459 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1460 doencrypt = False;
1463 if (doencrypt) {
1464 lm_resp = data_blob(p, passlen1);
1465 nt_resp = data_blob(p+passlen1, passlen2);
1466 } else if (lp_security() != SEC_SHARE) {
1468 * In share level we should ignore any passwords, so
1469 * only read them if we're not.
1471 char *pass = NULL;
1472 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1474 if (unic && (passlen2 == 0) && passlen1) {
1475 /* Only a ascii plaintext password was sent. */
1476 (void)srvstr_pull_talloc(talloc_tos(),
1477 req->inbuf,
1478 req->flags2,
1479 &pass,
1480 req->buf,
1481 passlen1,
1482 STR_TERMINATE|STR_ASCII);
1483 } else {
1484 (void)srvstr_pull_talloc(talloc_tos(),
1485 req->inbuf,
1486 req->flags2,
1487 &pass,
1488 req->buf,
1489 unic ? passlen2 : passlen1,
1490 STR_TERMINATE);
1492 if (!pass) {
1493 reply_nterror(req, nt_status_squash(
1494 NT_STATUS_INVALID_PARAMETER));
1495 END_PROFILE(SMBsesssetupX);
1496 return;
1498 plaintext_password = data_blob(pass, strlen(pass)+1);
1501 p += passlen1 + passlen2;
1503 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1504 STR_TERMINATE);
1505 user = tmp ? tmp : "";
1507 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1508 STR_TERMINATE);
1509 domain = tmp ? tmp : "";
1511 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1512 STR_TERMINATE);
1513 native_os = tmp ? tmp : "";
1515 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1516 STR_TERMINATE);
1517 native_lanman = tmp ? tmp : "";
1519 /* not documented or decoded by Ethereal but there is one more
1520 * string in the extra bytes which is the same as the
1521 * PrimaryDomain when using extended security. Windows NT 4
1522 * and 2003 use this string to store the native lanman string.
1523 * Windows 9x does not include a string here at all so we have
1524 * to check if we have any extra bytes left */
1526 byte_count = SVAL(req->vwv+13, 0);
1527 if ( PTR_DIFF(p, save_p) < byte_count) {
1528 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1529 STR_TERMINATE);
1530 primary_domain = tmp ? tmp : "";
1531 } else {
1532 primary_domain = talloc_strdup(talloc_tos(), "null");
1535 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1536 "PrimaryDomain=[%s]\n",
1537 domain, native_os, native_lanman, primary_domain));
1539 if ( ra_type == RA_WIN2K ) {
1540 if ( strlen(native_lanman) == 0 )
1541 ra_lanman_string( primary_domain );
1542 else
1543 ra_lanman_string( native_lanman );
1548 if (SVAL(req->vwv+4, 0) == 0) {
1549 setup_new_vc_session(req->sconn);
1552 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1553 domain, user, get_remote_machine_name()));
1555 if (*user) {
1556 if (sconn->smb1.negprot.spnego) {
1558 /* This has to be here, because this is a perfectly
1559 * valid behaviour for guest logons :-( */
1561 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1562 "at 'normal' session setup after "
1563 "negotiating spnego.\n"));
1564 reply_nterror(req, nt_status_squash(
1565 NT_STATUS_LOGON_FAILURE));
1566 END_PROFILE(SMBsesssetupX);
1567 return;
1569 fstrcpy(sub_user, user);
1570 } else {
1571 fstrcpy(sub_user, "");
1574 sub_set_smb_name(sub_user);
1576 reload_services(sconn->msg_ctx, sconn->sock, True);
1578 if (lp_security() == SEC_SHARE) {
1579 char *sub_user_mapped = NULL;
1580 /* In share level we should ignore any passwords */
1582 data_blob_free(&lm_resp);
1583 data_blob_free(&nt_resp);
1584 data_blob_clear_free(&plaintext_password);
1586 (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
1587 if (!sub_user_mapped) {
1588 reply_nterror(req, NT_STATUS_NO_MEMORY);
1589 END_PROFILE(SMBsesssetupX);
1590 return;
1592 fstrcpy(sub_user, sub_user_mapped);
1593 add_session_user(sconn, sub_user);
1594 add_session_workgroup(sconn, domain);
1595 /* Then force it to null for the benfit of the code below */
1596 user = "";
1599 if (!*user) {
1601 nt_status = check_guest_password(sconn->remote_address, &server_info);
1603 } else if (doencrypt) {
1604 struct auth_context *negprot_auth_context = NULL;
1605 negprot_auth_context = sconn->smb1.negprot.auth_context;
1606 if (!negprot_auth_context) {
1607 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1608 "session setup without negprot denied!\n"));
1609 reply_nterror(req, nt_status_squash(
1610 NT_STATUS_LOGON_FAILURE));
1611 END_PROFILE(SMBsesssetupX);
1612 return;
1614 nt_status = make_user_info_for_reply_enc(&user_info, user,
1615 domain,
1616 sconn->remote_address,
1617 lm_resp, nt_resp);
1618 if (NT_STATUS_IS_OK(nt_status)) {
1619 nt_status = negprot_auth_context->check_ntlm_password(
1620 negprot_auth_context,
1621 user_info,
1622 &server_info);
1624 } else {
1625 struct auth_context *plaintext_auth_context = NULL;
1627 nt_status = make_auth_context_subsystem(
1628 talloc_tos(), &plaintext_auth_context);
1630 if (NT_STATUS_IS_OK(nt_status)) {
1631 uint8_t chal[8];
1633 plaintext_auth_context->get_ntlm_challenge(
1634 plaintext_auth_context, chal);
1636 if (!make_user_info_for_reply(&user_info,
1637 user, domain,
1638 sconn->remote_address,
1639 chal,
1640 plaintext_password)) {
1641 nt_status = NT_STATUS_NO_MEMORY;
1644 if (NT_STATUS_IS_OK(nt_status)) {
1645 nt_status = plaintext_auth_context->check_ntlm_password(
1646 plaintext_auth_context,
1647 user_info,
1648 &server_info);
1650 TALLOC_FREE(plaintext_auth_context);
1655 free_user_info(&user_info);
1657 if (!NT_STATUS_IS_OK(nt_status)) {
1658 nt_status = do_map_to_guest_server_info(nt_status, &server_info,
1659 user, domain);
1662 if (!NT_STATUS_IS_OK(nt_status)) {
1663 data_blob_free(&nt_resp);
1664 data_blob_free(&lm_resp);
1665 data_blob_clear_free(&plaintext_password);
1666 reply_nterror(req, nt_status_squash(nt_status));
1667 END_PROFILE(SMBsesssetupX);
1668 return;
1671 nt_status = create_local_token(req, server_info, NULL, sub_user, &session_info);
1672 TALLOC_FREE(server_info);
1674 if (!NT_STATUS_IS_OK(nt_status)) {
1675 DEBUG(10, ("create_local_token failed: %s\n",
1676 nt_errstr(nt_status)));
1677 data_blob_free(&nt_resp);
1678 data_blob_free(&lm_resp);
1679 data_blob_clear_free(&plaintext_password);
1680 reply_nterror(req, nt_status_squash(nt_status));
1681 END_PROFILE(SMBsesssetupX);
1682 return;
1685 data_blob_clear_free(&plaintext_password);
1687 /* it's ok - setup a reply */
1688 reply_outbuf(req, 3, 0);
1689 if (get_Protocol() >= PROTOCOL_NT1) {
1690 push_signature(&req->outbuf);
1691 /* perhaps grab OS version here?? */
1694 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
1695 SSVAL(req->outbuf,smb_vwv2,1);
1698 /* register the name and uid as being validated, so further connections
1699 to a uid can get through without a password, on the same VC */
1701 if (lp_security() == SEC_SHARE) {
1702 sess_vuid = UID_FIELD_INVALID;
1703 TALLOC_FREE(session_info);
1704 } else {
1705 /* Ignore the initial vuid. */
1706 sess_vuid = register_initial_vuid(sconn);
1707 if (sess_vuid == UID_FIELD_INVALID) {
1708 data_blob_free(&nt_resp);
1709 data_blob_free(&lm_resp);
1710 reply_nterror(req, nt_status_squash(
1711 NT_STATUS_LOGON_FAILURE));
1712 END_PROFILE(SMBsesssetupX);
1713 return;
1715 /* register_existing_vuid keeps the session_info */
1716 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1717 session_info,
1718 nt_resp.data ? nt_resp : lm_resp);
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;
1728 /* current_user_info is changed on new vuid */
1729 reload_services(sconn->msg_ctx, sconn->sock, True);
1732 data_blob_free(&nt_resp);
1733 data_blob_free(&lm_resp);
1735 SSVAL(req->outbuf,smb_uid,sess_vuid);
1736 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1737 req->vuid = sess_vuid;
1739 if (!sconn->smb1.sessions.done_sesssetup) {
1740 sconn->smb1.sessions.max_send =
1741 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1743 sconn->smb1.sessions.done_sesssetup = true;
1745 END_PROFILE(SMBsesssetupX);
1746 chain_reply(req);
1747 return;