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