Here's the fix for bug #5750. Note this bug does *NOT* affect
[Samba.git] / source / smbd / sesssetup.c
bloba0847114f7b039c2134387e9db5afa01f5e3a552
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
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
26 extern struct auth_context *negprot_global_auth_context;
27 extern BOOL global_encrypted_passwords_negotiated;
28 extern BOOL global_spnego_negotiated;
29 extern enum protocol_types Protocol;
30 extern int max_send;
32 uint32 global_client_caps = 0;
35 on a logon error possibly map the error to success if "map to guest"
36 is set approriately
38 static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **server_info,
39 const char *user, const char *domain)
41 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
42 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
43 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
44 DEBUG(3,("No such user %s [%s] - using guest account\n",
45 user, domain));
46 status = make_server_info_guest(server_info);
50 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
51 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
52 DEBUG(3,("Registered username %s for guest access\n",user));
53 status = make_server_info_guest(server_info);
57 return status;
60 /****************************************************************************
61 Add the standard 'Samba' signature to the end of the session setup.
62 ****************************************************************************/
64 static int add_signature(char *outbuf, char *p)
66 char *start = p;
67 fstring lanman;
69 fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
71 p += srvstr_push(outbuf, p, "Unix", BUFFER_SIZE - (p - outbuf), STR_TERMINATE);
72 p += srvstr_push(outbuf, p, lanman, BUFFER_SIZE - (p - outbuf), STR_TERMINATE);
73 p += srvstr_push(outbuf, p, lp_workgroup(), BUFFER_SIZE - (p - outbuf), STR_TERMINATE);
75 return PTR_DIFF(p, start);
78 /****************************************************************************
79 Start the signing engine if needed. Don't fail signing here.
80 ****************************************************************************/
82 static void sessionsetup_start_signing_engine(const auth_serversupplied_info *server_info, char *inbuf)
84 if (!server_info->guest && !srv_signing_started()) {
85 /* We need to start the signing engine
86 * here but a W2K client sends the old
87 * "BSRSPYL " signature instead of the
88 * correct one. Subsequent packets will
89 * be correct.
91 srv_check_sign_mac(inbuf, False);
95 /****************************************************************************
96 Send a security blob via a session setup reply.
97 We must already have called set_message(outbuf,4,0,True)
98 before calling this function.
99 ****************************************************************************/
101 static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
102 DATA_BLOB blob, NTSTATUS nt_status)
104 char *p;
106 if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
107 ERROR_NT(nt_status_squash(nt_status));
108 } else {
109 nt_status = nt_status_squash(nt_status);
110 SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
111 SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
112 SSVAL(outbuf, smb_vwv3, blob.length);
113 p = smb_buf(outbuf);
115 /* should we cap this? */
116 memcpy(p, blob.data, blob.length);
117 p += blob.length;
119 p += add_signature( outbuf, p );
121 set_message_end(outbuf,p);
124 show_msg(outbuf);
125 return send_smb(smbd_server_fd(),outbuf);
128 /****************************************************************************
129 Do a 'guest' logon, getting back the
130 ****************************************************************************/
132 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
134 struct auth_context *auth_context;
135 auth_usersupplied_info *user_info = NULL;
137 NTSTATUS nt_status;
138 unsigned char chal[8];
140 ZERO_STRUCT(chal);
142 DEBUG(3,("Got anonymous request\n"));
144 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) {
145 return nt_status;
148 if (!make_user_info_guest(&user_info)) {
149 (auth_context->free)(&auth_context);
150 return NT_STATUS_NO_MEMORY;
153 nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info);
154 (auth_context->free)(&auth_context);
155 free_user_info(&user_info);
156 return nt_status;
160 #ifdef HAVE_KRB5
162 #if 0
163 /* Experiment that failed. See "only happens with a KDC" comment below. */
164 /****************************************************************************
165 Cerate a clock skew error blob for a Windows client.
166 ****************************************************************************/
168 static BOOL make_krb5_skew_error(DATA_BLOB *pblob_out)
170 krb5_context context = NULL;
171 krb5_error_code kerr = 0;
172 krb5_data reply;
173 krb5_principal host_princ = NULL;
174 char *host_princ_s = NULL;
175 BOOL ret = False;
177 *pblob_out = data_blob(NULL,0);
179 initialize_krb5_error_table();
180 kerr = krb5_init_context(&context);
181 if (kerr) {
182 return False;
184 /* Create server principal. */
185 asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
186 if (!host_princ_s) {
187 goto out;
189 strlower_m(host_princ_s);
191 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
192 if (kerr) {
193 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed for name %s: Error %s\n",
194 host_princ_s, error_message(kerr) ));
195 goto out;
198 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW, host_princ, &reply);
199 if (kerr) {
200 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error failed: Error %s\n",
201 error_message(kerr) ));
202 goto out;
205 *pblob_out = data_blob(reply.data, reply.length);
206 kerberos_free_data_contents(context,&reply);
207 ret = True;
209 out:
211 if (host_princ_s) {
212 SAFE_FREE(host_princ_s);
214 if (host_princ) {
215 krb5_free_principal(context, host_princ);
217 krb5_free_context(context);
218 return ret;
220 #endif
222 /****************************************************************************
223 Reply to a session setup spnego negotiate packet for kerberos.
224 ****************************************************************************/
226 static int reply_spnego_kerberos(connection_struct *conn,
227 char *inbuf, char *outbuf,
228 int length, int bufsize,
229 DATA_BLOB *secblob,
230 BOOL *p_invalidate_vuid)
232 TALLOC_CTX *mem_ctx;
233 DATA_BLOB ticket;
234 char *client, *p, *domain;
235 fstring netbios_domain_name;
236 struct passwd *pw;
237 fstring user;
238 int sess_vuid;
239 NTSTATUS ret;
240 PAC_DATA *pac_data;
241 DATA_BLOB ap_rep, ap_rep_wrapped, response;
242 auth_serversupplied_info *server_info = NULL;
243 DATA_BLOB session_key = data_blob(NULL, 0);
244 uint8 tok_id[2];
245 DATA_BLOB nullblob = data_blob(NULL, 0);
246 fstring real_username;
247 BOOL map_domainuser_to_guest = False;
248 BOOL username_was_mapped;
249 PAC_LOGON_INFO *logon_info = NULL;
251 ZERO_STRUCT(ticket);
252 ZERO_STRUCT(pac_data);
253 ZERO_STRUCT(ap_rep);
254 ZERO_STRUCT(ap_rep_wrapped);
255 ZERO_STRUCT(response);
257 /* Normally we will always invalidate the intermediate vuid. */
258 *p_invalidate_vuid = True;
260 mem_ctx = talloc_init("reply_spnego_kerberos");
261 if (mem_ctx == NULL) {
262 return ERROR_NT(nt_status_squash(NT_STATUS_NO_MEMORY));
265 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
266 talloc_destroy(mem_ctx);
267 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
270 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket, &client, &pac_data, &ap_rep, &session_key);
272 data_blob_free(&ticket);
274 if (!NT_STATUS_IS_OK(ret)) {
275 #if 0
276 /* Experiment that failed. See "only happens with a KDC" comment below. */
278 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
281 * Windows in this case returns NT_STATUS_MORE_PROCESSING_REQUIRED
282 * with a negTokenTarg blob containing an krb5_error struct ASN1 encoded
283 * containing KRB5KRB_AP_ERR_SKEW. The client then fixes its
284 * clock and continues rather than giving an error. JRA.
285 * -- Looks like this only happens with a KDC. JRA.
288 BOOL ok = make_krb5_skew_error(&ap_rep);
289 if (!ok) {
290 talloc_destroy(mem_ctx);
291 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
293 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_ERROR);
294 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
295 reply_sesssetup_blob(conn, outbuf, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
298 * In this one case we don't invalidate the intermediate vuid.
299 * as we're expecting the client to re-use it for the next
300 * sessionsetupX packet. JRA.
303 *p_invalidate_vuid = False;
305 data_blob_free(&ap_rep);
306 data_blob_free(&ap_rep_wrapped);
307 data_blob_free(&response);
308 talloc_destroy(mem_ctx);
309 return -1; /* already replied */
311 #else
312 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
313 ret = NT_STATUS_LOGON_FAILURE;
315 #endif
316 DEBUG(1,("Failed to verify incoming ticket with error %s!\n", nt_errstr(ret)));
317 talloc_destroy(mem_ctx);
318 return ERROR_NT(nt_status_squash(ret));
321 DEBUG(3,("Ticket name is [%s]\n", client));
323 p = strchr_m(client, '@');
324 if (!p) {
325 DEBUG(3,("Doesn't look like a valid principal\n"));
326 data_blob_free(&ap_rep);
327 data_blob_free(&session_key);
328 SAFE_FREE(client);
329 talloc_destroy(mem_ctx);
330 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
333 *p = 0;
335 /* save the PAC data if we have it */
337 if (pac_data) {
338 logon_info = get_logon_info_from_pac(pac_data);
339 if (logon_info) {
340 netsamlogon_cache_store( client, &logon_info->info3 );
344 if (!strequal(p+1, lp_realm())) {
345 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
346 if (!lp_allow_trusted_domains()) {
347 data_blob_free(&ap_rep);
348 data_blob_free(&session_key);
349 SAFE_FREE(client);
350 talloc_destroy(mem_ctx);
351 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
355 /* this gives a fully qualified user name (ie. with full realm).
356 that leads to very long usernames, but what else can we do? */
358 domain = p+1;
360 if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) {
362 unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, -1);
363 domain = netbios_domain_name;
364 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
366 } else {
368 /* If we have winbind running, we can (and must) shorten the
369 username by using the short netbios name. Otherwise we will
370 have inconsistent user names. With Kerberos, we get the
371 fully qualified realm, with ntlmssp we get the short
372 name. And even w2k3 does use ntlmssp if you for example
373 connect to an ip address. */
375 struct winbindd_request wb_request;
376 struct winbindd_response wb_response;
377 NSS_STATUS wb_result;
379 ZERO_STRUCT(wb_request);
380 ZERO_STRUCT(wb_response);
382 DEBUG(10, ("Mapping [%s] to short name\n", domain));
384 fstrcpy(wb_request.domain_name, domain);
386 wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
387 &wb_request, &wb_response);
389 if (wb_result == NSS_STATUS_SUCCESS) {
391 fstrcpy(netbios_domain_name,
392 wb_response.data.domain_info.name);
393 domain = netbios_domain_name;
395 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
396 } else {
397 DEBUG(3, ("Could not find short name -- winbind "
398 "not running?\n"));
402 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
404 /* lookup the passwd struct, create a new user if necessary */
406 username_was_mapped = map_username( user );
408 pw = smb_getpwnam( mem_ctx, user, real_username, True );
410 if (pw) {
411 /* if a real user check pam account restrictions */
412 /* only really perfomed if "obey pam restriction" is true */
413 /* do this before an eventual mappign to guest occurs */
414 ret = smb_pam_accountcheck(pw->pw_name);
415 if ( !NT_STATUS_IS_OK(ret)) {
416 DEBUG(1, ("PAM account restriction prevents user login\n"));
417 data_blob_free(&ap_rep);
418 data_blob_free(&session_key);
419 TALLOC_FREE(mem_ctx);
420 return ERROR_NT(nt_status_squash(ret));
424 if (!pw) {
426 /* this was originally the behavior of Samba 2.2, if a user
427 did not have a local uid but has been authenticated, then
428 map them to a guest account */
430 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
431 map_domainuser_to_guest = True;
432 fstrcpy(user,lp_guestaccount());
433 pw = smb_getpwnam( mem_ctx, user, real_username, True );
436 /* extra sanity check that the guest account is valid */
438 if ( !pw ) {
439 DEBUG(1,("Username %s is invalid on this system\n", user));
440 SAFE_FREE(client);
441 data_blob_free(&ap_rep);
442 data_blob_free(&session_key);
443 TALLOC_FREE(mem_ctx);
444 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
448 /* setup the string used by %U */
450 sub_set_smb_name( real_username );
451 reload_services(True);
453 if ( map_domainuser_to_guest ) {
454 make_server_info_guest(&server_info);
455 } else if (logon_info) {
456 /* pass the unmapped username here since map_username()
457 will be called again from inside make_server_info_info3() */
459 ret = make_server_info_info3(mem_ctx, client, domain,
460 &server_info, &logon_info->info3);
461 if ( !NT_STATUS_IS_OK(ret) ) {
462 DEBUG(1,("make_server_info_info3 failed: %s!\n",
463 nt_errstr(ret)));
464 SAFE_FREE(client);
465 data_blob_free(&ap_rep);
466 data_blob_free(&session_key);
467 TALLOC_FREE(mem_ctx);
468 return ERROR_NT(nt_status_squash(ret));
471 } else {
472 ret = make_server_info_pw(&server_info, real_username, pw);
474 if ( !NT_STATUS_IS_OK(ret) ) {
475 DEBUG(1,("make_server_info_pw failed: %s!\n",
476 nt_errstr(ret)));
477 SAFE_FREE(client);
478 data_blob_free(&ap_rep);
479 data_blob_free(&session_key);
480 TALLOC_FREE(mem_ctx);
481 return ERROR_NT(nt_status_squash(ret));
484 /* make_server_info_pw does not set the domain. Without this
485 * we end up with the local netbios name in substitutions for
486 * %D. */
488 if (server_info->sam_account != NULL) {
489 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
493 server_info->was_mapped |= username_was_mapped;
495 /* we need to build the token for the user. make_server_info_guest()
496 already does this */
498 if ( !server_info->ptok ) {
499 ret = create_local_token( server_info );
500 if ( !NT_STATUS_IS_OK(ret) ) {
501 SAFE_FREE(client);
502 data_blob_free(&ap_rep);
503 data_blob_free(&session_key);
504 TALLOC_FREE( mem_ctx );
505 TALLOC_FREE( server_info );
506 return ERROR_NT(nt_status_squash(ret));
510 /* register_vuid keeps the server info */
511 /* register_vuid takes ownership of session_key, no need to free after this.
512 A better interface would copy it.... */
513 sess_vuid = register_vuid(server_info, session_key, nullblob, client);
515 SAFE_FREE(client);
517 set_message(outbuf,4,0,True);
519 if (sess_vuid == UID_FIELD_INVALID ) {
520 ret = NT_STATUS_LOGON_FAILURE;
521 } else {
522 /* current_user_info is changed on new vuid */
523 reload_services( True );
525 SSVAL(outbuf, smb_vwv3, 0);
527 if (server_info->guest) {
528 SSVAL(outbuf,smb_vwv2,1);
531 SSVAL(outbuf, smb_uid, sess_vuid);
533 sessionsetup_start_signing_engine(server_info, inbuf);
536 /* wrap that up in a nice GSS-API wrapping */
537 if (NT_STATUS_IS_OK(ret)) {
538 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
539 } else {
540 ap_rep_wrapped = data_blob(NULL, 0);
542 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
543 reply_sesssetup_blob(conn, outbuf, response, ret);
545 data_blob_free(&ap_rep);
546 data_blob_free(&ap_rep_wrapped);
547 data_blob_free(&response);
548 TALLOC_FREE(mem_ctx);
550 return -1; /* already replied */
552 #endif
554 /****************************************************************************
555 Send a session setup reply, wrapped in SPNEGO.
556 Get vuid and check first.
557 End the NTLMSSP exchange context if we are OK/complete fail
558 This should be split into two functions, one to handle each
559 leg of the NTLM auth steps.
560 ***************************************************************************/
562 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
563 uint16 vuid,
564 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
565 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
566 BOOL wrap)
568 BOOL ret;
569 DATA_BLOB response;
570 struct auth_serversupplied_info *server_info = NULL;
572 if (NT_STATUS_IS_OK(nt_status)) {
573 server_info = (*auth_ntlmssp_state)->server_info;
574 } else {
575 nt_status = do_map_to_guest(nt_status,
576 &server_info,
577 (*auth_ntlmssp_state)->ntlmssp_state->user,
578 (*auth_ntlmssp_state)->ntlmssp_state->domain);
581 set_message(outbuf,4,0,True);
583 if (NT_STATUS_IS_OK(nt_status)) {
584 int sess_vuid;
585 DATA_BLOB nullblob = data_blob(NULL, 0);
586 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
588 /* register_vuid keeps the server info */
589 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
590 (*auth_ntlmssp_state)->server_info = NULL;
592 if (sess_vuid == UID_FIELD_INVALID ) {
593 nt_status = NT_STATUS_LOGON_FAILURE;
594 } else {
596 /* current_user_info is changed on new vuid */
597 reload_services( True );
599 SSVAL(outbuf, smb_vwv3, 0);
601 if (server_info->guest) {
602 SSVAL(outbuf,smb_vwv2,1);
605 SSVAL(outbuf,smb_uid,sess_vuid);
607 sessionsetup_start_signing_engine(server_info, inbuf);
611 if (wrap) {
612 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
613 } else {
614 response = *ntlmssp_blob;
617 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
618 if (wrap) {
619 data_blob_free(&response);
622 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
623 and the other end, that we are not finished yet. */
625 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
626 /* NB. This is *NOT* an error case. JRA */
627 auth_ntlmssp_end(auth_ntlmssp_state);
628 /* Kill the intermediate vuid */
629 invalidate_intermediate_vuid(vuid);
632 return ret;
635 /****************************************************************************
636 Is this a krb5 mechanism ?
637 ****************************************************************************/
639 static NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, BOOL *p_is_krb5)
641 char *OIDs[ASN1_MAX_OIDS];
642 int i;
644 *p_is_krb5 = False;
646 /* parse out the OIDs and the first sec blob */
647 if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
648 return NT_STATUS_LOGON_FAILURE;
651 /* only look at the first OID for determining the mechToken --
652 accoirding to RFC2478, we should choose the one we want
653 and renegotiate, but i smell a client bug here..
655 Problem observed when connecting to a member (samba box)
656 of an AD domain as a user in a Samba domain. Samba member
657 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
658 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
659 NTLMSSP mechtoken. --jerry */
661 #ifdef HAVE_KRB5
662 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
663 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
664 *p_is_krb5 = True;
666 #endif
668 for (i=0;OIDs[i];i++) {
669 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
670 free(OIDs[i]);
672 return NT_STATUS_OK;
675 /****************************************************************************
676 Reply to a session setup spnego negotiate packet.
677 ****************************************************************************/
679 static int reply_spnego_negotiate(connection_struct *conn,
680 char *inbuf,
681 char *outbuf,
682 uint16 vuid,
683 int length, int bufsize,
684 DATA_BLOB blob1,
685 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
687 DATA_BLOB secblob;
688 DATA_BLOB chal;
689 BOOL got_kerberos_mechanism = False;
690 NTSTATUS status;
692 status = parse_spnego_mechanisms(blob1, &secblob, &got_kerberos_mechanism);
693 if (!NT_STATUS_IS_OK(status)) {
694 /* Kill the intermediate vuid */
695 invalidate_intermediate_vuid(vuid);
696 return ERROR_NT(nt_status_squash(status));
699 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n", (unsigned long)secblob.length));
701 #ifdef HAVE_KRB5
702 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
703 BOOL destroy_vuid = True;
704 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
705 length, bufsize, &secblob, &destroy_vuid);
706 data_blob_free(&secblob);
707 if (destroy_vuid) {
708 /* Kill the intermediate vuid */
709 invalidate_intermediate_vuid(vuid);
711 return ret;
713 #endif
715 if (got_kerberos_mechanism) {
716 invalidate_intermediate_vuid(vuid);
717 DEBUG(3,("reply_spnego_negotiate: network "
718 "misconfiguration, client sent us a "
719 "krb5 ticket and kerberos security "
720 "not enabled"));
721 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
724 if (*auth_ntlmssp_state) {
725 auth_ntlmssp_end(auth_ntlmssp_state);
728 status = auth_ntlmssp_start(auth_ntlmssp_state);
729 if (!NT_STATUS_IS_OK(status)) {
730 /* Kill the intermediate vuid */
731 invalidate_intermediate_vuid(vuid);
732 return ERROR_NT(nt_status_squash(status));
735 status = auth_ntlmssp_update(*auth_ntlmssp_state,
736 secblob, &chal);
738 data_blob_free(&secblob);
740 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
741 &chal, status, True);
743 data_blob_free(&chal);
745 /* already replied */
746 return -1;
749 /****************************************************************************
750 Reply to a session setup spnego auth packet.
751 ****************************************************************************/
753 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
754 uint16 vuid,
755 int length, int bufsize,
756 DATA_BLOB blob1,
757 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
759 DATA_BLOB auth = data_blob(NULL,0);
760 DATA_BLOB auth_reply = data_blob(NULL,0);
761 DATA_BLOB secblob = data_blob(NULL,0);
762 NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
764 if (!spnego_parse_auth(blob1, &auth)) {
765 #if 0
766 file_save("auth.dat", blob1.data, blob1.length);
767 #endif
768 /* Kill the intermediate vuid */
769 invalidate_intermediate_vuid(vuid);
771 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
774 if (auth.data[0] == ASN1_APPLICATION(0)) {
775 /* Might be a second negTokenTarg packet */
777 BOOL got_krb5_mechanism = False;
778 status = parse_spnego_mechanisms(auth, &secblob, &got_krb5_mechanism);
779 if (NT_STATUS_IS_OK(status)) {
780 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n", (unsigned long)secblob.length));
781 #ifdef HAVE_KRB5
782 if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
783 BOOL destroy_vuid = True;
784 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
785 length, bufsize, &secblob, &destroy_vuid);
786 data_blob_free(&secblob);
787 data_blob_free(&auth);
788 if (destroy_vuid) {
789 /* Kill the intermediate vuid */
790 invalidate_intermediate_vuid(vuid);
792 return ret;
794 #endif
798 /* If we get here it wasn't a negTokenTarg auth packet. */
799 data_blob_free(&secblob);
801 if (!*auth_ntlmssp_state) {
802 /* Kill the intermediate vuid */
803 invalidate_intermediate_vuid(vuid);
805 /* auth before negotiatiate? */
806 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
809 status = auth_ntlmssp_update(*auth_ntlmssp_state,
810 auth, &auth_reply);
812 data_blob_free(&auth);
814 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
815 auth_ntlmssp_state,
816 &auth_reply, status, True);
818 data_blob_free(&auth_reply);
820 /* and tell smbd that we have already replied to this packet */
821 return -1;
824 /****************************************************************************
825 List to store partial SPNEGO auth fragments.
826 ****************************************************************************/
828 static struct pending_auth_data *pd_list;
830 /****************************************************************************
831 Delete an entry on the list.
832 ****************************************************************************/
834 static void delete_partial_auth(struct pending_auth_data *pad)
836 if (!pad) {
837 return;
839 DLIST_REMOVE(pd_list, pad);
840 data_blob_free(&pad->partial_data);
841 SAFE_FREE(pad);
844 /****************************************************************************
845 Search for a partial SPNEGO auth fragment matching an smbpid.
846 ****************************************************************************/
848 static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
850 struct pending_auth_data *pad;
852 for (pad = pd_list; pad; pad = pad->next) {
853 if (pad->smbpid == smbpid) {
854 break;
857 return pad;
860 /****************************************************************************
861 Check the size of an SPNEGO blob. If we need more return NT_STATUS_MORE_PROCESSING_REQUIRED,
862 else return NT_STATUS_OK. Don't allow the blob to be more than 64k.
863 ****************************************************************************/
865 static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB *pblob)
867 struct pending_auth_data *pad = NULL;
868 ASN1_DATA data;
869 size_t needed_len = 0;
871 pad = get_pending_auth_data(smbpid);
873 /* Ensure we have some data. */
874 if (pblob->length == 0) {
875 /* Caller can cope. */
876 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
877 delete_partial_auth(pad);
878 return NT_STATUS_OK;
881 /* Were we waiting for more data ? */
882 if (pad) {
883 DATA_BLOB tmp_blob;
884 size_t copy_len = MIN(65536, pblob->length);
886 /* Integer wrap paranoia.... */
888 if (pad->partial_data.length + copy_len < pad->partial_data.length ||
889 pad->partial_data.length + copy_len < copy_len) {
891 DEBUG(2,("check_spnego_blob_complete: integer wrap "
892 "pad->partial_data.length = %u, "
893 "copy_len = %u\n",
894 (unsigned int)pad->partial_data.length,
895 (unsigned int)copy_len ));
897 delete_partial_auth(pad);
898 return NT_STATUS_INVALID_PARAMETER;
901 DEBUG(10,("check_spnego_blob_complete: "
902 "pad->partial_data.length = %u, "
903 "pad->needed_len = %u, "
904 "copy_len = %u, "
905 "pblob->length = %u,\n",
906 (unsigned int)pad->partial_data.length,
907 (unsigned int)pad->needed_len,
908 (unsigned int)copy_len,
909 (unsigned int)pblob->length ));
911 tmp_blob = data_blob(NULL,
912 pad->partial_data.length + copy_len);
914 /* Concatenate the two (up to copy_len) bytes. */
915 memcpy(tmp_blob.data,
916 pad->partial_data.data,
917 pad->partial_data.length);
918 memcpy(tmp_blob.data + pad->partial_data.length,
919 pblob->data,
920 copy_len);
922 /* Replace the partial data. */
923 data_blob_free(&pad->partial_data);
924 pad->partial_data = tmp_blob;
925 ZERO_STRUCT(tmp_blob);
927 /* Are we done ? */
928 if (pblob->length >= pad->needed_len) {
929 /* Yes, replace pblob. */
930 data_blob_free(pblob);
931 *pblob = pad->partial_data;
932 ZERO_STRUCT(pad->partial_data);
933 delete_partial_auth(pad);
934 return NT_STATUS_OK;
937 /* Still need more data. */
938 pad->needed_len -= copy_len;
939 return NT_STATUS_MORE_PROCESSING_REQUIRED;
942 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
943 (pblob->data[0] != ASN1_CONTEXT(1))) {
944 /* Not something we can determine the
945 * length of.
947 return NT_STATUS_OK;
950 /* This is a new SPNEGO sessionsetup - see if
951 * the data given in this blob is enough.
954 asn1_load(&data, *pblob);
955 asn1_start_tag(&data, pblob->data[0]);
956 if (data.has_error || data.nesting == NULL) {
957 asn1_free(&data);
958 /* Let caller catch. */
959 return NT_STATUS_OK;
962 /* Integer wrap paranoia.... */
964 if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
965 data.nesting->taglen + data.nesting->start < data.nesting->start) {
967 DEBUG(2,("check_spnego_blob_complete: integer wrap "
968 "data.nesting->taglen = %u, "
969 "data.nesting->start = %u\n",
970 (unsigned int)data.nesting->taglen,
971 (unsigned int)data.nesting->start ));
973 asn1_free(&data);
974 return NT_STATUS_INVALID_PARAMETER;
977 /* Total length of the needed asn1 is the tag length
978 * plus the current offset. */
980 needed_len = data.nesting->taglen + data.nesting->start;
981 asn1_free(&data);
983 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
984 "pblob->length = %u\n",
985 (unsigned int)needed_len,
986 (unsigned int)pblob->length ));
988 if (needed_len <= pblob->length) {
989 /* Nothing to do - blob is complete. */
990 return NT_STATUS_OK;
993 /* Refuse the blob if it's bigger than 64k. */
994 if (needed_len > 65536) {
995 DEBUG(2,("check_spnego_blob_complete: needed_len too large (%u)\n",
996 (unsigned int)needed_len ));
997 return NT_STATUS_INVALID_PARAMETER;
1000 /* We must store this blob until complete. */
1001 pad = SMB_MALLOC(sizeof(struct pending_auth_data));
1002 if (!pad) {
1003 return NT_STATUS_NO_MEMORY;
1005 pad->needed_len = needed_len - pblob->length;
1006 pad->partial_data = data_blob(pblob->data, pblob->length);
1007 if (pad->partial_data.data == NULL) {
1008 SAFE_FREE(pad);
1009 return NT_STATUS_NO_MEMORY;
1011 pad->smbpid = smbpid;
1012 pad->vuid = vuid;
1013 DLIST_ADD(pd_list, pad);
1015 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1018 /****************************************************************************
1019 Reply to a session setup command.
1020 conn POINTER CAN BE NULL HERE !
1021 ****************************************************************************/
1023 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
1024 char *outbuf,
1025 int length,int bufsize)
1027 uint8 *p;
1028 DATA_BLOB blob1;
1029 int ret;
1030 size_t bufrem;
1031 fstring native_os, native_lanman, primary_domain;
1032 char *p2;
1033 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
1034 enum remote_arch_types ra_type = get_remote_arch();
1035 int vuid = SVAL(inbuf,smb_uid);
1036 user_struct *vuser = NULL;
1037 NTSTATUS status = NT_STATUS_OK;
1038 uint16 smbpid = SVAL(inbuf,smb_pid);
1040 DEBUG(3,("Doing spnego session setup\n"));
1042 if (global_client_caps == 0) {
1043 global_client_caps = IVAL(inbuf,smb_vwv10);
1045 if (!(global_client_caps & CAP_STATUS32)) {
1046 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1051 p = (uint8 *)smb_buf(inbuf);
1053 if (data_blob_len == 0) {
1054 /* an invalid request */
1055 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1058 bufrem = smb_bufrem(inbuf, p);
1059 /* pull the spnego blob */
1060 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1062 #if 0
1063 file_save("negotiate.dat", blob1.data, blob1.length);
1064 #endif
1066 p2 = inbuf + smb_vwv13 + data_blob_len;
1067 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
1068 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
1069 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
1070 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1071 native_os, native_lanman, primary_domain));
1073 if ( ra_type == RA_WIN2K ) {
1074 /* Vista sets neither the OS or lanman strings */
1076 if ( !strlen(native_os) && !strlen(native_lanman) )
1077 set_remote_arch(RA_VISTA);
1079 /* Windows 2003 doesn't set the native lanman string,
1080 but does set primary domain which is a bug I think */
1082 if ( !strlen(native_lanman) ) {
1083 ra_lanman_string( primary_domain );
1084 } else {
1085 ra_lanman_string( native_lanman );
1089 vuser = get_partial_auth_user_struct(vuid);
1090 if (!vuser) {
1091 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
1092 if (pad) {
1093 DEBUG(10,("reply_sesssetup_and_X_spnego: found pending vuid %u\n",
1094 (unsigned int)pad->vuid ));
1095 vuid = pad->vuid;
1096 vuser = get_partial_auth_user_struct(vuid);
1100 if (!vuser) {
1101 vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);
1102 if (vuid == UID_FIELD_INVALID ) {
1103 data_blob_free(&blob1);
1104 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1107 vuser = get_partial_auth_user_struct(vuid);
1110 if (!vuser) {
1111 data_blob_free(&blob1);
1112 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1115 SSVAL(outbuf,smb_uid,vuid);
1117 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1118 * sessionsetup requests as the Windows limit on the security blob
1119 * field is 4k. Bug #4400. JRA.
1122 status = check_spnego_blob_complete(smbpid, vuid, &blob1);
1123 if (!NT_STATUS_IS_OK(status)) {
1124 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1125 /* Real error - kill the intermediate vuid */
1126 invalidate_intermediate_vuid(vuid);
1128 data_blob_free(&blob1);
1129 return ERROR_NT(nt_status_squash(status));
1132 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1133 /* its a negTokenTarg packet */
1134 ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
1135 &vuser->auth_ntlmssp_state);
1136 data_blob_free(&blob1);
1137 return ret;
1140 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1141 /* its a auth packet */
1142 ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
1143 &vuser->auth_ntlmssp_state);
1144 data_blob_free(&blob1);
1145 return ret;
1148 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1149 DATA_BLOB chal;
1150 if (!vuser->auth_ntlmssp_state) {
1151 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1152 if (!NT_STATUS_IS_OK(status)) {
1153 /* Kill the intermediate vuid */
1154 invalidate_intermediate_vuid(vuid);
1155 data_blob_free(&blob1);
1156 return ERROR_NT(nt_status_squash(status));
1160 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1161 blob1, &chal);
1163 data_blob_free(&blob1);
1165 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
1166 &vuser->auth_ntlmssp_state,
1167 &chal, status, False);
1168 data_blob_free(&chal);
1169 return -1;
1172 /* what sort of packet is this? */
1173 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1175 data_blob_free(&blob1);
1177 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1180 /****************************************************************************
1181 On new VC == 0, shutdown *all* old connections and users.
1182 It seems that only NT4.x does this. At W2K and above (XP etc.).
1183 a new session setup with VC==0 is ignored.
1184 ****************************************************************************/
1186 static int shutdown_other_smbds(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
1187 void *p)
1189 struct sessionid sessionid;
1190 const char *ip = (const char *)p;
1192 SMB_ASSERT(dbuf.dsize == sizeof(sessionid));
1193 memcpy(&sessionid, dbuf.dptr, sizeof(sessionid));
1195 if (!process_exists(pid_to_procid(sessionid.pid))) {
1196 return 0;
1199 if (sessionid.pid == sys_getpid()) {
1200 return 0;
1203 if (strcmp(ip, sessionid.ip_addr) != 0) {
1204 return 0;
1207 message_send_pid(pid_to_procid(sessionid.pid), MSG_SHUTDOWN,
1208 NULL, 0, True);
1209 return 0;
1212 static void setup_new_vc_session(void)
1214 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
1215 #if 0
1216 conn_close_all();
1217 invalidate_all_vuids();
1218 #endif
1219 if (lp_reset_on_zero_vc()) {
1220 session_traverse(shutdown_other_smbds, client_addr());
1224 /****************************************************************************
1225 Reply to a session setup command.
1226 ****************************************************************************/
1228 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
1229 int length,int bufsize)
1231 int sess_vuid;
1232 int smb_bufsize;
1233 DATA_BLOB lm_resp;
1234 DATA_BLOB nt_resp;
1235 DATA_BLOB plaintext_password;
1236 fstring user;
1237 fstring sub_user; /* Sainitised username for substituion */
1238 fstring domain;
1239 fstring native_os;
1240 fstring native_lanman;
1241 fstring primary_domain;
1242 static BOOL done_sesssetup = False;
1243 auth_usersupplied_info *user_info = NULL;
1244 auth_serversupplied_info *server_info = NULL;
1246 NTSTATUS nt_status;
1248 BOOL doencrypt = global_encrypted_passwords_negotiated;
1250 DATA_BLOB session_key;
1252 START_PROFILE(SMBsesssetupX);
1254 ZERO_STRUCT(lm_resp);
1255 ZERO_STRUCT(nt_resp);
1256 ZERO_STRUCT(plaintext_password);
1258 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
1260 /* a SPNEGO session setup has 12 command words, whereas a normal
1261 NT1 session setup has 13. See the cifs spec. */
1262 if (CVAL(inbuf, smb_wct) == 12 &&
1263 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
1264 if (!global_spnego_negotiated) {
1265 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
1266 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1269 if (SVAL(inbuf,smb_vwv4) == 0) {
1270 setup_new_vc_session();
1272 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
1275 smb_bufsize = SVAL(inbuf,smb_vwv2);
1277 if (Protocol < PROTOCOL_NT1) {
1278 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
1280 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
1281 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1283 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
1284 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1287 if (doencrypt) {
1288 lm_resp = data_blob(smb_buf(inbuf), passlen1);
1289 } else {
1290 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
1291 /* Ensure null termination */
1292 plaintext_password.data[passlen1] = 0;
1295 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
1296 *domain = 0;
1298 } else {
1299 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
1300 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
1301 enum remote_arch_types ra_type = get_remote_arch();
1302 char *p = smb_buf(inbuf);
1303 char *save_p = smb_buf(inbuf);
1304 uint16 byte_count;
1307 if(global_client_caps == 0) {
1308 global_client_caps = IVAL(inbuf,smb_vwv11);
1310 if (!(global_client_caps & CAP_STATUS32)) {
1311 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1314 /* client_caps is used as final determination if client is NT or Win95.
1315 This is needed to return the correct error codes in some
1316 circumstances.
1319 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
1320 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
1321 set_remote_arch( RA_WIN95);
1326 if (!doencrypt) {
1327 /* both Win95 and WinNT stuff up the password lengths for
1328 non-encrypting systems. Uggh.
1330 if passlen1==24 its a win95 system, and its setting the
1331 password length incorrectly. Luckily it still works with the
1332 default code because Win95 will null terminate the password
1333 anyway
1335 if passlen1>0 and passlen2>0 then maybe its a NT box and its
1336 setting passlen2 to some random value which really stuffs
1337 things up. we need to fix that one. */
1339 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
1340 passlen2 = 0;
1343 /* check for nasty tricks */
1344 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
1345 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1348 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
1349 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1352 /* Save the lanman2 password and the NT md4 password. */
1354 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1355 doencrypt = False;
1358 if (doencrypt) {
1359 lm_resp = data_blob(p, passlen1);
1360 nt_resp = data_blob(p+passlen1, passlen2);
1361 } else {
1362 pstring pass;
1363 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
1365 #if 0
1366 /* This was the previous fix. Not sure if it's still valid. JRA. */
1367 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
1368 /* NT4.0 stuffs up plaintext unicode password lengths... */
1369 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
1370 sizeof(pass), passlen1, STR_TERMINATE);
1371 #endif
1373 if (unic && (passlen2 == 0) && passlen1) {
1374 /* Only a ascii plaintext password was sent. */
1375 srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
1376 passlen1, STR_TERMINATE|STR_ASCII);
1377 } else {
1378 srvstr_pull(inbuf, pass, smb_buf(inbuf),
1379 sizeof(pass), unic ? passlen2 : passlen1,
1380 STR_TERMINATE);
1382 plaintext_password = data_blob(pass, strlen(pass)+1);
1385 p += passlen1 + passlen2;
1386 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
1387 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
1388 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
1389 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
1391 /* not documented or decoded by Ethereal but there is one more string
1392 in the extra bytes which is the same as the PrimaryDomain when using
1393 extended security. Windows NT 4 and 2003 use this string to store
1394 the native lanman string. Windows 9x does not include a string here
1395 at all so we have to check if we have any extra bytes left */
1397 byte_count = SVAL(inbuf, smb_vwv13);
1398 if ( PTR_DIFF(p, save_p) < byte_count)
1399 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
1400 else
1401 fstrcpy( primary_domain, "null" );
1403 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1404 domain, native_os, native_lanman, primary_domain));
1406 if ( ra_type == RA_WIN2K ) {
1407 if ( strlen(native_lanman) == 0 )
1408 ra_lanman_string( primary_domain );
1409 else
1410 ra_lanman_string( native_lanman );
1415 if (SVAL(inbuf,smb_vwv4) == 0) {
1416 setup_new_vc_session();
1419 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
1421 if (*user) {
1422 if (global_spnego_negotiated) {
1424 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
1426 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
1427 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1429 fstrcpy(sub_user, user);
1430 } else {
1431 fstrcpy(sub_user, lp_guestaccount());
1434 sub_set_smb_name(sub_user);
1436 reload_services(True);
1438 if (lp_security() == SEC_SHARE) {
1439 /* in share level we should ignore any passwords */
1441 data_blob_free(&lm_resp);
1442 data_blob_free(&nt_resp);
1443 data_blob_clear_free(&plaintext_password);
1445 map_username(sub_user);
1446 add_session_user(sub_user);
1447 add_session_workgroup(domain);
1448 /* Then force it to null for the benfit of the code below */
1449 *user = 0;
1452 if (!*user) {
1454 nt_status = check_guest_password(&server_info);
1456 } else if (doencrypt) {
1457 if (!negprot_global_auth_context) {
1458 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
1459 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1461 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
1462 lm_resp, nt_resp);
1463 if (NT_STATUS_IS_OK(nt_status)) {
1464 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
1465 user_info,
1466 &server_info);
1468 } else {
1469 struct auth_context *plaintext_auth_context = NULL;
1470 const uint8 *chal;
1472 nt_status = make_auth_context_subsystem(&plaintext_auth_context);
1474 if (NT_STATUS_IS_OK(nt_status)) {
1475 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
1477 if (!make_user_info_for_reply(&user_info,
1478 user, domain, chal,
1479 plaintext_password)) {
1480 nt_status = NT_STATUS_NO_MEMORY;
1483 if (NT_STATUS_IS_OK(nt_status)) {
1484 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
1485 user_info,
1486 &server_info);
1488 (plaintext_auth_context->free)(&plaintext_auth_context);
1493 free_user_info(&user_info);
1495 if (!NT_STATUS_IS_OK(nt_status)) {
1496 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
1499 if (!NT_STATUS_IS_OK(nt_status)) {
1500 data_blob_free(&nt_resp);
1501 data_blob_free(&lm_resp);
1502 data_blob_clear_free(&plaintext_password);
1503 return ERROR_NT(nt_status_squash(nt_status));
1506 /* Ensure we can't possible take a code path leading to a null defref. */
1507 if (!server_info) {
1508 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1511 if (!server_info->ptok) {
1512 nt_status = create_local_token(server_info);
1513 if (!NT_STATUS_IS_OK(nt_status)) {
1514 DEBUG(10, ("create_local_token failed: %s\n",
1515 nt_errstr(nt_status)));
1516 data_blob_free(&nt_resp);
1517 data_blob_free(&lm_resp);
1518 data_blob_clear_free(&plaintext_password);
1519 return ERROR_NT(nt_status_squash(nt_status));
1523 if (server_info->user_session_key.data) {
1524 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
1525 } else {
1526 session_key = data_blob(NULL, 0);
1529 data_blob_clear_free(&plaintext_password);
1531 /* it's ok - setup a reply */
1532 set_message(outbuf,3,0,True);
1533 if (Protocol >= PROTOCOL_NT1) {
1534 char *p = smb_buf( outbuf );
1535 p += add_signature( outbuf, p );
1536 set_message_end( outbuf, p );
1537 /* perhaps grab OS version here?? */
1540 if (server_info->guest) {
1541 SSVAL(outbuf,smb_vwv2,1);
1544 /* register the name and uid as being validated, so further connections
1545 to a uid can get through without a password, on the same VC */
1547 if (lp_security() == SEC_SHARE) {
1548 sess_vuid = UID_FIELD_INVALID;
1549 data_blob_free(&session_key);
1550 TALLOC_FREE(server_info);
1551 } else {
1552 /* register_vuid keeps the server info */
1553 sess_vuid = register_vuid(server_info, session_key,
1554 nt_resp.data ? nt_resp : lm_resp,
1555 sub_user);
1556 if (sess_vuid == UID_FIELD_INVALID) {
1557 data_blob_free(&nt_resp);
1558 data_blob_free(&lm_resp);
1559 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1562 /* current_user_info is changed on new vuid */
1563 reload_services( True );
1565 sessionsetup_start_signing_engine(server_info, inbuf);
1568 data_blob_free(&nt_resp);
1569 data_blob_free(&lm_resp);
1571 SSVAL(outbuf,smb_uid,sess_vuid);
1572 SSVAL(inbuf,smb_uid,sess_vuid);
1574 if (!done_sesssetup)
1575 max_send = MIN(max_send,smb_bufsize);
1577 done_sesssetup = True;
1579 END_PROFILE(SMBsesssetupX);
1580 return chain_reply(inbuf,outbuf,length,bufsize);