Stop get_peer_addr() and client_addr() from using global
[Samba/nascimento.git] / source3 / smbd / sesssetup.c
blob35efbc009f94f5e4b16c64ec6a135a1b5000b88d
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"
27 extern struct auth_context *negprot_global_auth_context;
28 extern bool global_encrypted_passwords_negotiated;
29 extern bool global_spnego_negotiated;
30 extern enum protocol_types Protocol;
31 extern int max_send;
33 uint32 global_client_caps = 0;
36 on a logon error possibly map the error to success if "map to guest"
37 is set approriately
39 static NTSTATUS do_map_to_guest(NTSTATUS status,
40 auth_serversupplied_info **server_info,
41 const char *user, const char *domain)
43 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
44 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
45 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
46 DEBUG(3,("No such user %s [%s] - using guest account\n",
47 user, domain));
48 status = make_server_info_guest(server_info);
52 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
53 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
54 DEBUG(3,("Registered username %s for guest access\n",
55 user));
56 status = make_server_info_guest(server_info);
60 return status;
63 /****************************************************************************
64 Add the standard 'Samba' signature to the end of the session setup.
65 ****************************************************************************/
67 static int push_signature(uint8 **outbuf)
69 char *lanman;
70 int result, tmp;
72 result = 0;
74 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
76 if (tmp == -1) return -1;
77 result += tmp;
79 if (asprintf(&lanman, "Samba %s", SAMBA_VERSION_STRING) != -1) {
80 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
81 SAFE_FREE(lanman);
83 else {
84 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
87 if (tmp == -1) return -1;
88 result += tmp;
90 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
92 if (tmp == -1) return -1;
93 result += tmp;
95 return result;
98 /****************************************************************************
99 Start the signing engine if needed. Don't fail signing here.
100 ****************************************************************************/
102 static void sessionsetup_start_signing_engine(
103 const auth_serversupplied_info *server_info,
104 const uint8 *inbuf)
106 if (!server_info->guest && !srv_signing_started()) {
107 /* We need to start the signing engine
108 * here but a W2K client sends the old
109 * "BSRSPYL " signature instead of the
110 * correct one. Subsequent packets will
111 * be correct.
113 srv_check_sign_mac((char *)inbuf, False);
117 /****************************************************************************
118 Send a security blob via a session setup reply.
119 ****************************************************************************/
121 static void reply_sesssetup_blob(connection_struct *conn,
122 struct smb_request *req,
123 DATA_BLOB blob,
124 NTSTATUS nt_status)
126 if (!NT_STATUS_IS_OK(nt_status) &&
127 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
128 reply_nterror(req, nt_status_squash(nt_status));
129 } else {
130 nt_status = nt_status_squash(nt_status);
131 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
132 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
133 SSVAL(req->outbuf, smb_vwv3, blob.length);
135 if ((message_push_blob(&req->outbuf, blob) == -1)
136 || (push_signature(&req->outbuf) == -1)) {
137 reply_nterror(req, NT_STATUS_NO_MEMORY);
141 show_msg((char *)req->outbuf);
142 send_smb(smbd_server_fd(),(char *)req->outbuf);
143 TALLOC_FREE(req->outbuf);
146 /****************************************************************************
147 Do a 'guest' logon, getting back the
148 ****************************************************************************/
150 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
152 struct auth_context *auth_context;
153 auth_usersupplied_info *user_info = NULL;
155 NTSTATUS nt_status;
156 unsigned char chal[8];
158 ZERO_STRUCT(chal);
160 DEBUG(3,("Got anonymous request\n"));
162 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context,
163 chal))) {
164 return nt_status;
167 if (!make_user_info_guest(&user_info)) {
168 (auth_context->free)(&auth_context);
169 return NT_STATUS_NO_MEMORY;
172 nt_status = auth_context->check_ntlm_password(auth_context,
173 user_info,
174 server_info);
175 (auth_context->free)(&auth_context);
176 free_user_info(&user_info);
177 return nt_status;
181 #ifdef HAVE_KRB5
183 #if 0
184 /* Experiment that failed. See "only happens with a KDC" comment below. */
185 /****************************************************************************
186 Cerate a clock skew error blob for a Windows client.
187 ****************************************************************************/
189 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
191 krb5_context context = NULL;
192 krb5_error_code kerr = 0;
193 krb5_data reply;
194 krb5_principal host_princ = NULL;
195 char *host_princ_s = NULL;
196 bool ret = False;
198 *pblob_out = data_blob_null;
200 initialize_krb5_error_table();
201 kerr = krb5_init_context(&context);
202 if (kerr) {
203 return False;
205 /* Create server principal. */
206 asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
207 if (!host_princ_s) {
208 goto out;
210 strlower_m(host_princ_s);
212 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
213 if (kerr) {
214 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
215 "for name %s: Error %s\n",
216 host_princ_s, error_message(kerr) ));
217 goto out;
220 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
221 host_princ, &reply);
222 if (kerr) {
223 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
224 "failed: Error %s\n",
225 error_message(kerr) ));
226 goto out;
229 *pblob_out = data_blob(reply.data, reply.length);
230 kerberos_free_data_contents(context,&reply);
231 ret = True;
233 out:
235 if (host_princ_s) {
236 SAFE_FREE(host_princ_s);
238 if (host_princ) {
239 krb5_free_principal(context, host_princ);
241 krb5_free_context(context);
242 return ret;
244 #endif
246 /****************************************************************************
247 Reply to a session setup spnego negotiate packet for kerberos.
248 ****************************************************************************/
250 static void reply_spnego_kerberos(connection_struct *conn,
251 struct smb_request *req,
252 DATA_BLOB *secblob,
253 uint16 vuid,
254 bool *p_invalidate_vuid)
256 TALLOC_CTX *mem_ctx;
257 DATA_BLOB ticket;
258 char *client, *p, *domain;
259 fstring netbios_domain_name;
260 struct passwd *pw;
261 fstring user;
262 int sess_vuid = req->vuid;
263 NTSTATUS ret = NT_STATUS_OK;
264 PAC_DATA *pac_data;
265 DATA_BLOB ap_rep, ap_rep_wrapped, response;
266 auth_serversupplied_info *server_info = NULL;
267 DATA_BLOB session_key = data_blob_null;
268 uint8 tok_id[2];
269 DATA_BLOB nullblob = data_blob_null;
270 fstring real_username;
271 bool map_domainuser_to_guest = False;
272 bool username_was_mapped;
273 PAC_LOGON_INFO *logon_info = NULL;
275 ZERO_STRUCT(ticket);
276 ZERO_STRUCT(pac_data);
277 ZERO_STRUCT(ap_rep);
278 ZERO_STRUCT(ap_rep_wrapped);
279 ZERO_STRUCT(response);
281 /* Normally we will always invalidate the intermediate vuid. */
282 *p_invalidate_vuid = True;
284 mem_ctx = talloc_init("reply_spnego_kerberos");
285 if (mem_ctx == NULL) {
286 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
287 return;
290 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
291 talloc_destroy(mem_ctx);
292 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
293 return;
296 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
297 &client, &pac_data, &ap_rep,
298 &session_key, True);
300 data_blob_free(&ticket);
302 if (!NT_STATUS_IS_OK(ret)) {
303 #if 0
304 /* Experiment that failed.
305 * See "only happens with a KDC" comment below. */
307 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
310 * Windows in this case returns
311 * NT_STATUS_MORE_PROCESSING_REQUIRED
312 * with a negTokenTarg blob containing an krb5_error
313 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
314 * The client then fixes its clock and continues rather
315 * than giving an error. JRA.
316 * -- Looks like this only happens with a KDC. JRA.
319 bool ok = make_krb5_skew_error(&ap_rep);
320 if (!ok) {
321 talloc_destroy(mem_ctx);
322 return ERROR_NT(nt_status_squash(
323 NT_STATUS_LOGON_FAILURE));
325 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
326 TOK_ID_KRB_ERROR);
327 response = spnego_gen_auth_response(&ap_rep_wrapped,
328 ret, OID_KERBEROS5_OLD);
329 reply_sesssetup_blob(conn, inbuf, outbuf, response,
330 NT_STATUS_MORE_PROCESSING_REQUIRED);
333 * In this one case we don't invalidate the
334 * intermediate vuid as we're expecting the client
335 * to re-use it for the next sessionsetupX packet. JRA.
338 *p_invalidate_vuid = False;
340 data_blob_free(&ap_rep);
341 data_blob_free(&ap_rep_wrapped);
342 data_blob_free(&response);
343 talloc_destroy(mem_ctx);
344 return -1; /* already replied */
346 #else
347 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
348 ret = NT_STATUS_LOGON_FAILURE;
350 #endif
351 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
352 nt_errstr(ret)));
353 talloc_destroy(mem_ctx);
354 reply_nterror(req, nt_status_squash(ret));
355 return;
358 DEBUG(3,("Ticket name is [%s]\n", client));
360 p = strchr_m(client, '@');
361 if (!p) {
362 DEBUG(3,("Doesn't look like a valid principal\n"));
363 data_blob_free(&ap_rep);
364 data_blob_free(&session_key);
365 SAFE_FREE(client);
366 talloc_destroy(mem_ctx);
367 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
368 return;
371 *p = 0;
373 /* save the PAC data if we have it */
375 if (pac_data) {
376 logon_info = get_logon_info_from_pac(pac_data);
377 if (logon_info) {
378 netsamlogon_cache_store( client, &logon_info->info3 );
382 if (!strequal(p+1, lp_realm())) {
383 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
384 if (!lp_allow_trusted_domains()) {
385 data_blob_free(&ap_rep);
386 data_blob_free(&session_key);
387 SAFE_FREE(client);
388 talloc_destroy(mem_ctx);
389 reply_nterror(req, nt_status_squash(
390 NT_STATUS_LOGON_FAILURE));
391 return;
395 /* this gives a fully qualified user name (ie. with full realm).
396 that leads to very long usernames, but what else can we do? */
398 domain = p+1;
400 if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) {
401 unistr2_to_ascii(netbios_domain_name,
402 &logon_info->info3.uni_logon_dom,
403 sizeof(netbios_domain_name));
404 domain = netbios_domain_name;
405 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
407 } else {
409 /* If we have winbind running, we can (and must) shorten the
410 username by using the short netbios name. Otherwise we will
411 have inconsistent user names. With Kerberos, we get the
412 fully qualified realm, with ntlmssp we get the short
413 name. And even w2k3 does use ntlmssp if you for example
414 connect to an ip address. */
416 struct winbindd_request wb_request;
417 struct winbindd_response wb_response;
418 NSS_STATUS wb_result;
420 ZERO_STRUCT(wb_request);
421 ZERO_STRUCT(wb_response);
423 DEBUG(10, ("Mapping [%s] to short name\n", domain));
425 fstrcpy(wb_request.domain_name, domain);
427 wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
428 &wb_request, &wb_response);
430 if (wb_result == NSS_STATUS_SUCCESS) {
432 fstrcpy(netbios_domain_name,
433 wb_response.data.domain_info.name);
434 domain = netbios_domain_name;
436 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
437 } else {
438 DEBUG(3, ("Could not find short name -- winbind "
439 "not running?\n"));
443 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
445 /* lookup the passwd struct, create a new user if necessary */
447 username_was_mapped = map_username( user );
449 pw = smb_getpwnam( mem_ctx, user, real_username, True );
451 if (pw) {
452 /* if a real user check pam account restrictions */
453 /* only really perfomed if "obey pam restriction" is true */
454 /* do this before an eventual mappign to guest occurs */
455 ret = smb_pam_accountcheck(pw->pw_name);
456 if ( !NT_STATUS_IS_OK(ret)) {
457 DEBUG(1,("PAM account restriction "
458 "prevents user login\n"));
459 data_blob_free(&ap_rep);
460 data_blob_free(&session_key);
461 TALLOC_FREE(mem_ctx);
462 reply_nterror(req, nt_status_squash(ret));
463 return;
467 if (!pw) {
469 /* this was originally the behavior of Samba 2.2, if a user
470 did not have a local uid but has been authenticated, then
471 map them to a guest account */
473 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
474 map_domainuser_to_guest = True;
475 fstrcpy(user,lp_guestaccount());
476 pw = smb_getpwnam( mem_ctx, user, real_username, True );
479 /* extra sanity check that the guest account is valid */
481 if ( !pw ) {
482 DEBUG(1,("Username %s is invalid on this system\n",
483 user));
484 SAFE_FREE(client);
485 data_blob_free(&ap_rep);
486 data_blob_free(&session_key);
487 TALLOC_FREE(mem_ctx);
488 reply_nterror(req, nt_status_squash(
489 NT_STATUS_LOGON_FAILURE));
490 return;
494 /* setup the string used by %U */
496 sub_set_smb_name( real_username );
497 reload_services(True);
499 if ( map_domainuser_to_guest ) {
500 make_server_info_guest(&server_info);
501 } else if (logon_info) {
502 /* pass the unmapped username here since map_username()
503 will be called again from inside make_server_info_info3() */
505 ret = make_server_info_info3(mem_ctx, client, domain,
506 &server_info, &logon_info->info3);
507 if ( !NT_STATUS_IS_OK(ret) ) {
508 DEBUG(1,("make_server_info_info3 failed: %s!\n",
509 nt_errstr(ret)));
510 SAFE_FREE(client);
511 data_blob_free(&ap_rep);
512 data_blob_free(&session_key);
513 TALLOC_FREE(mem_ctx);
514 reply_nterror(req, nt_status_squash(ret));
515 return;
518 } else {
519 ret = make_server_info_pw(&server_info, real_username, pw);
521 if ( !NT_STATUS_IS_OK(ret) ) {
522 DEBUG(1,("make_server_info_pw failed: %s!\n",
523 nt_errstr(ret)));
524 SAFE_FREE(client);
525 data_blob_free(&ap_rep);
526 data_blob_free(&session_key);
527 TALLOC_FREE(mem_ctx);
528 reply_nterror(req, nt_status_squash(ret));
529 return;
532 /* make_server_info_pw does not set the domain. Without this
533 * we end up with the local netbios name in substitutions for
534 * %D. */
536 if (server_info->sam_account != NULL) {
537 pdb_set_domain(server_info->sam_account,
538 domain, PDB_SET);
542 server_info->was_mapped |= username_was_mapped;
544 /* we need to build the token for the user. make_server_info_guest()
545 already does this */
547 if ( !server_info->ptok ) {
548 ret = create_local_token( server_info );
549 if ( !NT_STATUS_IS_OK(ret) ) {
550 SAFE_FREE(client);
551 data_blob_free(&ap_rep);
552 data_blob_free(&session_key);
553 TALLOC_FREE( mem_ctx );
554 TALLOC_FREE( server_info );
555 reply_nterror(req, nt_status_squash(ret));
556 return;
560 /* register_existing_vuid keeps the server info */
561 /* register_existing_vuid takes ownership of session_key on success,
562 * no need to free after this on success. A better interface would copy
563 * it.... */
565 if (!is_partial_auth_vuid(sess_vuid)) {
566 sess_vuid = register_initial_vuid();
568 sess_vuid = register_existing_vuid(sess_vuid,
569 server_info,
570 session_key,
571 nullblob,
572 client);
574 SAFE_FREE(client);
576 reply_outbuf(req, 4, 0);
577 SSVAL(req->outbuf,smb_uid,sess_vuid);
579 if (sess_vuid == UID_FIELD_INVALID ) {
580 ret = NT_STATUS_LOGON_FAILURE;
581 data_blob_free(&session_key);
582 } else {
583 /* current_user_info is changed on new vuid */
584 reload_services( True );
586 SSVAL(req->outbuf, smb_vwv3, 0);
588 if (server_info->guest) {
589 SSVAL(req->outbuf,smb_vwv2,1);
592 SSVAL(req->outbuf, smb_uid, sess_vuid);
594 sessionsetup_start_signing_engine(server_info, req->inbuf);
595 /* Successful logon. Keep this vuid. */
596 *p_invalidate_vuid = False;
599 /* wrap that up in a nice GSS-API wrapping */
600 if (NT_STATUS_IS_OK(ret)) {
601 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
602 TOK_ID_KRB_AP_REP);
603 } else {
604 ap_rep_wrapped = data_blob_null;
606 response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
607 OID_KERBEROS5_OLD);
608 reply_sesssetup_blob(conn, req, response, ret);
610 data_blob_free(&ap_rep);
611 data_blob_free(&ap_rep_wrapped);
612 data_blob_free(&response);
613 TALLOC_FREE(mem_ctx);
616 #endif
618 /****************************************************************************
619 Send a session setup reply, wrapped in SPNEGO.
620 Get vuid and check first.
621 End the NTLMSSP exchange context if we are OK/complete fail
622 This should be split into two functions, one to handle each
623 leg of the NTLM auth steps.
624 ***************************************************************************/
626 static void reply_spnego_ntlmssp(connection_struct *conn,
627 struct smb_request *req,
628 uint16 vuid,
629 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
630 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
631 bool wrap)
633 DATA_BLOB response;
634 struct auth_serversupplied_info *server_info = NULL;
636 if (NT_STATUS_IS_OK(nt_status)) {
637 server_info = (*auth_ntlmssp_state)->server_info;
638 } else {
639 nt_status = do_map_to_guest(nt_status,
640 &server_info,
641 (*auth_ntlmssp_state)->ntlmssp_state->user,
642 (*auth_ntlmssp_state)->ntlmssp_state->domain);
645 reply_outbuf(req, 4, 0);
647 SSVAL(req->outbuf, smb_uid, vuid);
649 if (NT_STATUS_IS_OK(nt_status)) {
650 DATA_BLOB nullblob = data_blob_null;
651 DATA_BLOB session_key =
652 data_blob(
653 (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
654 (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
656 if (!is_partial_auth_vuid(vuid)) {
657 data_blob_free(&session_key);
658 nt_status = NT_STATUS_LOGON_FAILURE;
659 goto out;
661 /* register_existing_vuid keeps the server info */
662 if (register_existing_vuid(vuid,
663 server_info,
664 session_key, nullblob,
665 (*auth_ntlmssp_state)->ntlmssp_state->user) !=
666 vuid) {
667 data_blob_free(&session_key);
668 nt_status = NT_STATUS_LOGON_FAILURE;
669 goto out;
672 (*auth_ntlmssp_state)->server_info = NULL;
674 /* current_user_info is changed on new vuid */
675 reload_services( True );
677 SSVAL(req->outbuf, smb_vwv3, 0);
679 if (server_info->guest) {
680 SSVAL(req->outbuf,smb_vwv2,1);
683 sessionsetup_start_signing_engine(server_info,
684 (uint8 *)req->inbuf);
687 out:
689 if (wrap) {
690 response = spnego_gen_auth_response(ntlmssp_blob,
691 nt_status, OID_NTLMSSP);
692 } else {
693 response = *ntlmssp_blob;
696 reply_sesssetup_blob(conn, req, response, nt_status);
697 if (wrap) {
698 data_blob_free(&response);
701 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
702 and the other end, that we are not finished yet. */
704 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
705 /* NB. This is *NOT* an error case. JRA */
706 auth_ntlmssp_end(auth_ntlmssp_state);
707 if (!NT_STATUS_IS_OK(nt_status)) {
708 /* Kill the intermediate vuid */
709 invalidate_vuid(vuid);
714 /****************************************************************************
715 Is this a krb5 mechanism ?
716 ****************************************************************************/
718 NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out,
719 bool *p_is_krb5)
721 char *OIDs[ASN1_MAX_OIDS];
722 int i;
724 *p_is_krb5 = False;
726 /* parse out the OIDs and the first sec blob */
727 if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
728 return NT_STATUS_LOGON_FAILURE;
731 /* only look at the first OID for determining the mechToken --
732 according to RFC2478, we should choose the one we want
733 and renegotiate, but i smell a client bug here..
735 Problem observed when connecting to a member (samba box)
736 of an AD domain as a user in a Samba domain. Samba member
737 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
738 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
739 NTLMSSP mechtoken. --jerry */
741 #ifdef HAVE_KRB5
742 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
743 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
744 *p_is_krb5 = True;
746 #endif
748 for (i=0;OIDs[i];i++) {
749 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
750 free(OIDs[i]);
752 return NT_STATUS_OK;
755 /****************************************************************************
756 Reply to a session setup spnego negotiate packet.
757 ****************************************************************************/
759 static void reply_spnego_negotiate(connection_struct *conn,
760 struct smb_request *req,
761 uint16 vuid,
762 DATA_BLOB blob1,
763 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
765 DATA_BLOB secblob;
766 DATA_BLOB chal;
767 bool got_kerberos_mechanism = False;
768 NTSTATUS status;
770 status = parse_spnego_mechanisms(blob1, &secblob,
771 &got_kerberos_mechanism);
772 if (!NT_STATUS_IS_OK(status)) {
773 /* Kill the intermediate vuid */
774 invalidate_vuid(vuid);
775 reply_nterror(req, nt_status_squash(status));
776 return;
779 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
780 (unsigned long)secblob.length));
782 #ifdef HAVE_KRB5
783 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) ||
784 lp_use_kerberos_keytab()) ) {
785 bool destroy_vuid = True;
786 reply_spnego_kerberos(conn, req, &secblob, vuid,
787 &destroy_vuid);
788 data_blob_free(&secblob);
789 if (destroy_vuid) {
790 /* Kill the intermediate vuid */
791 invalidate_vuid(vuid);
793 return;
795 #endif
797 if (*auth_ntlmssp_state) {
798 auth_ntlmssp_end(auth_ntlmssp_state);
801 status = auth_ntlmssp_start(auth_ntlmssp_state);
802 if (!NT_STATUS_IS_OK(status)) {
803 /* Kill the intermediate vuid */
804 invalidate_vuid(vuid);
805 reply_nterror(req, nt_status_squash(status));
806 return;
809 status = auth_ntlmssp_update(*auth_ntlmssp_state,
810 secblob, &chal);
812 data_blob_free(&secblob);
814 reply_spnego_ntlmssp(conn, req, vuid, auth_ntlmssp_state,
815 &chal, status, True);
817 data_blob_free(&chal);
819 /* already replied */
820 return;
823 /****************************************************************************
824 Reply to a session setup spnego auth packet.
825 ****************************************************************************/
827 static void reply_spnego_auth(connection_struct *conn,
828 struct smb_request *req,
829 uint16 vuid,
830 DATA_BLOB blob1,
831 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
833 DATA_BLOB auth = data_blob_null;
834 DATA_BLOB auth_reply = data_blob_null;
835 DATA_BLOB secblob = data_blob_null;
836 NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
838 if (!spnego_parse_auth(blob1, &auth)) {
839 #if 0
840 file_save("auth.dat", blob1.data, blob1.length);
841 #endif
842 /* Kill the intermediate vuid */
843 invalidate_vuid(vuid);
845 reply_nterror(req, nt_status_squash(
846 NT_STATUS_INVALID_PARAMETER));
847 return;
850 if (auth.data[0] == ASN1_APPLICATION(0)) {
851 /* Might be a second negTokenTarg packet */
853 bool got_krb5_mechanism = False;
854 status = parse_spnego_mechanisms(auth, &secblob,
855 &got_krb5_mechanism);
856 if (NT_STATUS_IS_OK(status)) {
857 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
858 (unsigned long)secblob.length));
859 #ifdef HAVE_KRB5
860 if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) ||
861 lp_use_kerberos_keytab()) ) {
862 bool destroy_vuid = True;
863 reply_spnego_kerberos(conn, req, &secblob,
864 vuid, &destroy_vuid);
865 data_blob_free(&secblob);
866 data_blob_free(&auth);
867 if (destroy_vuid) {
868 /* Kill the intermediate vuid */
869 invalidate_vuid(vuid);
871 return;
873 #endif
877 /* If we get here it wasn't a negTokenTarg auth packet. */
878 data_blob_free(&secblob);
880 if (!*auth_ntlmssp_state) {
881 /* Kill the intermediate vuid */
882 invalidate_vuid(vuid);
884 /* auth before negotiatiate? */
885 reply_nterror(req, nt_status_squash(
886 NT_STATUS_INVALID_PARAMETER));
887 return;
890 status = auth_ntlmssp_update(*auth_ntlmssp_state,
891 auth, &auth_reply);
893 data_blob_free(&auth);
895 reply_spnego_ntlmssp(conn, req, vuid,
896 auth_ntlmssp_state,
897 &auth_reply, status, True);
899 data_blob_free(&auth_reply);
901 /* and tell smbd that we have already replied to this packet */
902 return;
905 /****************************************************************************
906 List to store partial SPNEGO auth fragments.
907 ****************************************************************************/
909 static struct pending_auth_data *pd_list;
911 /****************************************************************************
912 Delete an entry on the list.
913 ****************************************************************************/
915 static void delete_partial_auth(struct pending_auth_data *pad)
917 if (!pad) {
918 return;
920 DLIST_REMOVE(pd_list, pad);
921 data_blob_free(&pad->partial_data);
922 SAFE_FREE(pad);
925 /****************************************************************************
926 Search for a partial SPNEGO auth fragment matching an smbpid.
927 ****************************************************************************/
929 static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
931 struct pending_auth_data *pad;
933 for (pad = pd_list; pad; pad = pad->next) {
934 if (pad->smbpid == smbpid) {
935 break;
938 return pad;
941 /****************************************************************************
942 Check the size of an SPNEGO blob. If we need more return
943 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
944 the blob to be more than 64k.
945 ****************************************************************************/
947 static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid,
948 DATA_BLOB *pblob)
950 struct pending_auth_data *pad = NULL;
951 ASN1_DATA data;
952 size_t needed_len = 0;
954 pad = get_pending_auth_data(smbpid);
956 /* Ensure we have some data. */
957 if (pblob->length == 0) {
958 /* Caller can cope. */
959 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
960 delete_partial_auth(pad);
961 return NT_STATUS_OK;
964 /* Were we waiting for more data ? */
965 if (pad) {
966 DATA_BLOB tmp_blob;
967 size_t copy_len = MIN(65536, pblob->length);
969 /* Integer wrap paranoia.... */
971 if (pad->partial_data.length + copy_len <
972 pad->partial_data.length ||
973 pad->partial_data.length + copy_len < copy_len) {
975 DEBUG(2,("check_spnego_blob_complete: integer wrap "
976 "pad->partial_data.length = %u, "
977 "copy_len = %u\n",
978 (unsigned int)pad->partial_data.length,
979 (unsigned int)copy_len ));
981 delete_partial_auth(pad);
982 return NT_STATUS_INVALID_PARAMETER;
985 DEBUG(10,("check_spnego_blob_complete: "
986 "pad->partial_data.length = %u, "
987 "pad->needed_len = %u, "
988 "copy_len = %u, "
989 "pblob->length = %u,\n",
990 (unsigned int)pad->partial_data.length,
991 (unsigned int)pad->needed_len,
992 (unsigned int)copy_len,
993 (unsigned int)pblob->length ));
995 tmp_blob = data_blob(NULL,
996 pad->partial_data.length + copy_len);
998 /* Concatenate the two (up to copy_len) bytes. */
999 memcpy(tmp_blob.data,
1000 pad->partial_data.data,
1001 pad->partial_data.length);
1002 memcpy(tmp_blob.data + pad->partial_data.length,
1003 pblob->data,
1004 copy_len);
1006 /* Replace the partial data. */
1007 data_blob_free(&pad->partial_data);
1008 pad->partial_data = tmp_blob;
1009 ZERO_STRUCT(tmp_blob);
1011 /* Are we done ? */
1012 if (pblob->length >= pad->needed_len) {
1013 /* Yes, replace pblob. */
1014 data_blob_free(pblob);
1015 *pblob = pad->partial_data;
1016 ZERO_STRUCT(pad->partial_data);
1017 delete_partial_auth(pad);
1018 return NT_STATUS_OK;
1021 /* Still need more data. */
1022 pad->needed_len -= copy_len;
1023 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1026 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
1027 (pblob->data[0] != ASN1_CONTEXT(1))) {
1028 /* Not something we can determine the
1029 * length of.
1031 return NT_STATUS_OK;
1034 /* This is a new SPNEGO sessionsetup - see if
1035 * the data given in this blob is enough.
1038 asn1_load(&data, *pblob);
1039 asn1_start_tag(&data, pblob->data[0]);
1040 if (data.has_error || data.nesting == NULL) {
1041 asn1_free(&data);
1042 /* Let caller catch. */
1043 return NT_STATUS_OK;
1046 /* Integer wrap paranoia.... */
1048 if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
1049 data.nesting->taglen + data.nesting->start < data.nesting->start) {
1051 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1052 "data.nesting->taglen = %u, "
1053 "data.nesting->start = %u\n",
1054 (unsigned int)data.nesting->taglen,
1055 (unsigned int)data.nesting->start ));
1057 asn1_free(&data);
1058 return NT_STATUS_INVALID_PARAMETER;
1061 /* Total length of the needed asn1 is the tag length
1062 * plus the current offset. */
1064 needed_len = data.nesting->taglen + data.nesting->start;
1065 asn1_free(&data);
1067 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1068 "pblob->length = %u\n",
1069 (unsigned int)needed_len,
1070 (unsigned int)pblob->length ));
1072 if (needed_len <= pblob->length) {
1073 /* Nothing to do - blob is complete. */
1074 return NT_STATUS_OK;
1077 /* Refuse the blob if it's bigger than 64k. */
1078 if (needed_len > 65536) {
1079 DEBUG(2,("check_spnego_blob_complete: needed_len "
1080 "too large (%u)\n",
1081 (unsigned int)needed_len ));
1082 return NT_STATUS_INVALID_PARAMETER;
1085 /* We must store this blob until complete. */
1086 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1087 return NT_STATUS_NO_MEMORY;
1089 pad->needed_len = needed_len - pblob->length;
1090 pad->partial_data = data_blob(pblob->data, pblob->length);
1091 if (pad->partial_data.data == NULL) {
1092 SAFE_FREE(pad);
1093 return NT_STATUS_NO_MEMORY;
1095 pad->smbpid = smbpid;
1096 pad->vuid = vuid;
1097 DLIST_ADD(pd_list, pad);
1099 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1102 /****************************************************************************
1103 Reply to a session setup command.
1104 conn POINTER CAN BE NULL HERE !
1105 ****************************************************************************/
1107 static void reply_sesssetup_and_X_spnego(connection_struct *conn,
1108 struct smb_request *req)
1110 uint8 *p;
1111 DATA_BLOB blob1;
1112 size_t bufrem;
1113 fstring native_os, native_lanman, primary_domain;
1114 const char *p2;
1115 uint16 data_blob_len = SVAL(req->inbuf, smb_vwv7);
1116 enum remote_arch_types ra_type = get_remote_arch();
1117 int vuid = SVAL(req->inbuf,smb_uid);
1118 user_struct *vuser = NULL;
1119 NTSTATUS status = NT_STATUS_OK;
1120 uint16 smbpid = req->smbpid;
1121 uint16 smb_flag2 = req->flags2;
1123 DEBUG(3,("Doing spnego session setup\n"));
1125 if (global_client_caps == 0) {
1126 global_client_caps = IVAL(req->inbuf,smb_vwv10);
1128 if (!(global_client_caps & CAP_STATUS32)) {
1129 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1134 p = (uint8 *)smb_buf(req->inbuf);
1136 if (data_blob_len == 0) {
1137 /* an invalid request */
1138 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1139 return;
1142 bufrem = smb_bufrem(req->inbuf, p);
1143 /* pull the spnego blob */
1144 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1146 #if 0
1147 file_save("negotiate.dat", blob1.data, blob1.length);
1148 #endif
1150 p2 = (char *)req->inbuf + smb_vwv13 + data_blob_len;
1151 p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_os, p2,
1152 sizeof(native_os), STR_TERMINATE);
1153 p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_lanman, p2,
1154 sizeof(native_lanman), STR_TERMINATE);
1155 p2 += srvstr_pull_buf(req->inbuf, smb_flag2, primary_domain, p2,
1156 sizeof(primary_domain), STR_TERMINATE);
1157 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1158 native_os, native_lanman, primary_domain));
1160 if ( ra_type == RA_WIN2K ) {
1161 /* Vista sets neither the OS or lanman strings */
1163 if ( !strlen(native_os) && !strlen(native_lanman) )
1164 set_remote_arch(RA_VISTA);
1166 /* Windows 2003 doesn't set the native lanman string,
1167 but does set primary domain which is a bug I think */
1169 if ( !strlen(native_lanman) ) {
1170 ra_lanman_string( primary_domain );
1171 } else {
1172 ra_lanman_string( native_lanman );
1176 /* Did we get a valid vuid ? */
1177 if (!is_partial_auth_vuid(vuid)) {
1178 /* No, then try and see if this is an intermediate sessionsetup
1179 * for a large SPNEGO packet. */
1180 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
1181 if (pad) {
1182 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1183 "pending vuid %u\n",
1184 (unsigned int)pad->vuid ));
1185 vuid = pad->vuid;
1189 /* Do we have a valid vuid now ? */
1190 if (!is_partial_auth_vuid(vuid)) {
1191 /* No, start a new authentication setup. */
1192 vuid = register_initial_vuid();
1193 if (vuid == UID_FIELD_INVALID) {
1194 data_blob_free(&blob1);
1195 reply_nterror(req, nt_status_squash(
1196 NT_STATUS_INVALID_PARAMETER));
1197 return;
1201 vuser = get_partial_auth_user_struct(vuid);
1202 /* This MUST be valid. */
1203 if (!vuser) {
1204 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1207 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1208 * sessionsetup requests as the Windows limit on the security blob
1209 * field is 4k. Bug #4400. JRA.
1212 status = check_spnego_blob_complete(smbpid, vuid, &blob1);
1213 if (!NT_STATUS_IS_OK(status)) {
1214 if (!NT_STATUS_EQUAL(status,
1215 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1216 /* Real error - kill the intermediate vuid */
1217 invalidate_vuid(vuid);
1219 data_blob_free(&blob1);
1220 reply_nterror(req, nt_status_squash(status));
1221 return;
1224 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1226 /* its a negTokenTarg packet */
1228 reply_spnego_negotiate(conn, req, vuid, blob1,
1229 &vuser->auth_ntlmssp_state);
1230 data_blob_free(&blob1);
1231 return;
1234 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1236 /* its a auth packet */
1238 reply_spnego_auth(conn, req, vuid, blob1,
1239 &vuser->auth_ntlmssp_state);
1240 data_blob_free(&blob1);
1241 return;
1244 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1245 DATA_BLOB chal;
1247 if (!vuser->auth_ntlmssp_state) {
1248 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1249 if (!NT_STATUS_IS_OK(status)) {
1250 /* Kill the intermediate vuid */
1251 invalidate_vuid(vuid);
1252 data_blob_free(&blob1);
1253 reply_nterror(req, nt_status_squash(status));
1254 return;
1258 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1259 blob1, &chal);
1261 data_blob_free(&blob1);
1263 reply_spnego_ntlmssp(conn, req, vuid,
1264 &vuser->auth_ntlmssp_state,
1265 &chal, status, False);
1266 data_blob_free(&chal);
1267 return;
1270 /* what sort of packet is this? */
1271 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1273 data_blob_free(&blob1);
1275 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1278 /****************************************************************************
1279 On new VC == 0, shutdown *all* old connections and users.
1280 It seems that only NT4.x does this. At W2K and above (XP etc.).
1281 a new session setup with VC==0 is ignored.
1282 ****************************************************************************/
1284 static int shutdown_other_smbds(struct db_record *rec,
1285 const struct connections_key *key,
1286 const struct connections_data *crec,
1287 void *private_data)
1289 const char *ip = (const char *)private_data;
1291 if (!process_exists(crec->pid)) {
1292 return 0;
1295 if (procid_is_me(&crec->pid)) {
1296 return 0;
1299 if (strcmp(ip, crec->addr) != 0) {
1300 return 0;
1303 messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1304 &data_blob_null);
1305 return 0;
1308 static void setup_new_vc_session(void)
1310 char addr[INET6_ADDRSTRLEN];
1312 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1313 "compatible we would close all old resources.\n"));
1314 #if 0
1315 conn_close_all();
1316 invalidate_all_vuids();
1317 #endif
1318 if (lp_reset_on_zero_vc()) {
1319 connections_forall(shutdown_other_smbds,
1320 CONST_DISCARD(void *,client_addr(addr)));
1324 /****************************************************************************
1325 Reply to a session setup command.
1326 ****************************************************************************/
1328 void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req)
1330 int sess_vuid;
1331 int smb_bufsize;
1332 DATA_BLOB lm_resp;
1333 DATA_BLOB nt_resp;
1334 DATA_BLOB plaintext_password;
1335 fstring user;
1336 fstring sub_user; /* Sainitised username for substituion */
1337 fstring domain;
1338 fstring native_os;
1339 fstring native_lanman;
1340 fstring primary_domain;
1341 static bool done_sesssetup = False;
1342 auth_usersupplied_info *user_info = NULL;
1343 auth_serversupplied_info *server_info = NULL;
1344 uint16 smb_flag2 = req->flags2;
1346 NTSTATUS nt_status;
1348 bool doencrypt = global_encrypted_passwords_negotiated;
1350 DATA_BLOB session_key;
1352 START_PROFILE(SMBsesssetupX);
1354 ZERO_STRUCT(lm_resp);
1355 ZERO_STRUCT(nt_resp);
1356 ZERO_STRUCT(plaintext_password);
1358 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1360 /* a SPNEGO session setup has 12 command words, whereas a normal
1361 NT1 session setup has 13. See the cifs spec. */
1362 if (req->wct == 12 &&
1363 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1365 if (!global_spnego_negotiated) {
1366 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1367 "at SPNEGO session setup when it was not "
1368 "negotiated.\n"));
1369 reply_nterror(req, nt_status_squash(
1370 NT_STATUS_LOGON_FAILURE));
1371 END_PROFILE(SMBsesssetupX);
1372 return;
1375 if (SVAL(req->inbuf,smb_vwv4) == 0) {
1376 setup_new_vc_session();
1379 reply_sesssetup_and_X_spnego(conn, req);
1380 END_PROFILE(SMBsesssetupX);
1381 return;
1384 smb_bufsize = SVAL(req->inbuf,smb_vwv2);
1386 if (Protocol < PROTOCOL_NT1) {
1387 uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
1389 /* Never do NT status codes with protocols before NT1 as we
1390 * don't get client caps. */
1391 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1393 if ((passlen1 > MAX_PASS_LEN)
1394 || (passlen1 > smb_bufrem(req->inbuf,
1395 smb_buf(req->inbuf)))) {
1396 reply_nterror(req, nt_status_squash(
1397 NT_STATUS_INVALID_PARAMETER));
1398 END_PROFILE(SMBsesssetupX);
1399 return;
1402 if (doencrypt) {
1403 lm_resp = data_blob(smb_buf(req->inbuf), passlen1);
1404 } else {
1405 plaintext_password = data_blob(smb_buf(req->inbuf),
1406 passlen1+1);
1407 /* Ensure null termination */
1408 plaintext_password.data[passlen1] = 0;
1411 srvstr_pull_buf(req->inbuf, req->flags2, user,
1412 smb_buf(req->inbuf)+passlen1, sizeof(user),
1413 STR_TERMINATE);
1414 *domain = 0;
1416 } else {
1417 uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
1418 uint16 passlen2 = SVAL(req->inbuf,smb_vwv8);
1419 enum remote_arch_types ra_type = get_remote_arch();
1420 char *p = smb_buf(req->inbuf);
1421 char *save_p = smb_buf(req->inbuf);
1422 uint16 byte_count;
1425 if(global_client_caps == 0) {
1426 global_client_caps = IVAL(req->inbuf,smb_vwv11);
1428 if (!(global_client_caps & CAP_STATUS32)) {
1429 remove_from_common_flags2(
1430 FLAGS2_32_BIT_ERROR_CODES);
1433 /* client_caps is used as final determination if
1434 * client is NT or Win95. This is needed to return
1435 * the correct error codes in some circumstances.
1438 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1439 ra_type == RA_WIN95) {
1440 if(!(global_client_caps & (CAP_NT_SMBS|
1441 CAP_STATUS32))) {
1442 set_remote_arch( RA_WIN95);
1447 if (!doencrypt) {
1448 /* both Win95 and WinNT stuff up the password
1449 * lengths for non-encrypting systems. Uggh.
1451 if passlen1==24 its a win95 system, and its setting
1452 the password length incorrectly. Luckily it still
1453 works with the default code because Win95 will null
1454 terminate the password anyway
1456 if passlen1>0 and passlen2>0 then maybe its a NT box
1457 and its setting passlen2 to some random value which
1458 really stuffs things up. we need to fix that one. */
1460 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1461 passlen2 != 1) {
1462 passlen2 = 0;
1466 /* check for nasty tricks */
1467 if (passlen1 > MAX_PASS_LEN
1468 || passlen1 > smb_bufrem(req->inbuf, p)) {
1469 reply_nterror(req, nt_status_squash(
1470 NT_STATUS_INVALID_PARAMETER));
1471 END_PROFILE(SMBsesssetupX);
1472 return;
1475 if (passlen2 > MAX_PASS_LEN
1476 || passlen2 > smb_bufrem(req->inbuf, p+passlen1)) {
1477 reply_nterror(req, nt_status_squash(
1478 NT_STATUS_INVALID_PARAMETER));
1479 END_PROFILE(SMBsesssetupX);
1480 return;
1483 /* Save the lanman2 password and the NT md4 password. */
1485 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1486 doencrypt = False;
1489 if (doencrypt) {
1490 lm_resp = data_blob(p, passlen1);
1491 nt_resp = data_blob(p+passlen1, passlen2);
1492 } else {
1493 pstring pass;
1494 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1496 #if 0
1497 /* This was the previous fix. Not sure if it's still
1498 * valid. JRA. */
1499 if ((ra_type == RA_WINNT) && (passlen2 == 0)
1500 && unic && passlen1) {
1501 /* NT4.0 stuffs up plaintext unicode password
1502 * lengths... */
1503 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
1504 sizeof(pass), passlen1, STR_TERMINATE);
1505 #endif
1507 if (unic && (passlen2 == 0) && passlen1) {
1508 /* Only a ascii plaintext password was sent. */
1509 srvstr_pull(req->inbuf, req->flags2, pass,
1510 smb_buf(req->inbuf), sizeof(pass),
1511 passlen1, STR_TERMINATE|STR_ASCII);
1512 } else {
1513 srvstr_pull(req->inbuf, req->flags2, pass,
1514 smb_buf(req->inbuf), sizeof(pass),
1515 unic ? passlen2 : passlen1,
1516 STR_TERMINATE);
1518 plaintext_password = data_blob(pass, strlen(pass)+1);
1521 p += passlen1 + passlen2;
1522 p += srvstr_pull_buf(req->inbuf, req->flags2, user, p,
1523 sizeof(user), STR_TERMINATE);
1524 p += srvstr_pull_buf(req->inbuf, req->flags2, domain, p,
1525 sizeof(domain), STR_TERMINATE);
1526 p += srvstr_pull_buf(req->inbuf, req->flags2, native_os,
1527 p, sizeof(native_os), STR_TERMINATE);
1528 p += srvstr_pull_buf(req->inbuf, req->flags2,
1529 native_lanman, p, sizeof(native_lanman),
1530 STR_TERMINATE);
1532 /* not documented or decoded by Ethereal but there is one more
1533 * string in the extra bytes which is the same as the
1534 * PrimaryDomain when using extended security. Windows NT 4
1535 * and 2003 use this string to store the native lanman string.
1536 * Windows 9x does not include a string here at all so we have
1537 * to check if we have any extra bytes left */
1539 byte_count = SVAL(req->inbuf, smb_vwv13);
1540 if ( PTR_DIFF(p, save_p) < byte_count) {
1541 p += srvstr_pull_buf(req->inbuf, req->flags2,
1542 primary_domain, p,
1543 sizeof(primary_domain),
1544 STR_TERMINATE);
1545 } else {
1546 fstrcpy( primary_domain, "null" );
1549 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1550 "PrimaryDomain=[%s]\n",
1551 domain, native_os, native_lanman, primary_domain));
1553 if ( ra_type == RA_WIN2K ) {
1554 if ( strlen(native_lanman) == 0 )
1555 ra_lanman_string( primary_domain );
1556 else
1557 ra_lanman_string( native_lanman );
1562 if (SVAL(req->inbuf,smb_vwv4) == 0) {
1563 setup_new_vc_session();
1566 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1567 domain, user, get_remote_machine_name()));
1569 if (*user) {
1570 if (global_spnego_negotiated) {
1572 /* This has to be here, because this is a perfectly
1573 * valid behaviour for guest logons :-( */
1575 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1576 "at 'normal' session setup after "
1577 "negotiating spnego.\n"));
1578 reply_nterror(req, nt_status_squash(
1579 NT_STATUS_LOGON_FAILURE));
1580 END_PROFILE(SMBsesssetupX);
1581 return;
1583 fstrcpy(sub_user, user);
1584 } else {
1585 fstrcpy(sub_user, lp_guestaccount());
1588 sub_set_smb_name(sub_user);
1590 reload_services(True);
1592 if (lp_security() == SEC_SHARE) {
1593 /* in share level we should ignore any passwords */
1595 data_blob_free(&lm_resp);
1596 data_blob_free(&nt_resp);
1597 data_blob_clear_free(&plaintext_password);
1599 map_username(sub_user);
1600 add_session_user(sub_user);
1601 add_session_workgroup(domain);
1602 /* Then force it to null for the benfit of the code below */
1603 *user = 0;
1606 if (!*user) {
1608 nt_status = check_guest_password(&server_info);
1610 } else if (doencrypt) {
1611 if (!negprot_global_auth_context) {
1612 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1613 "session setup without negprot denied!\n"));
1614 reply_nterror(req, nt_status_squash(
1615 NT_STATUS_LOGON_FAILURE));
1616 END_PROFILE(SMBsesssetupX);
1617 return;
1619 nt_status = make_user_info_for_reply_enc(&user_info, user,
1620 domain,
1621 lm_resp, nt_resp);
1622 if (NT_STATUS_IS_OK(nt_status)) {
1623 nt_status = negprot_global_auth_context->check_ntlm_password(
1624 negprot_global_auth_context,
1625 user_info,
1626 &server_info);
1628 } else {
1629 struct auth_context *plaintext_auth_context = NULL;
1630 const uint8 *chal;
1632 nt_status = make_auth_context_subsystem(
1633 &plaintext_auth_context);
1635 if (NT_STATUS_IS_OK(nt_status)) {
1636 chal = plaintext_auth_context->get_ntlm_challenge(
1637 plaintext_auth_context);
1639 if (!make_user_info_for_reply(&user_info,
1640 user, domain, 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 (plaintext_auth_context->free)(
1652 &plaintext_auth_context);
1657 free_user_info(&user_info);
1659 if (!NT_STATUS_IS_OK(nt_status)) {
1660 nt_status = do_map_to_guest(nt_status, &server_info,
1661 user, domain);
1664 if (!NT_STATUS_IS_OK(nt_status)) {
1665 data_blob_free(&nt_resp);
1666 data_blob_free(&lm_resp);
1667 data_blob_clear_free(&plaintext_password);
1668 reply_nterror(req, nt_status_squash(nt_status));
1669 END_PROFILE(SMBsesssetupX);
1670 return;
1673 /* Ensure we can't possible take a code path leading to a
1674 * null defref. */
1675 if (!server_info) {
1676 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1677 END_PROFILE(SMBsesssetupX);
1678 return;
1681 nt_status = create_local_token(server_info);
1682 if (!NT_STATUS_IS_OK(nt_status)) {
1683 DEBUG(10, ("create_local_token failed: %s\n",
1684 nt_errstr(nt_status)));
1685 data_blob_free(&nt_resp);
1686 data_blob_free(&lm_resp);
1687 data_blob_clear_free(&plaintext_password);
1688 reply_nterror(req, nt_status_squash(nt_status));
1689 END_PROFILE(SMBsesssetupX);
1690 return;
1693 if (server_info->user_session_key.data) {
1694 session_key = data_blob(server_info->user_session_key.data,
1695 server_info->user_session_key.length);
1696 } else {
1697 session_key = data_blob_null;
1700 data_blob_clear_free(&plaintext_password);
1702 /* it's ok - setup a reply */
1703 reply_outbuf(req, 3, 0);
1704 if (Protocol >= PROTOCOL_NT1) {
1705 push_signature(&req->outbuf);
1706 /* perhaps grab OS version here?? */
1709 if (server_info->guest) {
1710 SSVAL(req->outbuf,smb_vwv2,1);
1713 /* register the name and uid as being validated, so further connections
1714 to a uid can get through without a password, on the same VC */
1716 if (lp_security() == SEC_SHARE) {
1717 sess_vuid = UID_FIELD_INVALID;
1718 data_blob_free(&session_key);
1719 TALLOC_FREE(server_info);
1720 } else {
1721 /* Ignore the initial vuid. */
1722 sess_vuid = register_initial_vuid();
1723 if (sess_vuid == UID_FIELD_INVALID) {
1724 data_blob_free(&nt_resp);
1725 data_blob_free(&lm_resp);
1726 data_blob_free(&session_key);
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(sess_vuid,
1734 server_info,
1735 session_key,
1736 nt_resp.data ? nt_resp : lm_resp,
1737 sub_user);
1738 if (sess_vuid == UID_FIELD_INVALID) {
1739 data_blob_free(&nt_resp);
1740 data_blob_free(&lm_resp);
1741 data_blob_free(&session_key);
1742 reply_nterror(req, nt_status_squash(
1743 NT_STATUS_LOGON_FAILURE));
1744 END_PROFILE(SMBsesssetupX);
1745 return;
1748 /* current_user_info is changed on new vuid */
1749 reload_services( True );
1751 sessionsetup_start_signing_engine(server_info, req->inbuf);
1754 data_blob_free(&nt_resp);
1755 data_blob_free(&lm_resp);
1757 SSVAL(req->outbuf,smb_uid,sess_vuid);
1758 SSVAL(req->inbuf,smb_uid,sess_vuid);
1760 if (!done_sesssetup)
1761 max_send = MIN(max_send,smb_bufsize);
1763 done_sesssetup = True;
1765 END_PROFILE(SMBsesssetupX);
1766 chain_reply(req);
1767 return;