r22868: Replace some message_send_pid calls with messaging_send_pid calls. More
[Samba/bb.git] / source3 / smbd / sesssetup.c
blobccfc22598d7a2f0d13523b1849ddf6967667db86
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", -1, STR_TERMINATE);
72 p += srvstr_push(outbuf, p, lanman, -1, STR_TERMINATE);
73 p += srvstr_push(outbuf, p, lp_workgroup(), -1, 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 ****************************************************************************/
99 static BOOL reply_sesssetup_blob(connection_struct *conn,
100 const char *inbuf,
101 char *outbuf,
102 DATA_BLOB blob,
103 NTSTATUS nt_status)
105 char *p;
107 if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
108 ERROR_NT(nt_status_squash(nt_status));
109 } else {
110 set_message(inbuf,outbuf,4,0,True);
112 nt_status = nt_status_squash(nt_status);
113 SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
114 SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
115 SSVAL(outbuf, smb_vwv3, blob.length);
116 p = smb_buf(outbuf);
118 /* should we cap this? */
119 memcpy(p, blob.data, blob.length);
120 p += blob.length;
122 p += add_signature( outbuf, p );
124 set_message_end(inbuf,outbuf,p);
127 show_msg(outbuf);
128 return send_smb(smbd_server_fd(),outbuf);
131 /****************************************************************************
132 Do a 'guest' logon, getting back the
133 ****************************************************************************/
135 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
137 struct auth_context *auth_context;
138 auth_usersupplied_info *user_info = NULL;
140 NTSTATUS nt_status;
141 unsigned char chal[8];
143 ZERO_STRUCT(chal);
145 DEBUG(3,("Got anonymous request\n"));
147 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) {
148 return nt_status;
151 if (!make_user_info_guest(&user_info)) {
152 (auth_context->free)(&auth_context);
153 return NT_STATUS_NO_MEMORY;
156 nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info);
157 (auth_context->free)(&auth_context);
158 free_user_info(&user_info);
159 return nt_status;
163 #ifdef HAVE_KRB5
165 #if 0
166 /* Experiment that failed. See "only happens with a KDC" comment below. */
167 /****************************************************************************
168 Cerate a clock skew error blob for a Windows client.
169 ****************************************************************************/
171 static BOOL make_krb5_skew_error(DATA_BLOB *pblob_out)
173 krb5_context context = NULL;
174 krb5_error_code kerr = 0;
175 krb5_data reply;
176 krb5_principal host_princ = NULL;
177 char *host_princ_s = NULL;
178 BOOL ret = False;
180 *pblob_out = data_blob_null;
182 initialize_krb5_error_table();
183 kerr = krb5_init_context(&context);
184 if (kerr) {
185 return False;
187 /* Create server principal. */
188 asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
189 if (!host_princ_s) {
190 goto out;
192 strlower_m(host_princ_s);
194 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
195 if (kerr) {
196 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed for name %s: Error %s\n",
197 host_princ_s, error_message(kerr) ));
198 goto out;
201 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW, host_princ, &reply);
202 if (kerr) {
203 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error failed: Error %s\n",
204 error_message(kerr) ));
205 goto out;
208 *pblob_out = data_blob(reply.data, reply.length);
209 kerberos_free_data_contents(context,&reply);
210 ret = True;
212 out:
214 if (host_princ_s) {
215 SAFE_FREE(host_princ_s);
217 if (host_princ) {
218 krb5_free_principal(context, host_princ);
220 krb5_free_context(context);
221 return ret;
223 #endif
225 /****************************************************************************
226 Reply to a session setup spnego negotiate packet for kerberos.
227 ****************************************************************************/
229 static int reply_spnego_kerberos(connection_struct *conn,
230 char *inbuf, char *outbuf,
231 int length, int bufsize,
232 DATA_BLOB *secblob,
233 BOOL *p_invalidate_vuid)
235 TALLOC_CTX *mem_ctx;
236 DATA_BLOB ticket;
237 char *client, *p, *domain;
238 fstring netbios_domain_name;
239 struct passwd *pw;
240 fstring user;
241 int sess_vuid;
242 NTSTATUS ret;
243 PAC_DATA *pac_data;
244 DATA_BLOB ap_rep, ap_rep_wrapped, response;
245 auth_serversupplied_info *server_info = NULL;
246 DATA_BLOB session_key = data_blob_null;
247 uint8 tok_id[2];
248 DATA_BLOB nullblob = data_blob_null;
249 fstring real_username;
250 BOOL map_domainuser_to_guest = False;
251 BOOL username_was_mapped;
252 PAC_LOGON_INFO *logon_info = NULL;
254 ZERO_STRUCT(ticket);
255 ZERO_STRUCT(pac_data);
256 ZERO_STRUCT(ap_rep);
257 ZERO_STRUCT(ap_rep_wrapped);
258 ZERO_STRUCT(response);
260 /* Normally we will always invalidate the intermediate vuid. */
261 *p_invalidate_vuid = True;
263 mem_ctx = talloc_init("reply_spnego_kerberos");
264 if (mem_ctx == NULL) {
265 return ERROR_NT(nt_status_squash(NT_STATUS_NO_MEMORY));
268 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
269 talloc_destroy(mem_ctx);
270 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
273 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket, &client, &pac_data, &ap_rep, &session_key);
275 data_blob_free(&ticket);
277 if (!NT_STATUS_IS_OK(ret)) {
278 #if 0
279 /* Experiment that failed. See "only happens with a KDC" comment below. */
281 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
284 * Windows in this case returns NT_STATUS_MORE_PROCESSING_REQUIRED
285 * with a negTokenTarg blob containing an krb5_error struct ASN1 encoded
286 * containing KRB5KRB_AP_ERR_SKEW. The client then fixes its
287 * clock and continues rather than giving an error. JRA.
288 * -- Looks like this only happens with a KDC. JRA.
291 BOOL ok = make_krb5_skew_error(&ap_rep);
292 if (!ok) {
293 talloc_destroy(mem_ctx);
294 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
296 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_ERROR);
297 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
298 reply_sesssetup_blob(conn, inbuf, outbuf, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
301 * In this one case we don't invalidate the intermediate vuid.
302 * as we're expecting the client to re-use it for the next
303 * sessionsetupX packet. JRA.
306 *p_invalidate_vuid = False;
308 data_blob_free(&ap_rep);
309 data_blob_free(&ap_rep_wrapped);
310 data_blob_free(&response);
311 talloc_destroy(mem_ctx);
312 return -1; /* already replied */
314 #else
315 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
316 ret = NT_STATUS_LOGON_FAILURE;
318 #endif
319 DEBUG(1,("Failed to verify incoming ticket with error %s!\n", nt_errstr(ret)));
320 talloc_destroy(mem_ctx);
321 return ERROR_NT(nt_status_squash(ret));
324 DEBUG(3,("Ticket name is [%s]\n", client));
326 p = strchr_m(client, '@');
327 if (!p) {
328 DEBUG(3,("Doesn't look like a valid principal\n"));
329 data_blob_free(&ap_rep);
330 data_blob_free(&session_key);
331 SAFE_FREE(client);
332 talloc_destroy(mem_ctx);
333 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
336 *p = 0;
338 /* save the PAC data if we have it */
340 if (pac_data) {
341 logon_info = get_logon_info_from_pac(pac_data);
342 if (logon_info) {
343 netsamlogon_cache_store( client, &logon_info->info3 );
347 if (!strequal(p+1, lp_realm())) {
348 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
349 if (!lp_allow_trusted_domains()) {
350 data_blob_free(&ap_rep);
351 data_blob_free(&session_key);
352 SAFE_FREE(client);
353 talloc_destroy(mem_ctx);
354 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
358 /* this gives a fully qualified user name (ie. with full realm).
359 that leads to very long usernames, but what else can we do? */
361 domain = p+1;
363 if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) {
365 unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, -1);
366 domain = netbios_domain_name;
367 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
369 } else {
371 /* If we have winbind running, we can (and must) shorten the
372 username by using the short netbios name. Otherwise we will
373 have inconsistent user names. With Kerberos, we get the
374 fully qualified realm, with ntlmssp we get the short
375 name. And even w2k3 does use ntlmssp if you for example
376 connect to an ip address. */
378 struct winbindd_request wb_request;
379 struct winbindd_response wb_response;
380 NSS_STATUS wb_result;
382 ZERO_STRUCT(wb_request);
383 ZERO_STRUCT(wb_response);
385 DEBUG(10, ("Mapping [%s] to short name\n", domain));
387 fstrcpy(wb_request.domain_name, domain);
389 wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
390 &wb_request, &wb_response);
392 if (wb_result == NSS_STATUS_SUCCESS) {
394 fstrcpy(netbios_domain_name,
395 wb_response.data.domain_info.name);
396 domain = netbios_domain_name;
398 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
399 } else {
400 DEBUG(3, ("Could not find short name -- winbind "
401 "not running?\n"));
405 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
407 /* lookup the passwd struct, create a new user if necessary */
409 username_was_mapped = map_username( user );
411 pw = smb_getpwnam( mem_ctx, user, real_username, True );
413 if (pw) {
414 /* if a real user check pam account restrictions */
415 /* only really perfomed if "obey pam restriction" is true */
416 /* do this before an eventual mappign to guest occurs */
417 ret = smb_pam_accountcheck(pw->pw_name);
418 if ( !NT_STATUS_IS_OK(ret)) {
419 DEBUG(1, ("PAM account restriction prevents user login\n"));
420 data_blob_free(&ap_rep);
421 data_blob_free(&session_key);
422 TALLOC_FREE(mem_ctx);
423 return ERROR_NT(nt_status_squash(ret));
427 if (!pw) {
429 /* this was originally the behavior of Samba 2.2, if a user
430 did not have a local uid but has been authenticated, then
431 map them to a guest account */
433 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
434 map_domainuser_to_guest = True;
435 fstrcpy(user,lp_guestaccount());
436 pw = smb_getpwnam( mem_ctx, user, real_username, True );
439 /* extra sanity check that the guest account is valid */
441 if ( !pw ) {
442 DEBUG(1,("Username %s is invalid on this system\n", user));
443 SAFE_FREE(client);
444 data_blob_free(&ap_rep);
445 data_blob_free(&session_key);
446 TALLOC_FREE(mem_ctx);
447 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
451 /* setup the string used by %U */
453 sub_set_smb_name( real_username );
454 reload_services(True);
456 if ( map_domainuser_to_guest ) {
457 make_server_info_guest(&server_info);
458 } else if (logon_info) {
459 /* pass the unmapped username here since map_username()
460 will be called again from inside make_server_info_info3() */
462 ret = make_server_info_info3(mem_ctx, client, domain,
463 &server_info, &logon_info->info3);
464 if ( !NT_STATUS_IS_OK(ret) ) {
465 DEBUG(1,("make_server_info_info3 failed: %s!\n",
466 nt_errstr(ret)));
467 SAFE_FREE(client);
468 data_blob_free(&ap_rep);
469 data_blob_free(&session_key);
470 TALLOC_FREE(mem_ctx);
471 return ERROR_NT(nt_status_squash(ret));
474 } else {
475 ret = make_server_info_pw(&server_info, real_username, pw);
477 if ( !NT_STATUS_IS_OK(ret) ) {
478 DEBUG(1,("make_server_info_pw failed: %s!\n",
479 nt_errstr(ret)));
480 SAFE_FREE(client);
481 data_blob_free(&ap_rep);
482 data_blob_free(&session_key);
483 TALLOC_FREE(mem_ctx);
484 return ERROR_NT(nt_status_squash(ret));
487 /* make_server_info_pw does not set the domain. Without this
488 * we end up with the local netbios name in substitutions for
489 * %D. */
491 if (server_info->sam_account != NULL) {
492 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
496 server_info->was_mapped |= username_was_mapped;
498 /* we need to build the token for the user. make_server_info_guest()
499 already does this */
501 if ( !server_info->ptok ) {
502 ret = create_local_token( server_info );
503 if ( !NT_STATUS_IS_OK(ret) ) {
504 SAFE_FREE(client);
505 data_blob_free(&ap_rep);
506 data_blob_free(&session_key);
507 TALLOC_FREE( mem_ctx );
508 TALLOC_FREE( server_info );
509 return ERROR_NT(nt_status_squash(ret));
513 /* register_vuid keeps the server info */
514 /* register_vuid takes ownership of session_key, no need to free after this.
515 A better interface would copy it.... */
516 sess_vuid = register_vuid(server_info, session_key, nullblob, client);
518 SAFE_FREE(client);
520 if (sess_vuid == UID_FIELD_INVALID ) {
521 ret = NT_STATUS_LOGON_FAILURE;
522 } else {
523 /* current_user_info is changed on new vuid */
524 reload_services( True );
526 set_message(inbuf,outbuf,4,0,True);
527 SSVAL(outbuf, smb_vwv3, 0);
529 if (server_info->guest) {
530 SSVAL(outbuf,smb_vwv2,1);
533 SSVAL(outbuf, smb_uid, sess_vuid);
535 sessionsetup_start_signing_engine(server_info, inbuf);
538 /* wrap that up in a nice GSS-API wrapping */
539 if (NT_STATUS_IS_OK(ret)) {
540 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
541 } else {
542 ap_rep_wrapped = data_blob_null;
544 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
545 reply_sesssetup_blob(conn, inbuf, outbuf, response, ret);
547 data_blob_free(&ap_rep);
548 data_blob_free(&ap_rep_wrapped);
549 data_blob_free(&response);
550 TALLOC_FREE(mem_ctx);
552 return -1; /* already replied */
554 #endif
556 /****************************************************************************
557 Send a session setup reply, wrapped in SPNEGO.
558 Get vuid and check first.
559 End the NTLMSSP exchange context if we are OK/complete fail
560 This should be split into two functions, one to handle each
561 leg of the NTLM auth steps.
562 ***************************************************************************/
564 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
565 uint16 vuid,
566 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
567 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
568 BOOL wrap)
570 BOOL ret;
571 DATA_BLOB response;
572 struct auth_serversupplied_info *server_info = NULL;
574 if (NT_STATUS_IS_OK(nt_status)) {
575 server_info = (*auth_ntlmssp_state)->server_info;
576 } else {
577 nt_status = do_map_to_guest(nt_status,
578 &server_info,
579 (*auth_ntlmssp_state)->ntlmssp_state->user,
580 (*auth_ntlmssp_state)->ntlmssp_state->domain);
583 if (NT_STATUS_IS_OK(nt_status)) {
584 int sess_vuid;
585 DATA_BLOB nullblob = data_blob_null;
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 set_message(inbuf,outbuf,4,0,True);
600 SSVAL(outbuf, smb_vwv3, 0);
602 if (server_info->guest) {
603 SSVAL(outbuf,smb_vwv2,1);
606 SSVAL(outbuf,smb_uid,sess_vuid);
608 sessionsetup_start_signing_engine(server_info, inbuf);
612 if (wrap) {
613 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
614 } else {
615 response = *ntlmssp_blob;
618 ret = reply_sesssetup_blob(conn, inbuf, outbuf, response, nt_status);
619 if (wrap) {
620 data_blob_free(&response);
623 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
624 and the other end, that we are not finished yet. */
626 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
627 /* NB. This is *NOT* an error case. JRA */
628 auth_ntlmssp_end(auth_ntlmssp_state);
629 /* Kill the intermediate vuid */
630 invalidate_vuid(vuid);
633 return ret;
636 /****************************************************************************
637 Is this a krb5 mechanism ?
638 ****************************************************************************/
640 NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, BOOL *p_is_krb5)
642 char *OIDs[ASN1_MAX_OIDS];
643 int i;
645 *p_is_krb5 = False;
647 /* parse out the OIDs and the first sec blob */
648 if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
649 return NT_STATUS_LOGON_FAILURE;
652 /* only look at the first OID for determining the mechToken --
653 accoirding to RFC2478, we should choose the one we want
654 and renegotiate, but i smell a client bug here..
656 Problem observed when connecting to a member (samba box)
657 of an AD domain as a user in a Samba domain. Samba member
658 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
659 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
660 NTLMSSP mechtoken. --jerry */
662 #ifdef HAVE_KRB5
663 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
664 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
665 *p_is_krb5 = True;
667 #endif
669 for (i=0;OIDs[i];i++) {
670 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
671 free(OIDs[i]);
673 return NT_STATUS_OK;
676 /****************************************************************************
677 Reply to a session setup spnego negotiate packet.
678 ****************************************************************************/
680 static int reply_spnego_negotiate(connection_struct *conn,
681 char *inbuf,
682 char *outbuf,
683 uint16 vuid,
684 int length, int bufsize,
685 DATA_BLOB blob1,
686 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
688 DATA_BLOB secblob;
689 DATA_BLOB chal;
690 BOOL got_kerberos_mechanism = False;
691 NTSTATUS status;
693 status = parse_spnego_mechanisms(blob1, &secblob, &got_kerberos_mechanism);
694 if (!NT_STATUS_IS_OK(status)) {
695 /* Kill the intermediate vuid */
696 invalidate_vuid(vuid);
697 return ERROR_NT(nt_status_squash(status));
700 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n", (unsigned long)secblob.length));
702 #ifdef HAVE_KRB5
703 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
704 BOOL destroy_vuid = True;
705 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
706 length, bufsize, &secblob, &destroy_vuid);
707 data_blob_free(&secblob);
708 if (destroy_vuid) {
709 /* Kill the intermediate vuid */
710 invalidate_vuid(vuid);
712 return ret;
714 #endif
716 if (*auth_ntlmssp_state) {
717 auth_ntlmssp_end(auth_ntlmssp_state);
720 status = auth_ntlmssp_start(auth_ntlmssp_state);
721 if (!NT_STATUS_IS_OK(status)) {
722 /* Kill the intermediate vuid */
723 invalidate_vuid(vuid);
724 return ERROR_NT(nt_status_squash(status));
727 status = auth_ntlmssp_update(*auth_ntlmssp_state,
728 secblob, &chal);
730 data_blob_free(&secblob);
732 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
733 &chal, status, True);
735 data_blob_free(&chal);
737 /* already replied */
738 return -1;
741 /****************************************************************************
742 Reply to a session setup spnego auth packet.
743 ****************************************************************************/
745 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
746 uint16 vuid,
747 int length, int bufsize,
748 DATA_BLOB blob1,
749 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
751 DATA_BLOB auth = data_blob_null;
752 DATA_BLOB auth_reply = data_blob_null;
753 DATA_BLOB secblob = data_blob_null;
754 NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
756 if (!spnego_parse_auth(blob1, &auth)) {
757 #if 0
758 file_save("auth.dat", blob1.data, blob1.length);
759 #endif
760 /* Kill the intermediate vuid */
761 invalidate_vuid(vuid);
763 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
766 if (auth.data[0] == ASN1_APPLICATION(0)) {
767 /* Might be a second negTokenTarg packet */
769 BOOL got_krb5_mechanism = False;
770 status = parse_spnego_mechanisms(auth, &secblob, &got_krb5_mechanism);
771 if (NT_STATUS_IS_OK(status)) {
772 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n", (unsigned long)secblob.length));
773 #ifdef HAVE_KRB5
774 if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
775 BOOL destroy_vuid = True;
776 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
777 length, bufsize, &secblob, &destroy_vuid);
778 data_blob_free(&secblob);
779 data_blob_free(&auth);
780 if (destroy_vuid) {
781 /* Kill the intermediate vuid */
782 invalidate_vuid(vuid);
784 return ret;
786 #endif
790 /* If we get here it wasn't a negTokenTarg auth packet. */
791 data_blob_free(&secblob);
793 if (!*auth_ntlmssp_state) {
794 /* Kill the intermediate vuid */
795 invalidate_vuid(vuid);
797 /* auth before negotiatiate? */
798 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
801 status = auth_ntlmssp_update(*auth_ntlmssp_state,
802 auth, &auth_reply);
804 data_blob_free(&auth);
806 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
807 auth_ntlmssp_state,
808 &auth_reply, status, True);
810 data_blob_free(&auth_reply);
812 /* and tell smbd that we have already replied to this packet */
813 return -1;
816 /****************************************************************************
817 List to store partial SPNEGO auth fragments.
818 ****************************************************************************/
820 static struct pending_auth_data *pd_list;
822 /****************************************************************************
823 Delete an entry on the list.
824 ****************************************************************************/
826 static void delete_partial_auth(struct pending_auth_data *pad)
828 if (!pad) {
829 return;
831 DLIST_REMOVE(pd_list, pad);
832 data_blob_free(&pad->partial_data);
833 SAFE_FREE(pad);
836 /****************************************************************************
837 Search for a partial SPNEGO auth fragment matching an smbpid.
838 ****************************************************************************/
840 static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
842 struct pending_auth_data *pad;
844 for (pad = pd_list; pad; pad = pad->next) {
845 if (pad->smbpid == smbpid) {
846 break;
849 return pad;
852 /****************************************************************************
853 Check the size of an SPNEGO blob. If we need more return NT_STATUS_MORE_PROCESSING_REQUIRED,
854 else return NT_STATUS_OK. Don't allow the blob to be more than 64k.
855 ****************************************************************************/
857 static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB *pblob)
859 struct pending_auth_data *pad = NULL;
860 ASN1_DATA data;
861 size_t needed_len = 0;
863 pad = get_pending_auth_data(smbpid);
865 /* Ensure we have some data. */
866 if (pblob->length == 0) {
867 /* Caller can cope. */
868 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
869 delete_partial_auth(pad);
870 return NT_STATUS_OK;
873 /* Were we waiting for more data ? */
874 if (pad) {
875 DATA_BLOB tmp_blob;
876 size_t copy_len = MIN(65536, pblob->length);
878 /* Integer wrap paranoia.... */
880 if (pad->partial_data.length + copy_len < pad->partial_data.length ||
881 pad->partial_data.length + copy_len < copy_len) {
883 DEBUG(2,("check_spnego_blob_complete: integer wrap "
884 "pad->partial_data.length = %u, "
885 "copy_len = %u\n",
886 (unsigned int)pad->partial_data.length,
887 (unsigned int)copy_len ));
889 delete_partial_auth(pad);
890 return NT_STATUS_INVALID_PARAMETER;
893 DEBUG(10,("check_spnego_blob_complete: "
894 "pad->partial_data.length = %u, "
895 "pad->needed_len = %u, "
896 "copy_len = %u, "
897 "pblob->length = %u,\n",
898 (unsigned int)pad->partial_data.length,
899 (unsigned int)pad->needed_len,
900 (unsigned int)copy_len,
901 (unsigned int)pblob->length ));
903 tmp_blob = data_blob(NULL,
904 pad->partial_data.length + copy_len);
906 /* Concatenate the two (up to copy_len) bytes. */
907 memcpy(tmp_blob.data,
908 pad->partial_data.data,
909 pad->partial_data.length);
910 memcpy(tmp_blob.data + pad->partial_data.length,
911 pblob->data,
912 copy_len);
914 /* Replace the partial data. */
915 data_blob_free(&pad->partial_data);
916 pad->partial_data = tmp_blob;
917 ZERO_STRUCT(tmp_blob);
919 /* Are we done ? */
920 if (pblob->length >= pad->needed_len) {
921 /* Yes, replace pblob. */
922 data_blob_free(pblob);
923 *pblob = pad->partial_data;
924 ZERO_STRUCT(pad->partial_data);
925 delete_partial_auth(pad);
926 return NT_STATUS_OK;
929 /* Still need more data. */
930 pad->needed_len -= copy_len;
931 return NT_STATUS_MORE_PROCESSING_REQUIRED;
934 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
935 (pblob->data[0] != ASN1_CONTEXT(1))) {
936 /* Not something we can determine the
937 * length of.
939 return NT_STATUS_OK;
942 /* This is a new SPNEGO sessionsetup - see if
943 * the data given in this blob is enough.
946 asn1_load(&data, *pblob);
947 asn1_start_tag(&data, pblob->data[0]);
948 if (data.has_error || data.nesting == NULL) {
949 asn1_free(&data);
950 /* Let caller catch. */
951 return NT_STATUS_OK;
954 /* Integer wrap paranoia.... */
956 if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
957 data.nesting->taglen + data.nesting->start < data.nesting->start) {
959 DEBUG(2,("check_spnego_blob_complete: integer wrap "
960 "data.nesting->taglen = %u, "
961 "data.nesting->start = %u\n",
962 (unsigned int)data.nesting->taglen,
963 (unsigned int)data.nesting->start ));
965 asn1_free(&data);
966 return NT_STATUS_INVALID_PARAMETER;
969 /* Total length of the needed asn1 is the tag length
970 * plus the current offset. */
972 needed_len = data.nesting->taglen + data.nesting->start;
973 asn1_free(&data);
975 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
976 "pblob->length = %u\n",
977 (unsigned int)needed_len,
978 (unsigned int)pblob->length ));
980 if (needed_len <= pblob->length) {
981 /* Nothing to do - blob is complete. */
982 return NT_STATUS_OK;
985 /* Refuse the blob if it's bigger than 64k. */
986 if (needed_len > 65536) {
987 DEBUG(2,("check_spnego_blob_complete: needed_len too large (%u)\n",
988 (unsigned int)needed_len ));
989 return NT_STATUS_INVALID_PARAMETER;
992 /* We must store this blob until complete. */
993 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
994 return NT_STATUS_NO_MEMORY;
996 pad->needed_len = needed_len - pblob->length;
997 pad->partial_data = data_blob(pblob->data, pblob->length);
998 if (pad->partial_data.data == NULL) {
999 SAFE_FREE(pad);
1000 return NT_STATUS_NO_MEMORY;
1002 pad->smbpid = smbpid;
1003 pad->vuid = vuid;
1004 DLIST_ADD(pd_list, pad);
1006 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1009 /****************************************************************************
1010 Reply to a session setup command.
1011 conn POINTER CAN BE NULL HERE !
1012 ****************************************************************************/
1014 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
1015 char *outbuf,
1016 int length,int bufsize)
1018 uint8 *p;
1019 DATA_BLOB blob1;
1020 int ret;
1021 size_t bufrem;
1022 fstring native_os, native_lanman, primary_domain;
1023 char *p2;
1024 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
1025 enum remote_arch_types ra_type = get_remote_arch();
1026 int vuid = SVAL(inbuf,smb_uid);
1027 user_struct *vuser = NULL;
1028 NTSTATUS status = NT_STATUS_OK;
1029 uint16 smbpid = SVAL(inbuf,smb_pid);
1031 DEBUG(3,("Doing spnego session setup\n"));
1033 if (global_client_caps == 0) {
1034 global_client_caps = IVAL(inbuf,smb_vwv10);
1036 if (!(global_client_caps & CAP_STATUS32)) {
1037 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1042 p = (uint8 *)smb_buf(inbuf);
1044 if (data_blob_len == 0) {
1045 /* an invalid request */
1046 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1049 bufrem = smb_bufrem(inbuf, p);
1050 /* pull the spnego blob */
1051 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1053 #if 0
1054 file_save("negotiate.dat", blob1.data, blob1.length);
1055 #endif
1057 p2 = inbuf + smb_vwv13 + data_blob_len;
1058 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
1059 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
1060 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
1061 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1062 native_os, native_lanman, primary_domain));
1064 if ( ra_type == RA_WIN2K ) {
1065 /* Vista sets neither the OS or lanman strings */
1067 if ( !strlen(native_os) && !strlen(native_lanman) )
1068 set_remote_arch(RA_VISTA);
1070 /* Windows 2003 doesn't set the native lanman string,
1071 but does set primary domain which is a bug I think */
1073 if ( !strlen(native_lanman) ) {
1074 ra_lanman_string( primary_domain );
1075 } else {
1076 ra_lanman_string( native_lanman );
1080 vuser = get_partial_auth_user_struct(vuid);
1081 if (!vuser) {
1082 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
1083 if (pad) {
1084 DEBUG(10,("reply_sesssetup_and_X_spnego: found pending vuid %u\n",
1085 (unsigned int)pad->vuid ));
1086 vuid = pad->vuid;
1087 vuser = get_partial_auth_user_struct(vuid);
1091 if (!vuser) {
1092 vuid = register_vuid(NULL, data_blob_null, data_blob_null, NULL);
1093 if (vuid == UID_FIELD_INVALID ) {
1094 data_blob_free(&blob1);
1095 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1098 vuser = get_partial_auth_user_struct(vuid);
1101 if (!vuser) {
1102 data_blob_free(&blob1);
1103 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1106 SSVAL(outbuf,smb_uid,vuid);
1108 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1109 * sessionsetup requests as the Windows limit on the security blob
1110 * field is 4k. Bug #4400. JRA.
1113 status = check_spnego_blob_complete(smbpid, vuid, &blob1);
1114 if (!NT_STATUS_IS_OK(status)) {
1115 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1116 /* Real error - kill the intermediate vuid */
1117 invalidate_vuid(vuid);
1119 data_blob_free(&blob1);
1120 return ERROR_NT(nt_status_squash(status));
1123 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1124 /* its a negTokenTarg packet */
1125 ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
1126 &vuser->auth_ntlmssp_state);
1127 data_blob_free(&blob1);
1128 return ret;
1131 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1132 /* its a auth packet */
1133 ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
1134 &vuser->auth_ntlmssp_state);
1135 data_blob_free(&blob1);
1136 return ret;
1139 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1140 DATA_BLOB chal;
1141 if (!vuser->auth_ntlmssp_state) {
1142 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1143 if (!NT_STATUS_IS_OK(status)) {
1144 /* Kill the intermediate vuid */
1145 invalidate_vuid(vuid);
1146 data_blob_free(&blob1);
1147 return ERROR_NT(nt_status_squash(status));
1151 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1152 blob1, &chal);
1154 data_blob_free(&blob1);
1156 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
1157 &vuser->auth_ntlmssp_state,
1158 &chal, status, False);
1159 data_blob_free(&chal);
1160 return -1;
1163 /* what sort of packet is this? */
1164 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1166 data_blob_free(&blob1);
1168 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1171 /****************************************************************************
1172 On new VC == 0, shutdown *all* old connections and users.
1173 It seems that only NT4.x does this. At W2K and above (XP etc.).
1174 a new session setup with VC==0 is ignored.
1175 ****************************************************************************/
1177 static int shutdown_other_smbds(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
1178 void *p)
1180 struct sessionid *sessionid = (struct sessionid *)dbuf.dptr;
1181 const char *ip = (const char *)p;
1183 if (!process_exists(sessionid->pid)) {
1184 return 0;
1187 if (procid_is_me(&sessionid->pid)) {
1188 return 0;
1191 if (strcmp(ip, sessionid->ip_addr) != 0) {
1192 return 0;
1195 messaging_send(smbd_messaging_context(), sessionid->pid, MSG_SHUTDOWN,
1196 &data_blob_null);
1197 return 0;
1200 static void setup_new_vc_session(void)
1202 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
1203 #if 0
1204 conn_close_all();
1205 invalidate_all_vuids();
1206 #endif
1207 if (lp_reset_on_zero_vc()) {
1208 session_traverse(shutdown_other_smbds, client_addr());
1212 /****************************************************************************
1213 Reply to a session setup command.
1214 ****************************************************************************/
1216 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
1217 int length,int bufsize)
1219 int sess_vuid;
1220 int smb_bufsize;
1221 DATA_BLOB lm_resp;
1222 DATA_BLOB nt_resp;
1223 DATA_BLOB plaintext_password;
1224 fstring user;
1225 fstring sub_user; /* Sainitised username for substituion */
1226 fstring domain;
1227 fstring native_os;
1228 fstring native_lanman;
1229 fstring primary_domain;
1230 static BOOL done_sesssetup = False;
1231 auth_usersupplied_info *user_info = NULL;
1232 auth_serversupplied_info *server_info = NULL;
1234 NTSTATUS nt_status;
1236 BOOL doencrypt = global_encrypted_passwords_negotiated;
1238 DATA_BLOB session_key;
1240 START_PROFILE(SMBsesssetupX);
1242 ZERO_STRUCT(lm_resp);
1243 ZERO_STRUCT(nt_resp);
1244 ZERO_STRUCT(plaintext_password);
1246 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
1248 /* a SPNEGO session setup has 12 command words, whereas a normal
1249 NT1 session setup has 13. See the cifs spec. */
1250 if (CVAL(inbuf, smb_wct) == 12 &&
1251 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
1252 if (!global_spnego_negotiated) {
1253 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
1254 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1257 if (SVAL(inbuf,smb_vwv4) == 0) {
1258 setup_new_vc_session();
1260 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
1263 smb_bufsize = SVAL(inbuf,smb_vwv2);
1265 if (Protocol < PROTOCOL_NT1) {
1266 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
1268 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
1269 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1271 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
1272 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1275 if (doencrypt) {
1276 lm_resp = data_blob(smb_buf(inbuf), passlen1);
1277 } else {
1278 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
1279 /* Ensure null termination */
1280 plaintext_password.data[passlen1] = 0;
1283 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
1284 *domain = 0;
1286 } else {
1287 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
1288 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
1289 enum remote_arch_types ra_type = get_remote_arch();
1290 char *p = smb_buf(inbuf);
1291 char *save_p = smb_buf(inbuf);
1292 uint16 byte_count;
1295 if(global_client_caps == 0) {
1296 global_client_caps = IVAL(inbuf,smb_vwv11);
1298 if (!(global_client_caps & CAP_STATUS32)) {
1299 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1302 /* client_caps is used as final determination if client is NT or Win95.
1303 This is needed to return the correct error codes in some
1304 circumstances.
1307 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
1308 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
1309 set_remote_arch( RA_WIN95);
1314 if (!doencrypt) {
1315 /* both Win95 and WinNT stuff up the password lengths for
1316 non-encrypting systems. Uggh.
1318 if passlen1==24 its a win95 system, and its setting the
1319 password length incorrectly. Luckily it still works with the
1320 default code because Win95 will null terminate the password
1321 anyway
1323 if passlen1>0 and passlen2>0 then maybe its a NT box and its
1324 setting passlen2 to some random value which really stuffs
1325 things up. we need to fix that one. */
1327 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
1328 passlen2 = 0;
1331 /* check for nasty tricks */
1332 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
1333 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1336 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
1337 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1340 /* Save the lanman2 password and the NT md4 password. */
1342 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1343 doencrypt = False;
1346 if (doencrypt) {
1347 lm_resp = data_blob(p, passlen1);
1348 nt_resp = data_blob(p+passlen1, passlen2);
1349 } else {
1350 pstring pass;
1351 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
1353 #if 0
1354 /* This was the previous fix. Not sure if it's still valid. JRA. */
1355 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
1356 /* NT4.0 stuffs up plaintext unicode password lengths... */
1357 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
1358 sizeof(pass), passlen1, STR_TERMINATE);
1359 #endif
1361 if (unic && (passlen2 == 0) && passlen1) {
1362 /* Only a ascii plaintext password was sent. */
1363 srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
1364 passlen1, STR_TERMINATE|STR_ASCII);
1365 } else {
1366 srvstr_pull(inbuf, pass, smb_buf(inbuf),
1367 sizeof(pass), unic ? passlen2 : passlen1,
1368 STR_TERMINATE);
1370 plaintext_password = data_blob(pass, strlen(pass)+1);
1373 p += passlen1 + passlen2;
1374 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
1375 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
1376 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
1377 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
1379 /* not documented or decoded by Ethereal but there is one more string
1380 in the extra bytes which is the same as the PrimaryDomain when using
1381 extended security. Windows NT 4 and 2003 use this string to store
1382 the native lanman string. Windows 9x does not include a string here
1383 at all so we have to check if we have any extra bytes left */
1385 byte_count = SVAL(inbuf, smb_vwv13);
1386 if ( PTR_DIFF(p, save_p) < byte_count)
1387 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
1388 else
1389 fstrcpy( primary_domain, "null" );
1391 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1392 domain, native_os, native_lanman, primary_domain));
1394 if ( ra_type == RA_WIN2K ) {
1395 if ( strlen(native_lanman) == 0 )
1396 ra_lanman_string( primary_domain );
1397 else
1398 ra_lanman_string( native_lanman );
1403 if (SVAL(inbuf,smb_vwv4) == 0) {
1404 setup_new_vc_session();
1407 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
1409 if (*user) {
1410 if (global_spnego_negotiated) {
1412 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
1414 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
1415 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1417 fstrcpy(sub_user, user);
1418 } else {
1419 fstrcpy(sub_user, lp_guestaccount());
1422 sub_set_smb_name(sub_user);
1424 reload_services(True);
1426 if (lp_security() == SEC_SHARE) {
1427 /* in share level we should ignore any passwords */
1429 data_blob_free(&lm_resp);
1430 data_blob_free(&nt_resp);
1431 data_blob_clear_free(&plaintext_password);
1433 map_username(sub_user);
1434 add_session_user(sub_user);
1435 add_session_workgroup(domain);
1436 /* Then force it to null for the benfit of the code below */
1437 *user = 0;
1440 if (!*user) {
1442 nt_status = check_guest_password(&server_info);
1444 } else if (doencrypt) {
1445 if (!negprot_global_auth_context) {
1446 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
1447 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1449 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
1450 lm_resp, nt_resp);
1451 if (NT_STATUS_IS_OK(nt_status)) {
1452 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
1453 user_info,
1454 &server_info);
1456 } else {
1457 struct auth_context *plaintext_auth_context = NULL;
1458 const uint8 *chal;
1460 nt_status = make_auth_context_subsystem(&plaintext_auth_context);
1462 if (NT_STATUS_IS_OK(nt_status)) {
1463 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
1465 if (!make_user_info_for_reply(&user_info,
1466 user, domain, chal,
1467 plaintext_password)) {
1468 nt_status = NT_STATUS_NO_MEMORY;
1471 if (NT_STATUS_IS_OK(nt_status)) {
1472 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
1473 user_info,
1474 &server_info);
1476 (plaintext_auth_context->free)(&plaintext_auth_context);
1481 free_user_info(&user_info);
1483 if (!NT_STATUS_IS_OK(nt_status)) {
1484 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
1487 if (!NT_STATUS_IS_OK(nt_status)) {
1488 data_blob_free(&nt_resp);
1489 data_blob_free(&lm_resp);
1490 data_blob_clear_free(&plaintext_password);
1491 return ERROR_NT(nt_status_squash(nt_status));
1494 /* Ensure we can't possible take a code path leading to a null defref. */
1495 if (!server_info) {
1496 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1499 nt_status = create_local_token(server_info);
1500 if (!NT_STATUS_IS_OK(nt_status)) {
1501 DEBUG(10, ("create_local_token failed: %s\n",
1502 nt_errstr(nt_status)));
1503 data_blob_free(&nt_resp);
1504 data_blob_free(&lm_resp);
1505 data_blob_clear_free(&plaintext_password);
1506 return ERROR_NT(nt_status_squash(nt_status));
1509 if (server_info->user_session_key.data) {
1510 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
1511 } else {
1512 session_key = data_blob_null;
1515 data_blob_clear_free(&plaintext_password);
1517 /* it's ok - setup a reply */
1518 set_message(inbuf,outbuf,3,0,True);
1519 if (Protocol >= PROTOCOL_NT1) {
1520 char *p = smb_buf( outbuf );
1521 p += add_signature( outbuf, p );
1522 set_message_end(inbuf, outbuf, p );
1523 /* perhaps grab OS version here?? */
1526 if (server_info->guest) {
1527 SSVAL(outbuf,smb_vwv2,1);
1530 /* register the name and uid as being validated, so further connections
1531 to a uid can get through without a password, on the same VC */
1533 if (lp_security() == SEC_SHARE) {
1534 sess_vuid = UID_FIELD_INVALID;
1535 data_blob_free(&session_key);
1536 TALLOC_FREE(server_info);
1537 } else {
1538 /* register_vuid keeps the server info */
1539 sess_vuid = register_vuid(server_info, session_key,
1540 nt_resp.data ? nt_resp : lm_resp,
1541 sub_user);
1542 if (sess_vuid == UID_FIELD_INVALID) {
1543 data_blob_free(&nt_resp);
1544 data_blob_free(&lm_resp);
1545 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1548 /* current_user_info is changed on new vuid */
1549 reload_services( True );
1551 sessionsetup_start_signing_engine(server_info, inbuf);
1554 data_blob_free(&nt_resp);
1555 data_blob_free(&lm_resp);
1557 SSVAL(outbuf,smb_uid,sess_vuid);
1558 SSVAL(inbuf,smb_uid,sess_vuid);
1560 if (!done_sesssetup)
1561 max_send = MIN(max_send,smb_bufsize);
1563 done_sesssetup = True;
1565 END_PROFILE(SMBsesssetupX);
1566 return chain_reply(inbuf,outbuf,length,bufsize);