r23510: Tidy calls to smb_panic by removing trailing newlines. Print the
[Samba.git] / source3 / smbd / sesssetup.c
blob22c598a6547db45ee0cd2338afd5d53deedd83cc
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,
274 &client, &pac_data, &ap_rep,
275 &session_key, True);
277 data_blob_free(&ticket);
279 if (!NT_STATUS_IS_OK(ret)) {
280 #if 0
281 /* Experiment that failed. See "only happens with a KDC" comment below. */
283 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
286 * Windows in this case returns NT_STATUS_MORE_PROCESSING_REQUIRED
287 * with a negTokenTarg blob containing an krb5_error struct ASN1 encoded
288 * containing KRB5KRB_AP_ERR_SKEW. The client then fixes its
289 * clock and continues rather than giving an error. JRA.
290 * -- Looks like this only happens with a KDC. JRA.
293 BOOL ok = make_krb5_skew_error(&ap_rep);
294 if (!ok) {
295 talloc_destroy(mem_ctx);
296 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
298 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_ERROR);
299 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
300 reply_sesssetup_blob(conn, inbuf, outbuf, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
303 * In this one case we don't invalidate the intermediate vuid.
304 * as we're expecting the client to re-use it for the next
305 * sessionsetupX packet. JRA.
308 *p_invalidate_vuid = False;
310 data_blob_free(&ap_rep);
311 data_blob_free(&ap_rep_wrapped);
312 data_blob_free(&response);
313 talloc_destroy(mem_ctx);
314 return -1; /* already replied */
316 #else
317 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
318 ret = NT_STATUS_LOGON_FAILURE;
320 #endif
321 DEBUG(1,("Failed to verify incoming ticket with error %s!\n", nt_errstr(ret)));
322 talloc_destroy(mem_ctx);
323 return ERROR_NT(nt_status_squash(ret));
326 DEBUG(3,("Ticket name is [%s]\n", client));
328 p = strchr_m(client, '@');
329 if (!p) {
330 DEBUG(3,("Doesn't look like a valid principal\n"));
331 data_blob_free(&ap_rep);
332 data_blob_free(&session_key);
333 SAFE_FREE(client);
334 talloc_destroy(mem_ctx);
335 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
338 *p = 0;
340 /* save the PAC data if we have it */
342 if (pac_data) {
343 logon_info = get_logon_info_from_pac(pac_data);
344 if (logon_info) {
345 netsamlogon_cache_store( client, &logon_info->info3 );
349 if (!strequal(p+1, lp_realm())) {
350 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
351 if (!lp_allow_trusted_domains()) {
352 data_blob_free(&ap_rep);
353 data_blob_free(&session_key);
354 SAFE_FREE(client);
355 talloc_destroy(mem_ctx);
356 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
360 /* this gives a fully qualified user name (ie. with full realm).
361 that leads to very long usernames, but what else can we do? */
363 domain = p+1;
365 if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) {
367 unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, -1);
368 domain = netbios_domain_name;
369 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
371 } else {
373 /* If we have winbind running, we can (and must) shorten the
374 username by using the short netbios name. Otherwise we will
375 have inconsistent user names. With Kerberos, we get the
376 fully qualified realm, with ntlmssp we get the short
377 name. And even w2k3 does use ntlmssp if you for example
378 connect to an ip address. */
380 struct winbindd_request wb_request;
381 struct winbindd_response wb_response;
382 NSS_STATUS wb_result;
384 ZERO_STRUCT(wb_request);
385 ZERO_STRUCT(wb_response);
387 DEBUG(10, ("Mapping [%s] to short name\n", domain));
389 fstrcpy(wb_request.domain_name, domain);
391 wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
392 &wb_request, &wb_response);
394 if (wb_result == NSS_STATUS_SUCCESS) {
396 fstrcpy(netbios_domain_name,
397 wb_response.data.domain_info.name);
398 domain = netbios_domain_name;
400 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
401 } else {
402 DEBUG(3, ("Could not find short name -- winbind "
403 "not running?\n"));
407 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
409 /* lookup the passwd struct, create a new user if necessary */
411 username_was_mapped = map_username( user );
413 pw = smb_getpwnam( mem_ctx, user, real_username, True );
415 if (pw) {
416 /* if a real user check pam account restrictions */
417 /* only really perfomed if "obey pam restriction" is true */
418 /* do this before an eventual mappign to guest occurs */
419 ret = smb_pam_accountcheck(pw->pw_name);
420 if ( !NT_STATUS_IS_OK(ret)) {
421 DEBUG(1, ("PAM account restriction prevents user login\n"));
422 data_blob_free(&ap_rep);
423 data_blob_free(&session_key);
424 TALLOC_FREE(mem_ctx);
425 return ERROR_NT(nt_status_squash(ret));
429 if (!pw) {
431 /* this was originally the behavior of Samba 2.2, if a user
432 did not have a local uid but has been authenticated, then
433 map them to a guest account */
435 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
436 map_domainuser_to_guest = True;
437 fstrcpy(user,lp_guestaccount());
438 pw = smb_getpwnam( mem_ctx, user, real_username, True );
441 /* extra sanity check that the guest account is valid */
443 if ( !pw ) {
444 DEBUG(1,("Username %s is invalid on this system\n", user));
445 SAFE_FREE(client);
446 data_blob_free(&ap_rep);
447 data_blob_free(&session_key);
448 TALLOC_FREE(mem_ctx);
449 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
453 /* setup the string used by %U */
455 sub_set_smb_name( real_username );
456 reload_services(True);
458 if ( map_domainuser_to_guest ) {
459 make_server_info_guest(&server_info);
460 } else if (logon_info) {
461 /* pass the unmapped username here since map_username()
462 will be called again from inside make_server_info_info3() */
464 ret = make_server_info_info3(mem_ctx, client, domain,
465 &server_info, &logon_info->info3);
466 if ( !NT_STATUS_IS_OK(ret) ) {
467 DEBUG(1,("make_server_info_info3 failed: %s!\n",
468 nt_errstr(ret)));
469 SAFE_FREE(client);
470 data_blob_free(&ap_rep);
471 data_blob_free(&session_key);
472 TALLOC_FREE(mem_ctx);
473 return ERROR_NT(nt_status_squash(ret));
476 } else {
477 ret = make_server_info_pw(&server_info, real_username, pw);
479 if ( !NT_STATUS_IS_OK(ret) ) {
480 DEBUG(1,("make_server_info_pw failed: %s!\n",
481 nt_errstr(ret)));
482 SAFE_FREE(client);
483 data_blob_free(&ap_rep);
484 data_blob_free(&session_key);
485 TALLOC_FREE(mem_ctx);
486 return ERROR_NT(nt_status_squash(ret));
489 /* make_server_info_pw does not set the domain. Without this
490 * we end up with the local netbios name in substitutions for
491 * %D. */
493 if (server_info->sam_account != NULL) {
494 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
498 server_info->was_mapped |= username_was_mapped;
500 /* we need to build the token for the user. make_server_info_guest()
501 already does this */
503 if ( !server_info->ptok ) {
504 ret = create_local_token( server_info );
505 if ( !NT_STATUS_IS_OK(ret) ) {
506 SAFE_FREE(client);
507 data_blob_free(&ap_rep);
508 data_blob_free(&session_key);
509 TALLOC_FREE( mem_ctx );
510 TALLOC_FREE( server_info );
511 return ERROR_NT(nt_status_squash(ret));
515 /* register_vuid keeps the server info */
516 /* register_vuid takes ownership of session_key, no need to free after this.
517 A better interface would copy it.... */
518 sess_vuid = register_vuid(server_info, session_key, nullblob, client);
520 SAFE_FREE(client);
522 if (sess_vuid == UID_FIELD_INVALID ) {
523 ret = NT_STATUS_LOGON_FAILURE;
524 } else {
525 /* current_user_info is changed on new vuid */
526 reload_services( True );
528 set_message(inbuf,outbuf,4,0,True);
529 SSVAL(outbuf, smb_vwv3, 0);
531 if (server_info->guest) {
532 SSVAL(outbuf,smb_vwv2,1);
535 SSVAL(outbuf, smb_uid, sess_vuid);
537 sessionsetup_start_signing_engine(server_info, inbuf);
540 /* wrap that up in a nice GSS-API wrapping */
541 if (NT_STATUS_IS_OK(ret)) {
542 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
543 } else {
544 ap_rep_wrapped = data_blob_null;
546 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
547 reply_sesssetup_blob(conn, inbuf, outbuf, response, ret);
549 data_blob_free(&ap_rep);
550 data_blob_free(&ap_rep_wrapped);
551 data_blob_free(&response);
552 TALLOC_FREE(mem_ctx);
554 return -1; /* already replied */
556 #endif
558 /****************************************************************************
559 Send a session setup reply, wrapped in SPNEGO.
560 Get vuid and check first.
561 End the NTLMSSP exchange context if we are OK/complete fail
562 This should be split into two functions, one to handle each
563 leg of the NTLM auth steps.
564 ***************************************************************************/
566 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
567 uint16 vuid,
568 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
569 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
570 BOOL wrap)
572 BOOL ret;
573 DATA_BLOB response;
574 struct auth_serversupplied_info *server_info = NULL;
576 if (NT_STATUS_IS_OK(nt_status)) {
577 server_info = (*auth_ntlmssp_state)->server_info;
578 } else {
579 nt_status = do_map_to_guest(nt_status,
580 &server_info,
581 (*auth_ntlmssp_state)->ntlmssp_state->user,
582 (*auth_ntlmssp_state)->ntlmssp_state->domain);
585 if (NT_STATUS_IS_OK(nt_status)) {
586 int sess_vuid;
587 DATA_BLOB nullblob = data_blob_null;
588 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
590 /* register_vuid keeps the server info */
591 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
592 (*auth_ntlmssp_state)->server_info = NULL;
594 if (sess_vuid == UID_FIELD_INVALID ) {
595 nt_status = NT_STATUS_LOGON_FAILURE;
596 } else {
598 /* current_user_info is changed on new vuid */
599 reload_services( True );
601 set_message(inbuf,outbuf,4,0,True);
602 SSVAL(outbuf, smb_vwv3, 0);
604 if (server_info->guest) {
605 SSVAL(outbuf,smb_vwv2,1);
608 SSVAL(outbuf,smb_uid,sess_vuid);
610 sessionsetup_start_signing_engine(server_info, inbuf);
614 if (wrap) {
615 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
616 } else {
617 response = *ntlmssp_blob;
620 ret = reply_sesssetup_blob(conn, inbuf, outbuf, response, nt_status);
621 if (wrap) {
622 data_blob_free(&response);
625 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
626 and the other end, that we are not finished yet. */
628 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
629 /* NB. This is *NOT* an error case. JRA */
630 auth_ntlmssp_end(auth_ntlmssp_state);
631 /* Kill the intermediate vuid */
632 invalidate_vuid(vuid);
635 return ret;
638 /****************************************************************************
639 Is this a krb5 mechanism ?
640 ****************************************************************************/
642 NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, BOOL *p_is_krb5)
644 char *OIDs[ASN1_MAX_OIDS];
645 int i;
647 *p_is_krb5 = False;
649 /* parse out the OIDs and the first sec blob */
650 if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
651 return NT_STATUS_LOGON_FAILURE;
654 /* only look at the first OID for determining the mechToken --
655 accoirding to RFC2478, we should choose the one we want
656 and renegotiate, but i smell a client bug here..
658 Problem observed when connecting to a member (samba box)
659 of an AD domain as a user in a Samba domain. Samba member
660 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
661 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
662 NTLMSSP mechtoken. --jerry */
664 #ifdef HAVE_KRB5
665 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
666 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
667 *p_is_krb5 = True;
669 #endif
671 for (i=0;OIDs[i];i++) {
672 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
673 free(OIDs[i]);
675 return NT_STATUS_OK;
678 /****************************************************************************
679 Reply to a session setup spnego negotiate packet.
680 ****************************************************************************/
682 static int reply_spnego_negotiate(connection_struct *conn,
683 char *inbuf,
684 char *outbuf,
685 uint16 vuid,
686 int length, int bufsize,
687 DATA_BLOB blob1,
688 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
690 DATA_BLOB secblob;
691 DATA_BLOB chal;
692 BOOL got_kerberos_mechanism = False;
693 NTSTATUS status;
695 status = parse_spnego_mechanisms(blob1, &secblob, &got_kerberos_mechanism);
696 if (!NT_STATUS_IS_OK(status)) {
697 /* Kill the intermediate vuid */
698 invalidate_vuid(vuid);
699 return ERROR_NT(nt_status_squash(status));
702 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n", (unsigned long)secblob.length));
704 #ifdef HAVE_KRB5
705 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
706 BOOL destroy_vuid = True;
707 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
708 length, bufsize, &secblob, &destroy_vuid);
709 data_blob_free(&secblob);
710 if (destroy_vuid) {
711 /* Kill the intermediate vuid */
712 invalidate_vuid(vuid);
714 return ret;
716 #endif
718 if (*auth_ntlmssp_state) {
719 auth_ntlmssp_end(auth_ntlmssp_state);
722 status = auth_ntlmssp_start(auth_ntlmssp_state);
723 if (!NT_STATUS_IS_OK(status)) {
724 /* Kill the intermediate vuid */
725 invalidate_vuid(vuid);
726 return ERROR_NT(nt_status_squash(status));
729 status = auth_ntlmssp_update(*auth_ntlmssp_state,
730 secblob, &chal);
732 data_blob_free(&secblob);
734 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
735 &chal, status, True);
737 data_blob_free(&chal);
739 /* already replied */
740 return -1;
743 /****************************************************************************
744 Reply to a session setup spnego auth packet.
745 ****************************************************************************/
747 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
748 uint16 vuid,
749 int length, int bufsize,
750 DATA_BLOB blob1,
751 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
753 DATA_BLOB auth = data_blob_null;
754 DATA_BLOB auth_reply = data_blob_null;
755 DATA_BLOB secblob = data_blob_null;
756 NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
758 if (!spnego_parse_auth(blob1, &auth)) {
759 #if 0
760 file_save("auth.dat", blob1.data, blob1.length);
761 #endif
762 /* Kill the intermediate vuid */
763 invalidate_vuid(vuid);
765 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
768 if (auth.data[0] == ASN1_APPLICATION(0)) {
769 /* Might be a second negTokenTarg packet */
771 BOOL got_krb5_mechanism = False;
772 status = parse_spnego_mechanisms(auth, &secblob, &got_krb5_mechanism);
773 if (NT_STATUS_IS_OK(status)) {
774 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n", (unsigned long)secblob.length));
775 #ifdef HAVE_KRB5
776 if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
777 BOOL destroy_vuid = True;
778 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
779 length, bufsize, &secblob, &destroy_vuid);
780 data_blob_free(&secblob);
781 data_blob_free(&auth);
782 if (destroy_vuid) {
783 /* Kill the intermediate vuid */
784 invalidate_vuid(vuid);
786 return ret;
788 #endif
792 /* If we get here it wasn't a negTokenTarg auth packet. */
793 data_blob_free(&secblob);
795 if (!*auth_ntlmssp_state) {
796 /* Kill the intermediate vuid */
797 invalidate_vuid(vuid);
799 /* auth before negotiatiate? */
800 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
803 status = auth_ntlmssp_update(*auth_ntlmssp_state,
804 auth, &auth_reply);
806 data_blob_free(&auth);
808 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
809 auth_ntlmssp_state,
810 &auth_reply, status, True);
812 data_blob_free(&auth_reply);
814 /* and tell smbd that we have already replied to this packet */
815 return -1;
818 /****************************************************************************
819 List to store partial SPNEGO auth fragments.
820 ****************************************************************************/
822 static struct pending_auth_data *pd_list;
824 /****************************************************************************
825 Delete an entry on the list.
826 ****************************************************************************/
828 static void delete_partial_auth(struct pending_auth_data *pad)
830 if (!pad) {
831 return;
833 DLIST_REMOVE(pd_list, pad);
834 data_blob_free(&pad->partial_data);
835 SAFE_FREE(pad);
838 /****************************************************************************
839 Search for a partial SPNEGO auth fragment matching an smbpid.
840 ****************************************************************************/
842 static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
844 struct pending_auth_data *pad;
846 for (pad = pd_list; pad; pad = pad->next) {
847 if (pad->smbpid == smbpid) {
848 break;
851 return pad;
854 /****************************************************************************
855 Check the size of an SPNEGO blob. If we need more return NT_STATUS_MORE_PROCESSING_REQUIRED,
856 else return NT_STATUS_OK. Don't allow the blob to be more than 64k.
857 ****************************************************************************/
859 static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB *pblob)
861 struct pending_auth_data *pad = NULL;
862 ASN1_DATA data;
863 size_t needed_len = 0;
865 pad = get_pending_auth_data(smbpid);
867 /* Ensure we have some data. */
868 if (pblob->length == 0) {
869 /* Caller can cope. */
870 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
871 delete_partial_auth(pad);
872 return NT_STATUS_OK;
875 /* Were we waiting for more data ? */
876 if (pad) {
877 DATA_BLOB tmp_blob;
878 size_t copy_len = MIN(65536, pblob->length);
880 /* Integer wrap paranoia.... */
882 if (pad->partial_data.length + copy_len < pad->partial_data.length ||
883 pad->partial_data.length + copy_len < copy_len) {
885 DEBUG(2,("check_spnego_blob_complete: integer wrap "
886 "pad->partial_data.length = %u, "
887 "copy_len = %u\n",
888 (unsigned int)pad->partial_data.length,
889 (unsigned int)copy_len ));
891 delete_partial_auth(pad);
892 return NT_STATUS_INVALID_PARAMETER;
895 DEBUG(10,("check_spnego_blob_complete: "
896 "pad->partial_data.length = %u, "
897 "pad->needed_len = %u, "
898 "copy_len = %u, "
899 "pblob->length = %u,\n",
900 (unsigned int)pad->partial_data.length,
901 (unsigned int)pad->needed_len,
902 (unsigned int)copy_len,
903 (unsigned int)pblob->length ));
905 tmp_blob = data_blob(NULL,
906 pad->partial_data.length + copy_len);
908 /* Concatenate the two (up to copy_len) bytes. */
909 memcpy(tmp_blob.data,
910 pad->partial_data.data,
911 pad->partial_data.length);
912 memcpy(tmp_blob.data + pad->partial_data.length,
913 pblob->data,
914 copy_len);
916 /* Replace the partial data. */
917 data_blob_free(&pad->partial_data);
918 pad->partial_data = tmp_blob;
919 ZERO_STRUCT(tmp_blob);
921 /* Are we done ? */
922 if (pblob->length >= pad->needed_len) {
923 /* Yes, replace pblob. */
924 data_blob_free(pblob);
925 *pblob = pad->partial_data;
926 ZERO_STRUCT(pad->partial_data);
927 delete_partial_auth(pad);
928 return NT_STATUS_OK;
931 /* Still need more data. */
932 pad->needed_len -= copy_len;
933 return NT_STATUS_MORE_PROCESSING_REQUIRED;
936 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
937 (pblob->data[0] != ASN1_CONTEXT(1))) {
938 /* Not something we can determine the
939 * length of.
941 return NT_STATUS_OK;
944 /* This is a new SPNEGO sessionsetup - see if
945 * the data given in this blob is enough.
948 asn1_load(&data, *pblob);
949 asn1_start_tag(&data, pblob->data[0]);
950 if (data.has_error || data.nesting == NULL) {
951 asn1_free(&data);
952 /* Let caller catch. */
953 return NT_STATUS_OK;
956 /* Integer wrap paranoia.... */
958 if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
959 data.nesting->taglen + data.nesting->start < data.nesting->start) {
961 DEBUG(2,("check_spnego_blob_complete: integer wrap "
962 "data.nesting->taglen = %u, "
963 "data.nesting->start = %u\n",
964 (unsigned int)data.nesting->taglen,
965 (unsigned int)data.nesting->start ));
967 asn1_free(&data);
968 return NT_STATUS_INVALID_PARAMETER;
971 /* Total length of the needed asn1 is the tag length
972 * plus the current offset. */
974 needed_len = data.nesting->taglen + data.nesting->start;
975 asn1_free(&data);
977 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
978 "pblob->length = %u\n",
979 (unsigned int)needed_len,
980 (unsigned int)pblob->length ));
982 if (needed_len <= pblob->length) {
983 /* Nothing to do - blob is complete. */
984 return NT_STATUS_OK;
987 /* Refuse the blob if it's bigger than 64k. */
988 if (needed_len > 65536) {
989 DEBUG(2,("check_spnego_blob_complete: needed_len too large (%u)\n",
990 (unsigned int)needed_len ));
991 return NT_STATUS_INVALID_PARAMETER;
994 /* We must store this blob until complete. */
995 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
996 return NT_STATUS_NO_MEMORY;
998 pad->needed_len = needed_len - pblob->length;
999 pad->partial_data = data_blob(pblob->data, pblob->length);
1000 if (pad->partial_data.data == NULL) {
1001 SAFE_FREE(pad);
1002 return NT_STATUS_NO_MEMORY;
1004 pad->smbpid = smbpid;
1005 pad->vuid = vuid;
1006 DLIST_ADD(pd_list, pad);
1008 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1011 /****************************************************************************
1012 Reply to a session setup command.
1013 conn POINTER CAN BE NULL HERE !
1014 ****************************************************************************/
1016 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
1017 char *outbuf,
1018 int length,int bufsize)
1020 uint8 *p;
1021 DATA_BLOB blob1;
1022 int ret;
1023 size_t bufrem;
1024 fstring native_os, native_lanman, primary_domain;
1025 char *p2;
1026 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
1027 enum remote_arch_types ra_type = get_remote_arch();
1028 int vuid = SVAL(inbuf,smb_uid);
1029 user_struct *vuser = NULL;
1030 NTSTATUS status = NT_STATUS_OK;
1031 uint16 smbpid = SVAL(inbuf,smb_pid);
1033 DEBUG(3,("Doing spnego session setup\n"));
1035 if (global_client_caps == 0) {
1036 global_client_caps = IVAL(inbuf,smb_vwv10);
1038 if (!(global_client_caps & CAP_STATUS32)) {
1039 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1044 p = (uint8 *)smb_buf(inbuf);
1046 if (data_blob_len == 0) {
1047 /* an invalid request */
1048 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1051 bufrem = smb_bufrem(inbuf, p);
1052 /* pull the spnego blob */
1053 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1055 #if 0
1056 file_save("negotiate.dat", blob1.data, blob1.length);
1057 #endif
1059 p2 = inbuf + smb_vwv13 + data_blob_len;
1060 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
1061 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
1062 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
1063 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1064 native_os, native_lanman, primary_domain));
1066 if ( ra_type == RA_WIN2K ) {
1067 /* Vista sets neither the OS or lanman strings */
1069 if ( !strlen(native_os) && !strlen(native_lanman) )
1070 set_remote_arch(RA_VISTA);
1072 /* Windows 2003 doesn't set the native lanman string,
1073 but does set primary domain which is a bug I think */
1075 if ( !strlen(native_lanman) ) {
1076 ra_lanman_string( primary_domain );
1077 } else {
1078 ra_lanman_string( native_lanman );
1082 vuser = get_partial_auth_user_struct(vuid);
1083 if (!vuser) {
1084 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
1085 if (pad) {
1086 DEBUG(10,("reply_sesssetup_and_X_spnego: found pending vuid %u\n",
1087 (unsigned int)pad->vuid ));
1088 vuid = pad->vuid;
1089 vuser = get_partial_auth_user_struct(vuid);
1093 if (!vuser) {
1094 vuid = register_vuid(NULL, data_blob_null, data_blob_null, NULL);
1095 if (vuid == UID_FIELD_INVALID ) {
1096 data_blob_free(&blob1);
1097 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1100 vuser = get_partial_auth_user_struct(vuid);
1103 if (!vuser) {
1104 data_blob_free(&blob1);
1105 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1108 SSVAL(outbuf,smb_uid,vuid);
1110 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1111 * sessionsetup requests as the Windows limit on the security blob
1112 * field is 4k. Bug #4400. JRA.
1115 status = check_spnego_blob_complete(smbpid, vuid, &blob1);
1116 if (!NT_STATUS_IS_OK(status)) {
1117 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1118 /* Real error - kill the intermediate vuid */
1119 invalidate_vuid(vuid);
1121 data_blob_free(&blob1);
1122 return ERROR_NT(nt_status_squash(status));
1125 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1126 /* its a negTokenTarg packet */
1127 ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
1128 &vuser->auth_ntlmssp_state);
1129 data_blob_free(&blob1);
1130 return ret;
1133 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1134 /* its a auth packet */
1135 ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
1136 &vuser->auth_ntlmssp_state);
1137 data_blob_free(&blob1);
1138 return ret;
1141 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1142 DATA_BLOB chal;
1143 if (!vuser->auth_ntlmssp_state) {
1144 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1145 if (!NT_STATUS_IS_OK(status)) {
1146 /* Kill the intermediate vuid */
1147 invalidate_vuid(vuid);
1148 data_blob_free(&blob1);
1149 return ERROR_NT(nt_status_squash(status));
1153 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1154 blob1, &chal);
1156 data_blob_free(&blob1);
1158 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
1159 &vuser->auth_ntlmssp_state,
1160 &chal, status, False);
1161 data_blob_free(&chal);
1162 return -1;
1165 /* what sort of packet is this? */
1166 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1168 data_blob_free(&blob1);
1170 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1173 /****************************************************************************
1174 On new VC == 0, shutdown *all* old connections and users.
1175 It seems that only NT4.x does this. At W2K and above (XP etc.).
1176 a new session setup with VC==0 is ignored.
1177 ****************************************************************************/
1179 static int shutdown_other_smbds(struct db_record *rec,
1180 const struct connections_key *key,
1181 const struct connections_data *crec,
1182 void *private_data)
1184 const char *ip = (const char *)private_data;
1186 if (!process_exists(crec->pid)) {
1187 return 0;
1190 if (procid_is_me(&crec->pid)) {
1191 return 0;
1194 if (strcmp(ip, crec->addr) != 0) {
1195 return 0;
1198 messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1199 &data_blob_null);
1200 return 0;
1203 static void setup_new_vc_session(void)
1205 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
1206 #if 0
1207 conn_close_all();
1208 invalidate_all_vuids();
1209 #endif
1210 if (lp_reset_on_zero_vc()) {
1211 connections_forall(shutdown_other_smbds, client_addr());
1215 /****************************************************************************
1216 Reply to a session setup command.
1217 ****************************************************************************/
1219 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
1220 int length,int bufsize)
1222 int sess_vuid;
1223 int smb_bufsize;
1224 DATA_BLOB lm_resp;
1225 DATA_BLOB nt_resp;
1226 DATA_BLOB plaintext_password;
1227 fstring user;
1228 fstring sub_user; /* Sainitised username for substituion */
1229 fstring domain;
1230 fstring native_os;
1231 fstring native_lanman;
1232 fstring primary_domain;
1233 static BOOL done_sesssetup = False;
1234 auth_usersupplied_info *user_info = NULL;
1235 auth_serversupplied_info *server_info = NULL;
1237 NTSTATUS nt_status;
1239 BOOL doencrypt = global_encrypted_passwords_negotiated;
1241 DATA_BLOB session_key;
1243 START_PROFILE(SMBsesssetupX);
1245 ZERO_STRUCT(lm_resp);
1246 ZERO_STRUCT(nt_resp);
1247 ZERO_STRUCT(plaintext_password);
1249 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
1251 /* a SPNEGO session setup has 12 command words, whereas a normal
1252 NT1 session setup has 13. See the cifs spec. */
1253 if (CVAL(inbuf, smb_wct) == 12 &&
1254 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
1255 if (!global_spnego_negotiated) {
1256 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
1257 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1260 if (SVAL(inbuf,smb_vwv4) == 0) {
1261 setup_new_vc_session();
1263 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
1266 smb_bufsize = SVAL(inbuf,smb_vwv2);
1268 if (Protocol < PROTOCOL_NT1) {
1269 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
1271 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
1272 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1274 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
1275 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1278 if (doencrypt) {
1279 lm_resp = data_blob(smb_buf(inbuf), passlen1);
1280 } else {
1281 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
1282 /* Ensure null termination */
1283 plaintext_password.data[passlen1] = 0;
1286 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
1287 *domain = 0;
1289 } else {
1290 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
1291 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
1292 enum remote_arch_types ra_type = get_remote_arch();
1293 char *p = smb_buf(inbuf);
1294 char *save_p = smb_buf(inbuf);
1295 uint16 byte_count;
1298 if(global_client_caps == 0) {
1299 global_client_caps = IVAL(inbuf,smb_vwv11);
1301 if (!(global_client_caps & CAP_STATUS32)) {
1302 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1305 /* client_caps is used as final determination if client is NT or Win95.
1306 This is needed to return the correct error codes in some
1307 circumstances.
1310 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
1311 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
1312 set_remote_arch( RA_WIN95);
1317 if (!doencrypt) {
1318 /* both Win95 and WinNT stuff up the password lengths for
1319 non-encrypting systems. Uggh.
1321 if passlen1==24 its a win95 system, and its setting the
1322 password length incorrectly. Luckily it still works with the
1323 default code because Win95 will null terminate the password
1324 anyway
1326 if passlen1>0 and passlen2>0 then maybe its a NT box and its
1327 setting passlen2 to some random value which really stuffs
1328 things up. we need to fix that one. */
1330 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
1331 passlen2 = 0;
1334 /* check for nasty tricks */
1335 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
1336 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1339 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
1340 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1343 /* Save the lanman2 password and the NT md4 password. */
1345 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1346 doencrypt = False;
1349 if (doencrypt) {
1350 lm_resp = data_blob(p, passlen1);
1351 nt_resp = data_blob(p+passlen1, passlen2);
1352 } else {
1353 pstring pass;
1354 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
1356 #if 0
1357 /* This was the previous fix. Not sure if it's still valid. JRA. */
1358 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
1359 /* NT4.0 stuffs up plaintext unicode password lengths... */
1360 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
1361 sizeof(pass), passlen1, STR_TERMINATE);
1362 #endif
1364 if (unic && (passlen2 == 0) && passlen1) {
1365 /* Only a ascii plaintext password was sent. */
1366 srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
1367 passlen1, STR_TERMINATE|STR_ASCII);
1368 } else {
1369 srvstr_pull(inbuf, pass, smb_buf(inbuf),
1370 sizeof(pass), unic ? passlen2 : passlen1,
1371 STR_TERMINATE);
1373 plaintext_password = data_blob(pass, strlen(pass)+1);
1376 p += passlen1 + passlen2;
1377 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
1378 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
1379 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
1380 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
1382 /* not documented or decoded by Ethereal but there is one more string
1383 in the extra bytes which is the same as the PrimaryDomain when using
1384 extended security. Windows NT 4 and 2003 use this string to store
1385 the native lanman string. Windows 9x does not include a string here
1386 at all so we have to check if we have any extra bytes left */
1388 byte_count = SVAL(inbuf, smb_vwv13);
1389 if ( PTR_DIFF(p, save_p) < byte_count)
1390 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
1391 else
1392 fstrcpy( primary_domain, "null" );
1394 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1395 domain, native_os, native_lanman, primary_domain));
1397 if ( ra_type == RA_WIN2K ) {
1398 if ( strlen(native_lanman) == 0 )
1399 ra_lanman_string( primary_domain );
1400 else
1401 ra_lanman_string( native_lanman );
1406 if (SVAL(inbuf,smb_vwv4) == 0) {
1407 setup_new_vc_session();
1410 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
1412 if (*user) {
1413 if (global_spnego_negotiated) {
1415 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
1417 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
1418 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1420 fstrcpy(sub_user, user);
1421 } else {
1422 fstrcpy(sub_user, lp_guestaccount());
1425 sub_set_smb_name(sub_user);
1427 reload_services(True);
1429 if (lp_security() == SEC_SHARE) {
1430 /* in share level we should ignore any passwords */
1432 data_blob_free(&lm_resp);
1433 data_blob_free(&nt_resp);
1434 data_blob_clear_free(&plaintext_password);
1436 map_username(sub_user);
1437 add_session_user(sub_user);
1438 add_session_workgroup(domain);
1439 /* Then force it to null for the benfit of the code below */
1440 *user = 0;
1443 if (!*user) {
1445 nt_status = check_guest_password(&server_info);
1447 } else if (doencrypt) {
1448 if (!negprot_global_auth_context) {
1449 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
1450 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1452 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
1453 lm_resp, nt_resp);
1454 if (NT_STATUS_IS_OK(nt_status)) {
1455 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
1456 user_info,
1457 &server_info);
1459 } else {
1460 struct auth_context *plaintext_auth_context = NULL;
1461 const uint8 *chal;
1463 nt_status = make_auth_context_subsystem(&plaintext_auth_context);
1465 if (NT_STATUS_IS_OK(nt_status)) {
1466 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
1468 if (!make_user_info_for_reply(&user_info,
1469 user, domain, chal,
1470 plaintext_password)) {
1471 nt_status = NT_STATUS_NO_MEMORY;
1474 if (NT_STATUS_IS_OK(nt_status)) {
1475 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
1476 user_info,
1477 &server_info);
1479 (plaintext_auth_context->free)(&plaintext_auth_context);
1484 free_user_info(&user_info);
1486 if (!NT_STATUS_IS_OK(nt_status)) {
1487 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
1490 if (!NT_STATUS_IS_OK(nt_status)) {
1491 data_blob_free(&nt_resp);
1492 data_blob_free(&lm_resp);
1493 data_blob_clear_free(&plaintext_password);
1494 return ERROR_NT(nt_status_squash(nt_status));
1497 /* Ensure we can't possible take a code path leading to a null defref. */
1498 if (!server_info) {
1499 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1502 nt_status = create_local_token(server_info);
1503 if (!NT_STATUS_IS_OK(nt_status)) {
1504 DEBUG(10, ("create_local_token failed: %s\n",
1505 nt_errstr(nt_status)));
1506 data_blob_free(&nt_resp);
1507 data_blob_free(&lm_resp);
1508 data_blob_clear_free(&plaintext_password);
1509 return ERROR_NT(nt_status_squash(nt_status));
1512 if (server_info->user_session_key.data) {
1513 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
1514 } else {
1515 session_key = data_blob_null;
1518 data_blob_clear_free(&plaintext_password);
1520 /* it's ok - setup a reply */
1521 set_message(inbuf,outbuf,3,0,True);
1522 if (Protocol >= PROTOCOL_NT1) {
1523 char *p = smb_buf( outbuf );
1524 p += add_signature( outbuf, p );
1525 set_message_end(inbuf, outbuf, p );
1526 /* perhaps grab OS version here?? */
1529 if (server_info->guest) {
1530 SSVAL(outbuf,smb_vwv2,1);
1533 /* register the name and uid as being validated, so further connections
1534 to a uid can get through without a password, on the same VC */
1536 if (lp_security() == SEC_SHARE) {
1537 sess_vuid = UID_FIELD_INVALID;
1538 data_blob_free(&session_key);
1539 TALLOC_FREE(server_info);
1540 } else {
1541 /* register_vuid keeps the server info */
1542 sess_vuid = register_vuid(server_info, session_key,
1543 nt_resp.data ? nt_resp : lm_resp,
1544 sub_user);
1545 if (sess_vuid == UID_FIELD_INVALID) {
1546 data_blob_free(&nt_resp);
1547 data_blob_free(&lm_resp);
1548 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1551 /* current_user_info is changed on new vuid */
1552 reload_services( True );
1554 sessionsetup_start_signing_engine(server_info, inbuf);
1557 data_blob_free(&nt_resp);
1558 data_blob_free(&lm_resp);
1560 SSVAL(outbuf,smb_uid,sess_vuid);
1561 SSVAL(inbuf,smb_uid,sess_vuid);
1563 if (!done_sesssetup)
1564 max_send = MIN(max_send,smb_bufsize);
1566 done_sesssetup = True;
1568 END_PROFILE(SMBsesssetupX);
1569 return chain_reply(inbuf,outbuf,length,bufsize);