s4 dns: Move record lookup to dns_utils.c
[Samba/gebeck_regimport.git] / source3 / smbd / sesssetup.c
blob889361acb8d745218753fac2b3b1fda712ec5abd
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 "../auth/ntlmssp/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, conn_snum_used, 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, conn_snum_used, 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 = gensec_session_info((*auth_ntlmssp_state)->gensec_security,
435 talloc_tos(),
436 &session_info);
439 reply_outbuf(req, 4, 0);
441 SSVAL(req->outbuf, smb_uid, vuid);
443 if (NT_STATUS_IS_OK(nt_status)) {
444 DATA_BLOB nullblob = data_blob_null;
446 if (!is_partial_auth_vuid(sconn, vuid)) {
447 nt_status = NT_STATUS_LOGON_FAILURE;
448 goto out;
451 /* register_existing_vuid keeps the server info */
452 if (register_existing_vuid(sconn, vuid,
453 session_info, nullblob) !=
454 vuid) {
455 /* The problem is, *auth_ntlmssp_state points
456 * into the vuser this will have
457 * talloc_free()'ed in
458 * register_existing_vuid() */
459 do_invalidate = false;
460 nt_status = NT_STATUS_LOGON_FAILURE;
461 goto out;
464 /* current_user_info is changed on new vuid */
465 reload_services(sconn, conn_snum_used, true);
467 SSVAL(req->outbuf, smb_vwv3, 0);
469 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
470 SSVAL(req->outbuf,smb_vwv2,1);
474 out:
476 if (wrap) {
477 response = spnego_gen_auth_response(talloc_tos(),
478 ntlmssp_blob,
479 nt_status, OID);
480 } else {
481 response = *ntlmssp_blob;
484 reply_sesssetup_blob(req, response, nt_status);
485 if (wrap) {
486 data_blob_free(&response);
489 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
490 and the other end, that we are not finished yet. */
492 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
493 /* NB. This is *NOT* an error case. JRA */
494 if (do_invalidate) {
495 TALLOC_FREE(*auth_ntlmssp_state);
496 if (!NT_STATUS_IS_OK(nt_status)) {
497 /* Kill the intermediate vuid */
498 invalidate_vuid(sconn, vuid);
504 /****************************************************************************
505 Is this a krb5 mechanism ?
506 ****************************************************************************/
508 NTSTATUS parse_spnego_mechanisms(TALLOC_CTX *ctx,
509 DATA_BLOB blob_in,
510 DATA_BLOB *pblob_out,
511 char **kerb_mechOID)
513 char *OIDs[ASN1_MAX_OIDS];
514 int i;
515 NTSTATUS ret = NT_STATUS_OK;
517 *kerb_mechOID = NULL;
519 /* parse out the OIDs and the first sec blob */
520 if (!spnego_parse_negTokenInit(ctx, blob_in, OIDs, NULL, pblob_out) ||
521 (OIDs[0] == NULL)) {
522 return NT_STATUS_LOGON_FAILURE;
525 /* only look at the first OID for determining the mechToken --
526 according to RFC2478, we should choose the one we want
527 and renegotiate, but i smell a client bug here..
529 Problem observed when connecting to a member (samba box)
530 of an AD domain as a user in a Samba domain. Samba member
531 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
532 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
533 NTLMSSP mechtoken. --jerry */
535 #ifdef HAVE_KRB5
536 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
537 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
538 *kerb_mechOID = talloc_strdup(ctx, OIDs[0]);
539 if (*kerb_mechOID == NULL) {
540 ret = NT_STATUS_NO_MEMORY;
543 #endif
545 for (i=0;OIDs[i];i++) {
546 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
547 talloc_free(OIDs[i]);
549 return ret;
552 /****************************************************************************
553 Fall back from krb5 to NTLMSSP.
554 ****************************************************************************/
556 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
557 uint16 vuid)
559 DATA_BLOB response;
561 reply_outbuf(req, 4, 0);
562 SSVAL(req->outbuf,smb_uid,vuid);
564 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
565 "but set to downgrade to NTLMSSP\n"));
567 response = spnego_gen_auth_response(talloc_tos(), NULL,
568 NT_STATUS_MORE_PROCESSING_REQUIRED,
569 OID_NTLMSSP);
570 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
571 data_blob_free(&response);
574 /****************************************************************************
575 Reply to a session setup spnego negotiate packet.
576 ****************************************************************************/
578 static void reply_spnego_negotiate(struct smb_request *req,
579 uint16 vuid,
580 DATA_BLOB blob1,
581 struct auth_ntlmssp_state **auth_ntlmssp_state)
583 DATA_BLOB secblob;
584 DATA_BLOB chal;
585 char *kerb_mech = NULL;
586 NTSTATUS status;
587 struct smbd_server_connection *sconn = req->sconn;
589 status = parse_spnego_mechanisms(talloc_tos(),
590 blob1, &secblob, &kerb_mech);
591 if (!NT_STATUS_IS_OK(status)) {
592 /* Kill the intermediate vuid */
593 invalidate_vuid(sconn, vuid);
594 reply_nterror(req, nt_status_squash(status));
595 return;
598 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
599 (unsigned long)secblob.length));
601 #ifdef HAVE_KRB5
602 if (kerb_mech && ((lp_security()==SEC_ADS) ||
603 USE_KERBEROS_KEYTAB) ) {
604 bool destroy_vuid = True;
605 reply_spnego_kerberos(req, &secblob, kerb_mech,
606 vuid, &destroy_vuid);
607 data_blob_free(&secblob);
608 if (destroy_vuid) {
609 /* Kill the intermediate vuid */
610 invalidate_vuid(sconn, vuid);
612 TALLOC_FREE(kerb_mech);
613 return;
615 #endif
617 TALLOC_FREE(*auth_ntlmssp_state);
619 if (kerb_mech) {
620 data_blob_free(&secblob);
621 /* The mechtoken is a krb5 ticket, but
622 * we need to fall back to NTLM. */
623 reply_spnego_downgrade_to_ntlmssp(req, vuid);
624 TALLOC_FREE(kerb_mech);
625 return;
628 status = auth_ntlmssp_prepare(sconn->remote_address,
629 auth_ntlmssp_state);
630 if (!NT_STATUS_IS_OK(status)) {
631 /* Kill the intermediate vuid */
632 invalidate_vuid(sconn, vuid);
633 reply_nterror(req, nt_status_squash(status));
634 return;
637 gensec_want_feature((*auth_ntlmssp_state)->gensec_security, GENSEC_FEATURE_SESSION_KEY);
639 status = auth_ntlmssp_start(*auth_ntlmssp_state);
640 if (!NT_STATUS_IS_OK(status)) {
641 /* Kill the intermediate vuid */
642 invalidate_vuid(sconn, vuid);
643 reply_nterror(req, nt_status_squash(status));
644 return;
647 status = gensec_update((*auth_ntlmssp_state)->gensec_security, talloc_tos(),
648 NULL, secblob, &chal);
650 data_blob_free(&secblob);
652 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
653 &chal, status, OID_NTLMSSP, true);
655 data_blob_free(&chal);
657 /* already replied */
658 return;
661 /****************************************************************************
662 Reply to a session setup spnego auth packet.
663 ****************************************************************************/
665 static void reply_spnego_auth(struct smb_request *req,
666 uint16 vuid,
667 DATA_BLOB blob1,
668 struct auth_ntlmssp_state **auth_ntlmssp_state)
670 DATA_BLOB auth = data_blob_null;
671 DATA_BLOB auth_reply = data_blob_null;
672 DATA_BLOB secblob = data_blob_null;
673 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
674 struct smbd_server_connection *sconn = req->sconn;
676 if (!spnego_parse_auth(talloc_tos(), blob1, &auth)) {
677 #if 0
678 file_save("auth.dat", blob1.data, blob1.length);
679 #endif
680 /* Kill the intermediate vuid */
681 invalidate_vuid(sconn, vuid);
683 reply_nterror(req, nt_status_squash(
684 NT_STATUS_LOGON_FAILURE));
685 return;
688 if (auth.data[0] == ASN1_APPLICATION(0)) {
689 /* Might be a second negTokenTarg packet */
690 char *kerb_mech = NULL;
692 status = parse_spnego_mechanisms(talloc_tos(),
693 auth, &secblob, &kerb_mech);
695 if (!NT_STATUS_IS_OK(status)) {
696 /* Kill the intermediate vuid */
697 invalidate_vuid(sconn, vuid);
698 reply_nterror(req, nt_status_squash(status));
699 return;
702 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
703 (unsigned long)secblob.length));
704 #ifdef HAVE_KRB5
705 if (kerb_mech && ((lp_security()==SEC_ADS) ||
706 USE_KERBEROS_KEYTAB)) {
707 bool destroy_vuid = True;
708 reply_spnego_kerberos(req, &secblob, kerb_mech,
709 vuid, &destroy_vuid);
710 data_blob_free(&secblob);
711 data_blob_free(&auth);
712 if (destroy_vuid) {
713 /* Kill the intermediate vuid */
714 invalidate_vuid(sconn, vuid);
716 TALLOC_FREE(kerb_mech);
717 return;
719 #endif
720 /* Can't blunder into NTLMSSP auth if we have
721 * a krb5 ticket. */
723 if (kerb_mech) {
724 /* Kill the intermediate vuid */
725 invalidate_vuid(sconn, vuid);
726 DEBUG(3,("reply_spnego_auth: network "
727 "misconfiguration, client sent us a "
728 "krb5 ticket and kerberos security "
729 "not enabled\n"));
730 reply_nterror(req, nt_status_squash(
731 NT_STATUS_LOGON_FAILURE));
732 TALLOC_FREE(kerb_mech);
736 /* If we get here it wasn't a negTokenTarg auth packet. */
737 data_blob_free(&secblob);
739 if (!*auth_ntlmssp_state) {
740 status = auth_ntlmssp_prepare(sconn->remote_address,
741 auth_ntlmssp_state);
742 if (!NT_STATUS_IS_OK(status)) {
743 /* Kill the intermediate vuid */
744 invalidate_vuid(sconn, vuid);
745 reply_nterror(req, nt_status_squash(status));
746 return;
749 gensec_want_feature((*auth_ntlmssp_state)->gensec_security, GENSEC_FEATURE_SESSION_KEY);
751 status = auth_ntlmssp_start(*auth_ntlmssp_state);
752 if (!NT_STATUS_IS_OK(status)) {
753 /* Kill the intermediate vuid */
754 invalidate_vuid(sconn, vuid);
755 reply_nterror(req, nt_status_squash(status));
756 return;
760 status = gensec_update((*auth_ntlmssp_state)->gensec_security, talloc_tos(),
761 NULL, auth, &auth_reply);
763 data_blob_free(&auth);
765 /* Don't send the mechid as we've already sent this (RFC4178). */
767 reply_spnego_ntlmssp(req, vuid,
768 auth_ntlmssp_state,
769 &auth_reply, status, NULL, true);
771 data_blob_free(&auth_reply);
773 /* and tell smbd that we have already replied to this packet */
774 return;
777 /****************************************************************************
778 Delete an entry on the list.
779 ****************************************************************************/
781 static void delete_partial_auth(struct smbd_server_connection *sconn,
782 struct pending_auth_data *pad)
784 if (!pad) {
785 return;
787 DLIST_REMOVE(sconn->smb1.pd_list, pad);
788 data_blob_free(&pad->partial_data);
789 SAFE_FREE(pad);
792 /****************************************************************************
793 Search for a partial SPNEGO auth fragment matching an smbpid.
794 ****************************************************************************/
796 static struct pending_auth_data *get_pending_auth_data(
797 struct smbd_server_connection *sconn,
798 uint16_t smbpid)
800 struct pending_auth_data *pad;
802 * NOTE: using the smbpid here is completely wrong...
803 * see [MS-SMB]
804 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
806 for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
807 if (pad->smbpid == smbpid) {
808 break;
811 return pad;
814 /****************************************************************************
815 Check the size of an SPNEGO blob. If we need more return
816 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
817 the blob to be more than 64k.
818 ****************************************************************************/
820 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
821 uint16 smbpid, uint16 vuid,
822 DATA_BLOB *pblob)
824 struct pending_auth_data *pad = NULL;
825 ASN1_DATA *data;
826 size_t needed_len = 0;
828 pad = get_pending_auth_data(sconn, smbpid);
830 /* Ensure we have some data. */
831 if (pblob->length == 0) {
832 /* Caller can cope. */
833 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
834 delete_partial_auth(sconn, pad);
835 return NT_STATUS_OK;
838 /* Were we waiting for more data ? */
839 if (pad) {
840 DATA_BLOB tmp_blob;
841 size_t copy_len = MIN(65536, pblob->length);
843 /* Integer wrap paranoia.... */
845 if (pad->partial_data.length + copy_len <
846 pad->partial_data.length ||
847 pad->partial_data.length + copy_len < copy_len) {
849 DEBUG(2,("check_spnego_blob_complete: integer wrap "
850 "pad->partial_data.length = %u, "
851 "copy_len = %u\n",
852 (unsigned int)pad->partial_data.length,
853 (unsigned int)copy_len ));
855 delete_partial_auth(sconn, pad);
856 return NT_STATUS_INVALID_PARAMETER;
859 DEBUG(10,("check_spnego_blob_complete: "
860 "pad->partial_data.length = %u, "
861 "pad->needed_len = %u, "
862 "copy_len = %u, "
863 "pblob->length = %u,\n",
864 (unsigned int)pad->partial_data.length,
865 (unsigned int)pad->needed_len,
866 (unsigned int)copy_len,
867 (unsigned int)pblob->length ));
869 tmp_blob = data_blob(NULL,
870 pad->partial_data.length + copy_len);
872 /* Concatenate the two (up to copy_len) bytes. */
873 memcpy(tmp_blob.data,
874 pad->partial_data.data,
875 pad->partial_data.length);
876 memcpy(tmp_blob.data + pad->partial_data.length,
877 pblob->data,
878 copy_len);
880 /* Replace the partial data. */
881 data_blob_free(&pad->partial_data);
882 pad->partial_data = tmp_blob;
883 ZERO_STRUCT(tmp_blob);
885 /* Are we done ? */
886 if (pblob->length >= pad->needed_len) {
887 /* Yes, replace pblob. */
888 data_blob_free(pblob);
889 *pblob = pad->partial_data;
890 ZERO_STRUCT(pad->partial_data);
891 delete_partial_auth(sconn, pad);
892 return NT_STATUS_OK;
895 /* Still need more data. */
896 pad->needed_len -= copy_len;
897 return NT_STATUS_MORE_PROCESSING_REQUIRED;
900 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
901 (pblob->data[0] != ASN1_CONTEXT(1))) {
902 /* Not something we can determine the
903 * length of.
905 return NT_STATUS_OK;
908 /* This is a new SPNEGO sessionsetup - see if
909 * the data given in this blob is enough.
912 data = asn1_init(NULL);
913 if (data == NULL) {
914 return NT_STATUS_NO_MEMORY;
917 asn1_load(data, *pblob);
918 if (asn1_start_tag(data, pblob->data[0])) {
919 /* asn1_start_tag checks if the given
920 length of the blob is enough to complete
921 the tag. If it returns true we know
922 there is nothing to do - the blob is
923 complete. */
924 asn1_free(data);
925 return NT_STATUS_OK;
928 if (data->nesting == NULL) {
929 /* Incorrect tag, allocation failed,
930 or reading the tag length failed.
931 Let the caller catch. */
932 asn1_free(data);
933 return NT_STATUS_OK;
936 /* Here we know asn1_start_tag() has set data->has_error to true.
937 asn1_tag_remaining() will have failed due to the given blob
938 being too short. We need to work out how short. */
940 /* Integer wrap paranoia.... */
942 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
943 data->nesting->taglen + data->nesting->start < data->nesting->start) {
945 DEBUG(2,("check_spnego_blob_complete: integer wrap "
946 "data.nesting->taglen = %u, "
947 "data.nesting->start = %u\n",
948 (unsigned int)data->nesting->taglen,
949 (unsigned int)data->nesting->start ));
951 asn1_free(data);
952 return NT_STATUS_INVALID_PARAMETER;
955 /* Total length of the needed asn1 is the tag length
956 * plus the current offset. */
958 needed_len = data->nesting->taglen + data->nesting->start;
959 asn1_free(data);
961 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
962 "pblob->length = %u\n",
963 (unsigned int)needed_len,
964 (unsigned int)pblob->length ));
966 if (needed_len <= pblob->length) {
967 /* Nothing to do - blob is complete. */
968 /* THIS SHOULD NOT HAPPEN - asn1_start_tag()
969 above should have caught this !!! */
970 DEBUG(0,("check_spnego_blob_complete: logic "
971 "error (needed_len = %u, "
972 "pblob->length = %u).\n",
973 (unsigned int)needed_len,
974 (unsigned int)pblob->length ));
975 return NT_STATUS_OK;
978 /* Refuse the blob if it's bigger than 64k. */
979 if (needed_len > 65536) {
980 DEBUG(2,("check_spnego_blob_complete: needed_len "
981 "too large (%u)\n",
982 (unsigned int)needed_len ));
983 return NT_STATUS_INVALID_PARAMETER;
986 /* We must store this blob until complete. */
987 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
988 return NT_STATUS_NO_MEMORY;
990 pad->needed_len = needed_len - pblob->length;
991 pad->partial_data = data_blob(pblob->data, pblob->length);
992 if (pad->partial_data.data == NULL) {
993 SAFE_FREE(pad);
994 return NT_STATUS_NO_MEMORY;
996 pad->smbpid = smbpid;
997 pad->vuid = vuid;
998 DLIST_ADD(sconn->smb1.pd_list, pad);
1000 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1003 /****************************************************************************
1004 Reply to a session setup command.
1005 conn POINTER CAN BE NULL HERE !
1006 ****************************************************************************/
1008 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1010 const uint8 *p;
1011 DATA_BLOB blob1;
1012 size_t bufrem;
1013 char *tmp;
1014 const char *native_os;
1015 const char *native_lanman;
1016 const char *primary_domain;
1017 const char *p2;
1018 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1019 enum remote_arch_types ra_type = get_remote_arch();
1020 int vuid = req->vuid;
1021 user_struct *vuser = NULL;
1022 NTSTATUS status = NT_STATUS_OK;
1023 uint16 smbpid = req->smbpid;
1024 struct smbd_server_connection *sconn = req->sconn;
1026 DEBUG(3,("Doing spnego session setup\n"));
1028 if (global_client_caps == 0) {
1029 global_client_caps = IVAL(req->vwv+10, 0);
1031 if (!(global_client_caps & CAP_STATUS32)) {
1032 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1037 p = req->buf;
1039 if (data_blob_len == 0) {
1040 /* an invalid request */
1041 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1042 return;
1045 bufrem = smbreq_bufrem(req, p);
1046 /* pull the spnego blob */
1047 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1049 #if 0
1050 file_save("negotiate.dat", blob1.data, blob1.length);
1051 #endif
1053 p2 = (const char *)req->buf + blob1.length;
1055 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1056 STR_TERMINATE);
1057 native_os = tmp ? tmp : "";
1059 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1060 STR_TERMINATE);
1061 native_lanman = tmp ? tmp : "";
1063 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1064 STR_TERMINATE);
1065 primary_domain = tmp ? tmp : "";
1067 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1068 native_os, native_lanman, primary_domain));
1070 if ( ra_type == RA_WIN2K ) {
1071 /* Vista sets neither the OS or lanman strings */
1073 if ( !strlen(native_os) && !strlen(native_lanman) )
1074 set_remote_arch(RA_VISTA);
1076 /* Windows 2003 doesn't set the native lanman string,
1077 but does set primary domain which is a bug I think */
1079 if ( !strlen(native_lanman) ) {
1080 ra_lanman_string( primary_domain );
1081 } else {
1082 ra_lanman_string( native_lanman );
1084 } else if ( ra_type == RA_VISTA ) {
1085 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
1086 set_remote_arch(RA_OSX);
1090 /* Did we get a valid vuid ? */
1091 if (!is_partial_auth_vuid(sconn, vuid)) {
1092 /* No, then try and see if this is an intermediate sessionsetup
1093 * for a large SPNEGO packet. */
1094 struct pending_auth_data *pad;
1095 pad = get_pending_auth_data(sconn, smbpid);
1096 if (pad) {
1097 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1098 "pending vuid %u\n",
1099 (unsigned int)pad->vuid ));
1100 vuid = pad->vuid;
1104 /* Do we have a valid vuid now ? */
1105 if (!is_partial_auth_vuid(sconn, vuid)) {
1106 /* No, start a new authentication setup. */
1107 vuid = register_initial_vuid(sconn);
1108 if (vuid == UID_FIELD_INVALID) {
1109 data_blob_free(&blob1);
1110 reply_nterror(req, nt_status_squash(
1111 NT_STATUS_INVALID_PARAMETER));
1112 return;
1116 vuser = get_partial_auth_user_struct(sconn, vuid);
1117 /* This MUST be valid. */
1118 if (!vuser) {
1119 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1122 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1123 * sessionsetup requests as the Windows limit on the security blob
1124 * field is 4k. Bug #4400. JRA.
1127 status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1128 if (!NT_STATUS_IS_OK(status)) {
1129 if (!NT_STATUS_EQUAL(status,
1130 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1131 /* Real error - kill the intermediate vuid */
1132 invalidate_vuid(sconn, vuid);
1134 data_blob_free(&blob1);
1135 reply_nterror(req, nt_status_squash(status));
1136 return;
1139 /* Handle either raw NTLMSSP or hand off the whole blob to
1140 * GENSEC. The processing at this layer is essentially
1141 * identical regardless. In particular, both rely only on the
1142 * status code (not the contents of the packet) and do not
1143 * wrap the result */
1144 if (sconn->use_gensec_hook || ntlmssp_blob_matches_magic(&blob1)) {
1145 DATA_BLOB chal;
1147 if (!vuser->auth_ntlmssp_state) {
1148 status = auth_ntlmssp_prepare(sconn->remote_address,
1149 &vuser->auth_ntlmssp_state);
1150 if (!NT_STATUS_IS_OK(status)) {
1151 /* Kill the intermediate vuid */
1152 invalidate_vuid(sconn, vuid);
1153 data_blob_free(&blob1);
1154 reply_nterror(req, nt_status_squash(status));
1155 return;
1158 gensec_want_feature(vuser->auth_ntlmssp_state->gensec_security, GENSEC_FEATURE_SESSION_KEY);
1160 if (sconn->use_gensec_hook) {
1161 status = auth_generic_start(vuser->auth_ntlmssp_state, GENSEC_OID_SPNEGO);
1162 } else {
1163 status = auth_ntlmssp_start(vuser->auth_ntlmssp_state);
1165 if (!NT_STATUS_IS_OK(status)) {
1166 /* Kill the intermediate vuid */
1167 invalidate_vuid(sconn, vuid);
1168 data_blob_free(&blob1);
1169 reply_nterror(req, nt_status_squash(status));
1170 return;
1174 status = gensec_update(vuser->auth_ntlmssp_state->gensec_security,
1175 talloc_tos(), NULL,
1176 blob1, &chal);
1178 data_blob_free(&blob1);
1180 reply_spnego_ntlmssp(req, vuid,
1181 &vuser->auth_ntlmssp_state,
1182 &chal, status, NULL, false);
1183 data_blob_free(&chal);
1184 return;
1187 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1189 /* its a negTokenTarg packet */
1191 reply_spnego_negotiate(req, vuid, blob1,
1192 &vuser->auth_ntlmssp_state);
1193 data_blob_free(&blob1);
1194 return;
1197 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1199 /* its a auth packet */
1201 reply_spnego_auth(req, vuid, blob1,
1202 &vuser->auth_ntlmssp_state);
1203 data_blob_free(&blob1);
1204 return;
1207 /* what sort of packet is this? */
1208 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1210 data_blob_free(&blob1);
1212 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1215 /****************************************************************************
1216 On new VC == 0, shutdown *all* old connections and users.
1217 It seems that only NT4.x does this. At W2K and above (XP etc.).
1218 a new session setup with VC==0 is ignored.
1219 ****************************************************************************/
1221 struct shutdown_state {
1222 const char *ip;
1223 struct messaging_context *msg_ctx;
1226 static int shutdown_other_smbds(const struct connections_key *key,
1227 const struct connections_data *crec,
1228 void *private_data)
1230 struct shutdown_state *state = (struct shutdown_state *)private_data;
1232 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
1233 server_id_str(talloc_tos(), &crec->pid), crec->addr));
1235 if (!process_exists(crec->pid)) {
1236 DEBUG(10, ("process does not exist\n"));
1237 return 0;
1240 if (procid_is_me(&crec->pid)) {
1241 DEBUG(10, ("It's me\n"));
1242 return 0;
1245 if (strcmp(state->ip, crec->addr) != 0) {
1246 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
1247 return 0;
1250 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
1251 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
1252 state->ip));
1254 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
1255 &data_blob_null);
1256 return 0;
1259 static void setup_new_vc_session(struct smbd_server_connection *sconn)
1261 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1262 "compatible we would close all old resources.\n"));
1263 #if 0
1264 conn_close_all();
1265 invalidate_all_vuids();
1266 #endif
1267 if (lp_reset_on_zero_vc()) {
1268 char *addr;
1269 struct shutdown_state state;
1271 addr = tsocket_address_inet_addr_string(
1272 sconn->remote_address, talloc_tos());
1273 if (addr == NULL) {
1274 return;
1276 state.ip = addr;
1277 state.msg_ctx = sconn->msg_ctx;
1278 connections_forall_read(shutdown_other_smbds, &state);
1279 TALLOC_FREE(addr);
1283 /****************************************************************************
1284 Reply to a session setup command.
1285 ****************************************************************************/
1287 void reply_sesssetup_and_X(struct smb_request *req)
1289 int sess_vuid;
1290 int smb_bufsize;
1291 DATA_BLOB lm_resp;
1292 DATA_BLOB nt_resp;
1293 DATA_BLOB plaintext_password;
1294 char *tmp;
1295 const char *user;
1296 fstring sub_user; /* Sanitised username for substituion */
1297 const char *domain;
1298 const char *native_os;
1299 const char *native_lanman;
1300 const char *primary_domain;
1301 struct auth_usersupplied_info *user_info = NULL;
1302 struct auth_serversupplied_info *server_info = NULL;
1303 struct auth_session_info *session_info = NULL;
1304 uint16 smb_flag2 = req->flags2;
1306 NTSTATUS nt_status;
1307 struct smbd_server_connection *sconn = req->sconn;
1309 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1310 bool signing_allowed = false;
1311 bool signing_mandatory = false;
1313 START_PROFILE(SMBsesssetupX);
1315 ZERO_STRUCT(lm_resp);
1316 ZERO_STRUCT(nt_resp);
1317 ZERO_STRUCT(plaintext_password);
1319 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1321 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
1322 signing_allowed = true;
1324 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
1325 signing_mandatory = true;
1329 * We can call srv_set_signing_negotiated() each time.
1330 * It finds out when it needs to turn into a noop
1331 * itself.
1333 srv_set_signing_negotiated(req->sconn,
1334 signing_allowed,
1335 signing_mandatory);
1337 /* a SPNEGO session setup has 12 command words, whereas a normal
1338 NT1 session setup has 13. See the cifs spec. */
1339 if (req->wct == 12 &&
1340 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1342 if (!sconn->smb1.negprot.spnego) {
1343 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1344 "at SPNEGO session setup when it was not "
1345 "negotiated.\n"));
1346 reply_nterror(req, nt_status_squash(
1347 NT_STATUS_LOGON_FAILURE));
1348 END_PROFILE(SMBsesssetupX);
1349 return;
1352 if (SVAL(req->vwv+4, 0) == 0) {
1353 setup_new_vc_session(req->sconn);
1356 reply_sesssetup_and_X_spnego(req);
1357 END_PROFILE(SMBsesssetupX);
1358 return;
1361 smb_bufsize = SVAL(req->vwv+2, 0);
1363 if (get_Protocol() < PROTOCOL_NT1) {
1364 uint16 passlen1 = SVAL(req->vwv+7, 0);
1366 /* Never do NT status codes with protocols before NT1 as we
1367 * don't get client caps. */
1368 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1370 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1371 reply_nterror(req, nt_status_squash(
1372 NT_STATUS_INVALID_PARAMETER));
1373 END_PROFILE(SMBsesssetupX);
1374 return;
1377 if (doencrypt) {
1378 lm_resp = data_blob(req->buf, passlen1);
1379 } else {
1380 plaintext_password = data_blob(req->buf, passlen1+1);
1381 /* Ensure null termination */
1382 plaintext_password.data[passlen1] = 0;
1385 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1386 req->buf + passlen1, STR_TERMINATE);
1387 user = tmp ? tmp : "";
1389 domain = "";
1391 } else {
1392 uint16 passlen1 = SVAL(req->vwv+7, 0);
1393 uint16 passlen2 = SVAL(req->vwv+8, 0);
1394 enum remote_arch_types ra_type = get_remote_arch();
1395 const uint8_t *p = req->buf;
1396 const uint8_t *save_p = req->buf;
1397 uint16 byte_count;
1400 if(global_client_caps == 0) {
1401 global_client_caps = IVAL(req->vwv+11, 0);
1403 if (!(global_client_caps & CAP_STATUS32)) {
1404 remove_from_common_flags2(
1405 FLAGS2_32_BIT_ERROR_CODES);
1408 /* client_caps is used as final determination if
1409 * client is NT or Win95. This is needed to return
1410 * the correct error codes in some circumstances.
1413 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1414 ra_type == RA_WIN95) {
1415 if(!(global_client_caps & (CAP_NT_SMBS|
1416 CAP_STATUS32))) {
1417 set_remote_arch( RA_WIN95);
1422 if (!doencrypt) {
1423 /* both Win95 and WinNT stuff up the password
1424 * lengths for non-encrypting systems. Uggh.
1426 if passlen1==24 its a win95 system, and its setting
1427 the password length incorrectly. Luckily it still
1428 works with the default code because Win95 will null
1429 terminate the password anyway
1431 if passlen1>0 and passlen2>0 then maybe its a NT box
1432 and its setting passlen2 to some random value which
1433 really stuffs things up. we need to fix that one. */
1435 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1436 passlen2 != 1) {
1437 passlen2 = 0;
1441 /* check for nasty tricks */
1442 if (passlen1 > MAX_PASS_LEN
1443 || passlen1 > smbreq_bufrem(req, p)) {
1444 reply_nterror(req, nt_status_squash(
1445 NT_STATUS_INVALID_PARAMETER));
1446 END_PROFILE(SMBsesssetupX);
1447 return;
1450 if (passlen2 > MAX_PASS_LEN
1451 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1452 reply_nterror(req, nt_status_squash(
1453 NT_STATUS_INVALID_PARAMETER));
1454 END_PROFILE(SMBsesssetupX);
1455 return;
1458 /* Save the lanman2 password and the NT md4 password. */
1460 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1461 doencrypt = False;
1464 if (doencrypt) {
1465 lm_resp = data_blob(p, passlen1);
1466 nt_resp = data_blob(p+passlen1, passlen2);
1467 } else if (lp_security() != SEC_SHARE) {
1469 * In share level we should ignore any passwords, so
1470 * only read them if we're not.
1472 char *pass = NULL;
1473 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1475 if (unic && (passlen2 == 0) && passlen1) {
1476 /* Only a ascii plaintext password was sent. */
1477 (void)srvstr_pull_talloc(talloc_tos(),
1478 req->inbuf,
1479 req->flags2,
1480 &pass,
1481 req->buf,
1482 passlen1,
1483 STR_TERMINATE|STR_ASCII);
1484 } else {
1485 (void)srvstr_pull_talloc(talloc_tos(),
1486 req->inbuf,
1487 req->flags2,
1488 &pass,
1489 req->buf,
1490 unic ? passlen2 : passlen1,
1491 STR_TERMINATE);
1493 if (!pass) {
1494 reply_nterror(req, nt_status_squash(
1495 NT_STATUS_INVALID_PARAMETER));
1496 END_PROFILE(SMBsesssetupX);
1497 return;
1499 plaintext_password = data_blob(pass, strlen(pass)+1);
1502 p += passlen1 + passlen2;
1504 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1505 STR_TERMINATE);
1506 user = tmp ? tmp : "";
1508 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1509 STR_TERMINATE);
1510 domain = tmp ? tmp : "";
1512 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1513 STR_TERMINATE);
1514 native_os = tmp ? tmp : "";
1516 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1517 STR_TERMINATE);
1518 native_lanman = tmp ? tmp : "";
1520 /* not documented or decoded by Ethereal but there is one more
1521 * string in the extra bytes which is the same as the
1522 * PrimaryDomain when using extended security. Windows NT 4
1523 * and 2003 use this string to store the native lanman string.
1524 * Windows 9x does not include a string here at all so we have
1525 * to check if we have any extra bytes left */
1527 byte_count = SVAL(req->vwv+13, 0);
1528 if ( PTR_DIFF(p, save_p) < byte_count) {
1529 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1530 STR_TERMINATE);
1531 primary_domain = tmp ? tmp : "";
1532 } else {
1533 primary_domain = talloc_strdup(talloc_tos(), "null");
1536 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1537 "PrimaryDomain=[%s]\n",
1538 domain, native_os, native_lanman, primary_domain));
1540 if ( ra_type == RA_WIN2K ) {
1541 if ( strlen(native_lanman) == 0 )
1542 ra_lanman_string( primary_domain );
1543 else
1544 ra_lanman_string( native_lanman );
1549 if (SVAL(req->vwv+4, 0) == 0) {
1550 setup_new_vc_session(req->sconn);
1553 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1554 domain, user, get_remote_machine_name()));
1556 if (*user) {
1557 if (sconn->smb1.negprot.spnego) {
1559 /* This has to be here, because this is a perfectly
1560 * valid behaviour for guest logons :-( */
1562 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1563 "at 'normal' session setup after "
1564 "negotiating spnego.\n"));
1565 reply_nterror(req, nt_status_squash(
1566 NT_STATUS_LOGON_FAILURE));
1567 END_PROFILE(SMBsesssetupX);
1568 return;
1570 fstrcpy(sub_user, user);
1571 } else {
1572 fstrcpy(sub_user, "");
1575 sub_set_smb_name(sub_user);
1577 reload_services(sconn, conn_snum_used, true);
1579 if (lp_security() == SEC_SHARE) {
1580 char *sub_user_mapped = NULL;
1581 /* In share level we should ignore any passwords */
1583 data_blob_free(&lm_resp);
1584 data_blob_free(&nt_resp);
1585 data_blob_clear_free(&plaintext_password);
1587 (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
1588 if (!sub_user_mapped) {
1589 reply_nterror(req, NT_STATUS_NO_MEMORY);
1590 END_PROFILE(SMBsesssetupX);
1591 return;
1593 fstrcpy(sub_user, sub_user_mapped);
1594 add_session_user(sconn, sub_user);
1595 add_session_workgroup(sconn, domain);
1596 /* Then force it to null for the benfit of the code below */
1597 user = "";
1600 if (!*user) {
1602 nt_status = check_guest_password(sconn->remote_address, &server_info);
1604 } else if (doencrypt) {
1605 struct auth_context *negprot_auth_context = NULL;
1606 negprot_auth_context = sconn->smb1.negprot.auth_context;
1607 if (!negprot_auth_context) {
1608 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1609 "session setup without negprot denied!\n"));
1610 reply_nterror(req, nt_status_squash(
1611 NT_STATUS_LOGON_FAILURE));
1612 END_PROFILE(SMBsesssetupX);
1613 return;
1615 nt_status = make_user_info_for_reply_enc(&user_info, user,
1616 domain,
1617 sconn->remote_address,
1618 lm_resp, nt_resp);
1619 if (NT_STATUS_IS_OK(nt_status)) {
1620 nt_status = negprot_auth_context->check_ntlm_password(
1621 negprot_auth_context,
1622 user_info,
1623 &server_info);
1625 } else {
1626 struct auth_context *plaintext_auth_context = NULL;
1628 nt_status = make_auth_context_subsystem(
1629 talloc_tos(), &plaintext_auth_context);
1631 if (NT_STATUS_IS_OK(nt_status)) {
1632 uint8_t chal[8];
1634 plaintext_auth_context->get_ntlm_challenge(
1635 plaintext_auth_context, chal);
1637 if (!make_user_info_for_reply(&user_info,
1638 user, domain,
1639 sconn->remote_address,
1640 chal,
1641 plaintext_password)) {
1642 nt_status = NT_STATUS_NO_MEMORY;
1645 if (NT_STATUS_IS_OK(nt_status)) {
1646 nt_status = plaintext_auth_context->check_ntlm_password(
1647 plaintext_auth_context,
1648 user_info,
1649 &server_info);
1651 TALLOC_FREE(plaintext_auth_context);
1656 free_user_info(&user_info);
1658 if (!NT_STATUS_IS_OK(nt_status)) {
1659 nt_status = do_map_to_guest_server_info(nt_status, &server_info,
1660 user, domain);
1663 if (!NT_STATUS_IS_OK(nt_status)) {
1664 data_blob_free(&nt_resp);
1665 data_blob_free(&lm_resp);
1666 data_blob_clear_free(&plaintext_password);
1667 reply_nterror(req, nt_status_squash(nt_status));
1668 END_PROFILE(SMBsesssetupX);
1669 return;
1672 nt_status = create_local_token(req, server_info, NULL, sub_user, &session_info);
1673 TALLOC_FREE(server_info);
1675 if (!NT_STATUS_IS_OK(nt_status)) {
1676 DEBUG(10, ("create_local_token failed: %s\n",
1677 nt_errstr(nt_status)));
1678 data_blob_free(&nt_resp);
1679 data_blob_free(&lm_resp);
1680 data_blob_clear_free(&plaintext_password);
1681 reply_nterror(req, nt_status_squash(nt_status));
1682 END_PROFILE(SMBsesssetupX);
1683 return;
1686 data_blob_clear_free(&plaintext_password);
1688 /* it's ok - setup a reply */
1689 reply_outbuf(req, 3, 0);
1690 if (get_Protocol() >= PROTOCOL_NT1) {
1691 push_signature(&req->outbuf);
1692 /* perhaps grab OS version here?? */
1695 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
1696 SSVAL(req->outbuf,smb_vwv2,1);
1699 /* register the name and uid as being validated, so further connections
1700 to a uid can get through without a password, on the same VC */
1702 if (lp_security() == SEC_SHARE) {
1703 sess_vuid = UID_FIELD_INVALID;
1704 TALLOC_FREE(session_info);
1705 } else {
1706 /* Ignore the initial vuid. */
1707 sess_vuid = register_initial_vuid(sconn);
1708 if (sess_vuid == UID_FIELD_INVALID) {
1709 data_blob_free(&nt_resp);
1710 data_blob_free(&lm_resp);
1711 reply_nterror(req, nt_status_squash(
1712 NT_STATUS_LOGON_FAILURE));
1713 END_PROFILE(SMBsesssetupX);
1714 return;
1716 /* register_existing_vuid keeps the session_info */
1717 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1718 session_info,
1719 nt_resp.data ? nt_resp : lm_resp);
1720 if (sess_vuid == UID_FIELD_INVALID) {
1721 data_blob_free(&nt_resp);
1722 data_blob_free(&lm_resp);
1723 reply_nterror(req, nt_status_squash(
1724 NT_STATUS_LOGON_FAILURE));
1725 END_PROFILE(SMBsesssetupX);
1726 return;
1729 /* current_user_info is changed on new vuid */
1730 reload_services(sconn, conn_snum_used, true);
1733 data_blob_free(&nt_resp);
1734 data_blob_free(&lm_resp);
1736 SSVAL(req->outbuf,smb_uid,sess_vuid);
1737 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1738 req->vuid = sess_vuid;
1740 if (!sconn->smb1.sessions.done_sesssetup) {
1741 sconn->smb1.sessions.max_send =
1742 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1744 sconn->smb1.sessions.done_sesssetup = true;
1746 END_PROFILE(SMBsesssetupX);
1747 chain_reply(req);
1748 return;