r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text
[Samba/bb.git] / source / smbd / sesssetup.c
blob320d2835752326f00879fda066cc36d396e11350
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 3 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, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
25 extern struct auth_context *negprot_global_auth_context;
26 extern BOOL global_encrypted_passwords_negotiated;
27 extern BOOL global_spnego_negotiated;
28 extern enum protocol_types Protocol;
29 extern int max_send;
31 uint32 global_client_caps = 0;
34 on a logon error possibly map the error to success if "map to guest"
35 is set approriately
37 static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **server_info,
38 const char *user, const char *domain)
40 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
41 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
42 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
43 DEBUG(3,("No such user %s [%s] - using guest account\n",
44 user, domain));
45 status = make_server_info_guest(server_info);
49 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
50 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
51 DEBUG(3,("Registered username %s for guest access\n",user));
52 status = make_server_info_guest(server_info);
56 return status;
59 /****************************************************************************
60 Add the standard 'Samba' signature to the end of the session setup.
61 ****************************************************************************/
63 static int add_signature(char *outbuf, char *p)
65 char *start = p;
66 fstring lanman;
68 fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
70 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
71 p += srvstr_push(outbuf, p, lanman, -1, STR_TERMINATE);
72 p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
74 return PTR_DIFF(p, start);
77 /****************************************************************************
78 Start the signing engine if needed. Don't fail signing here.
79 ****************************************************************************/
81 static void sessionsetup_start_signing_engine(const auth_serversupplied_info *server_info, char *inbuf)
83 if (!server_info->guest && !srv_signing_started()) {
84 /* We need to start the signing engine
85 * here but a W2K client sends the old
86 * "BSRSPYL " signature instead of the
87 * correct one. Subsequent packets will
88 * be correct.
90 srv_check_sign_mac(inbuf, False);
94 /****************************************************************************
95 Send a security blob via a session setup reply.
96 ****************************************************************************/
98 static BOOL reply_sesssetup_blob(connection_struct *conn,
99 const char *inbuf,
100 char *outbuf,
101 DATA_BLOB blob,
102 NTSTATUS nt_status)
104 char *p;
106 if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
107 ERROR_NT(nt_status_squash(nt_status));
108 } else {
109 set_message(inbuf,outbuf,4,0,True);
111 nt_status = nt_status_squash(nt_status);
112 SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
113 SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
114 SSVAL(outbuf, smb_vwv3, blob.length);
115 p = smb_buf(outbuf);
117 /* should we cap this? */
118 memcpy(p, blob.data, blob.length);
119 p += blob.length;
121 p += add_signature( outbuf, p );
123 set_message_end(inbuf,outbuf,p);
126 show_msg(outbuf);
127 return send_smb(smbd_server_fd(),outbuf);
130 /****************************************************************************
131 Do a 'guest' logon, getting back the
132 ****************************************************************************/
134 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
136 struct auth_context *auth_context;
137 auth_usersupplied_info *user_info = NULL;
139 NTSTATUS nt_status;
140 unsigned char chal[8];
142 ZERO_STRUCT(chal);
144 DEBUG(3,("Got anonymous request\n"));
146 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) {
147 return nt_status;
150 if (!make_user_info_guest(&user_info)) {
151 (auth_context->free)(&auth_context);
152 return NT_STATUS_NO_MEMORY;
155 nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info);
156 (auth_context->free)(&auth_context);
157 free_user_info(&user_info);
158 return nt_status;
162 #ifdef HAVE_KRB5
164 #if 0
165 /* Experiment that failed. See "only happens with a KDC" comment below. */
166 /****************************************************************************
167 Cerate a clock skew error blob for a Windows client.
168 ****************************************************************************/
170 static BOOL make_krb5_skew_error(DATA_BLOB *pblob_out)
172 krb5_context context = NULL;
173 krb5_error_code kerr = 0;
174 krb5_data reply;
175 krb5_principal host_princ = NULL;
176 char *host_princ_s = NULL;
177 BOOL ret = False;
179 *pblob_out = data_blob_null;
181 initialize_krb5_error_table();
182 kerr = krb5_init_context(&context);
183 if (kerr) {
184 return False;
186 /* Create server principal. */
187 asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
188 if (!host_princ_s) {
189 goto out;
191 strlower_m(host_princ_s);
193 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
194 if (kerr) {
195 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed for name %s: Error %s\n",
196 host_princ_s, error_message(kerr) ));
197 goto out;
200 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW, host_princ, &reply);
201 if (kerr) {
202 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error failed: Error %s\n",
203 error_message(kerr) ));
204 goto out;
207 *pblob_out = data_blob(reply.data, reply.length);
208 kerberos_free_data_contents(context,&reply);
209 ret = True;
211 out:
213 if (host_princ_s) {
214 SAFE_FREE(host_princ_s);
216 if (host_princ) {
217 krb5_free_principal(context, host_princ);
219 krb5_free_context(context);
220 return ret;
222 #endif
224 /****************************************************************************
225 Reply to a session setup spnego negotiate packet for kerberos.
226 ****************************************************************************/
228 static int reply_spnego_kerberos(connection_struct *conn,
229 char *inbuf, char *outbuf,
230 int length, int bufsize,
231 DATA_BLOB *secblob,
232 BOOL *p_invalidate_vuid)
234 TALLOC_CTX *mem_ctx;
235 DATA_BLOB ticket;
236 char *client, *p, *domain;
237 fstring netbios_domain_name;
238 struct passwd *pw;
239 fstring user;
240 int sess_vuid;
241 NTSTATUS ret;
242 PAC_DATA *pac_data;
243 DATA_BLOB ap_rep, ap_rep_wrapped, response;
244 auth_serversupplied_info *server_info = NULL;
245 DATA_BLOB session_key = data_blob_null;
246 uint8 tok_id[2];
247 DATA_BLOB nullblob = data_blob_null;
248 fstring real_username;
249 BOOL map_domainuser_to_guest = False;
250 BOOL username_was_mapped;
251 PAC_LOGON_INFO *logon_info = NULL;
253 ZERO_STRUCT(ticket);
254 ZERO_STRUCT(pac_data);
255 ZERO_STRUCT(ap_rep);
256 ZERO_STRUCT(ap_rep_wrapped);
257 ZERO_STRUCT(response);
259 /* Normally we will always invalidate the intermediate vuid. */
260 *p_invalidate_vuid = True;
262 mem_ctx = talloc_init("reply_spnego_kerberos");
263 if (mem_ctx == NULL) {
264 return ERROR_NT(nt_status_squash(NT_STATUS_NO_MEMORY));
267 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
268 talloc_destroy(mem_ctx);
269 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
272 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
273 &client, &pac_data, &ap_rep,
274 &session_key, True);
276 data_blob_free(&ticket);
278 if (!NT_STATUS_IS_OK(ret)) {
279 #if 0
280 /* Experiment that failed. See "only happens with a KDC" comment below. */
282 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
285 * Windows in this case returns NT_STATUS_MORE_PROCESSING_REQUIRED
286 * with a negTokenTarg blob containing an krb5_error struct ASN1 encoded
287 * containing KRB5KRB_AP_ERR_SKEW. The client then fixes its
288 * clock and continues rather than giving an error. JRA.
289 * -- Looks like this only happens with a KDC. JRA.
292 BOOL ok = make_krb5_skew_error(&ap_rep);
293 if (!ok) {
294 talloc_destroy(mem_ctx);
295 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
297 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_ERROR);
298 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
299 reply_sesssetup_blob(conn, inbuf, outbuf, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
302 * In this one case we don't invalidate the intermediate vuid.
303 * as we're expecting the client to re-use it for the next
304 * sessionsetupX packet. JRA.
307 *p_invalidate_vuid = False;
309 data_blob_free(&ap_rep);
310 data_blob_free(&ap_rep_wrapped);
311 data_blob_free(&response);
312 talloc_destroy(mem_ctx);
313 return -1; /* already replied */
315 #else
316 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
317 ret = NT_STATUS_LOGON_FAILURE;
319 #endif
320 DEBUG(1,("Failed to verify incoming ticket with error %s!\n", nt_errstr(ret)));
321 talloc_destroy(mem_ctx);
322 return ERROR_NT(nt_status_squash(ret));
325 DEBUG(3,("Ticket name is [%s]\n", client));
327 p = strchr_m(client, '@');
328 if (!p) {
329 DEBUG(3,("Doesn't look like a valid principal\n"));
330 data_blob_free(&ap_rep);
331 data_blob_free(&session_key);
332 SAFE_FREE(client);
333 talloc_destroy(mem_ctx);
334 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
337 *p = 0;
339 /* save the PAC data if we have it */
341 if (pac_data) {
342 logon_info = get_logon_info_from_pac(pac_data);
343 if (logon_info) {
344 netsamlogon_cache_store( client, &logon_info->info3 );
348 if (!strequal(p+1, lp_realm())) {
349 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
350 if (!lp_allow_trusted_domains()) {
351 data_blob_free(&ap_rep);
352 data_blob_free(&session_key);
353 SAFE_FREE(client);
354 talloc_destroy(mem_ctx);
355 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
359 /* this gives a fully qualified user name (ie. with full realm).
360 that leads to very long usernames, but what else can we do? */
362 domain = p+1;
364 if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) {
366 unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, -1);
367 domain = netbios_domain_name;
368 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
370 } else {
372 /* If we have winbind running, we can (and must) shorten the
373 username by using the short netbios name. Otherwise we will
374 have inconsistent user names. With Kerberos, we get the
375 fully qualified realm, with ntlmssp we get the short
376 name. And even w2k3 does use ntlmssp if you for example
377 connect to an ip address. */
379 struct winbindd_request wb_request;
380 struct winbindd_response wb_response;
381 NSS_STATUS wb_result;
383 ZERO_STRUCT(wb_request);
384 ZERO_STRUCT(wb_response);
386 DEBUG(10, ("Mapping [%s] to short name\n", domain));
388 fstrcpy(wb_request.domain_name, domain);
390 wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
391 &wb_request, &wb_response);
393 if (wb_result == NSS_STATUS_SUCCESS) {
395 fstrcpy(netbios_domain_name,
396 wb_response.data.domain_info.name);
397 domain = netbios_domain_name;
399 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
400 } else {
401 DEBUG(3, ("Could not find short name -- winbind "
402 "not running?\n"));
406 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
408 /* lookup the passwd struct, create a new user if necessary */
410 username_was_mapped = map_username( user );
412 pw = smb_getpwnam( mem_ctx, user, real_username, True );
414 if (pw) {
415 /* if a real user check pam account restrictions */
416 /* only really perfomed if "obey pam restriction" is true */
417 /* do this before an eventual mappign to guest occurs */
418 ret = smb_pam_accountcheck(pw->pw_name);
419 if ( !NT_STATUS_IS_OK(ret)) {
420 DEBUG(1, ("PAM account restriction prevents user login\n"));
421 data_blob_free(&ap_rep);
422 data_blob_free(&session_key);
423 TALLOC_FREE(mem_ctx);
424 return ERROR_NT(nt_status_squash(ret));
428 if (!pw) {
430 /* this was originally the behavior of Samba 2.2, if a user
431 did not have a local uid but has been authenticated, then
432 map them to a guest account */
434 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
435 map_domainuser_to_guest = True;
436 fstrcpy(user,lp_guestaccount());
437 pw = smb_getpwnam( mem_ctx, user, real_username, True );
440 /* extra sanity check that the guest account is valid */
442 if ( !pw ) {
443 DEBUG(1,("Username %s is invalid on this system\n", user));
444 SAFE_FREE(client);
445 data_blob_free(&ap_rep);
446 data_blob_free(&session_key);
447 TALLOC_FREE(mem_ctx);
448 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
452 /* setup the string used by %U */
454 sub_set_smb_name( real_username );
455 reload_services(True);
457 if ( map_domainuser_to_guest ) {
458 make_server_info_guest(&server_info);
459 } else if (logon_info) {
460 /* pass the unmapped username here since map_username()
461 will be called again from inside make_server_info_info3() */
463 ret = make_server_info_info3(mem_ctx, client, domain,
464 &server_info, &logon_info->info3);
465 if ( !NT_STATUS_IS_OK(ret) ) {
466 DEBUG(1,("make_server_info_info3 failed: %s!\n",
467 nt_errstr(ret)));
468 SAFE_FREE(client);
469 data_blob_free(&ap_rep);
470 data_blob_free(&session_key);
471 TALLOC_FREE(mem_ctx);
472 return ERROR_NT(nt_status_squash(ret));
475 } else {
476 ret = make_server_info_pw(&server_info, real_username, pw);
478 if ( !NT_STATUS_IS_OK(ret) ) {
479 DEBUG(1,("make_server_info_pw failed: %s!\n",
480 nt_errstr(ret)));
481 SAFE_FREE(client);
482 data_blob_free(&ap_rep);
483 data_blob_free(&session_key);
484 TALLOC_FREE(mem_ctx);
485 return ERROR_NT(nt_status_squash(ret));
488 /* make_server_info_pw does not set the domain. Without this
489 * we end up with the local netbios name in substitutions for
490 * %D. */
492 if (server_info->sam_account != NULL) {
493 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
497 server_info->was_mapped |= username_was_mapped;
499 /* we need to build the token for the user. make_server_info_guest()
500 already does this */
502 if ( !server_info->ptok ) {
503 ret = create_local_token( server_info );
504 if ( !NT_STATUS_IS_OK(ret) ) {
505 SAFE_FREE(client);
506 data_blob_free(&ap_rep);
507 data_blob_free(&session_key);
508 TALLOC_FREE( mem_ctx );
509 TALLOC_FREE( server_info );
510 return ERROR_NT(nt_status_squash(ret));
514 /* register_vuid keeps the server info */
515 /* register_vuid takes ownership of session_key, no need to free after this.
516 A better interface would copy it.... */
517 sess_vuid = register_vuid(server_info, session_key, nullblob, client);
519 SAFE_FREE(client);
521 if (sess_vuid == UID_FIELD_INVALID ) {
522 ret = NT_STATUS_LOGON_FAILURE;
523 } else {
524 /* current_user_info is changed on new vuid */
525 reload_services( True );
527 set_message(inbuf,outbuf,4,0,True);
528 SSVAL(outbuf, smb_vwv3, 0);
530 if (server_info->guest) {
531 SSVAL(outbuf,smb_vwv2,1);
534 SSVAL(outbuf, smb_uid, sess_vuid);
536 sessionsetup_start_signing_engine(server_info, inbuf);
539 /* wrap that up in a nice GSS-API wrapping */
540 if (NT_STATUS_IS_OK(ret)) {
541 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
542 } else {
543 ap_rep_wrapped = data_blob_null;
545 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
546 reply_sesssetup_blob(conn, inbuf, outbuf, response, ret);
548 data_blob_free(&ap_rep);
549 data_blob_free(&ap_rep_wrapped);
550 data_blob_free(&response);
551 TALLOC_FREE(mem_ctx);
553 return -1; /* already replied */
555 #endif
557 /****************************************************************************
558 Send a session setup reply, wrapped in SPNEGO.
559 Get vuid and check first.
560 End the NTLMSSP exchange context if we are OK/complete fail
561 This should be split into two functions, one to handle each
562 leg of the NTLM auth steps.
563 ***************************************************************************/
565 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
566 uint16 vuid,
567 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
568 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
569 BOOL wrap)
571 BOOL ret;
572 DATA_BLOB response;
573 struct auth_serversupplied_info *server_info = NULL;
575 if (NT_STATUS_IS_OK(nt_status)) {
576 server_info = (*auth_ntlmssp_state)->server_info;
577 } else {
578 nt_status = do_map_to_guest(nt_status,
579 &server_info,
580 (*auth_ntlmssp_state)->ntlmssp_state->user,
581 (*auth_ntlmssp_state)->ntlmssp_state->domain);
584 if (NT_STATUS_IS_OK(nt_status)) {
585 int sess_vuid;
586 DATA_BLOB nullblob = data_blob_null;
587 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
589 /* register_vuid keeps the server info */
590 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
591 (*auth_ntlmssp_state)->server_info = NULL;
593 if (sess_vuid == UID_FIELD_INVALID ) {
594 nt_status = NT_STATUS_LOGON_FAILURE;
595 } else {
597 /* current_user_info is changed on new vuid */
598 reload_services( True );
600 set_message(inbuf,outbuf,4,0,True);
601 SSVAL(outbuf, smb_vwv3, 0);
603 if (server_info->guest) {
604 SSVAL(outbuf,smb_vwv2,1);
607 SSVAL(outbuf,smb_uid,sess_vuid);
609 sessionsetup_start_signing_engine(server_info, inbuf);
613 if (wrap) {
614 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
615 } else {
616 response = *ntlmssp_blob;
619 ret = reply_sesssetup_blob(conn, inbuf, outbuf, response, nt_status);
620 if (wrap) {
621 data_blob_free(&response);
624 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
625 and the other end, that we are not finished yet. */
627 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
628 /* NB. This is *NOT* an error case. JRA */
629 auth_ntlmssp_end(auth_ntlmssp_state);
630 /* Kill the intermediate vuid */
631 invalidate_vuid(vuid);
634 return ret;
637 /****************************************************************************
638 Is this a krb5 mechanism ?
639 ****************************************************************************/
641 NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, BOOL *p_is_krb5)
643 char *OIDs[ASN1_MAX_OIDS];
644 int i;
646 *p_is_krb5 = False;
648 /* parse out the OIDs and the first sec blob */
649 if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
650 return NT_STATUS_LOGON_FAILURE;
653 /* only look at the first OID for determining the mechToken --
654 accoirding to RFC2478, we should choose the one we want
655 and renegotiate, but i smell a client bug here..
657 Problem observed when connecting to a member (samba box)
658 of an AD domain as a user in a Samba domain. Samba member
659 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
660 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
661 NTLMSSP mechtoken. --jerry */
663 #ifdef HAVE_KRB5
664 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
665 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
666 *p_is_krb5 = True;
668 #endif
670 for (i=0;OIDs[i];i++) {
671 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
672 free(OIDs[i]);
674 return NT_STATUS_OK;
677 /****************************************************************************
678 Reply to a session setup spnego negotiate packet.
679 ****************************************************************************/
681 static int reply_spnego_negotiate(connection_struct *conn,
682 char *inbuf,
683 char *outbuf,
684 uint16 vuid,
685 int length, int bufsize,
686 DATA_BLOB blob1,
687 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
689 DATA_BLOB secblob;
690 DATA_BLOB chal;
691 BOOL got_kerberos_mechanism = False;
692 NTSTATUS status;
694 status = parse_spnego_mechanisms(blob1, &secblob, &got_kerberos_mechanism);
695 if (!NT_STATUS_IS_OK(status)) {
696 /* Kill the intermediate vuid */
697 invalidate_vuid(vuid);
698 return ERROR_NT(nt_status_squash(status));
701 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n", (unsigned long)secblob.length));
703 #ifdef HAVE_KRB5
704 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
705 BOOL destroy_vuid = True;
706 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
707 length, bufsize, &secblob, &destroy_vuid);
708 data_blob_free(&secblob);
709 if (destroy_vuid) {
710 /* Kill the intermediate vuid */
711 invalidate_vuid(vuid);
713 return ret;
715 #endif
717 if (*auth_ntlmssp_state) {
718 auth_ntlmssp_end(auth_ntlmssp_state);
721 status = auth_ntlmssp_start(auth_ntlmssp_state);
722 if (!NT_STATUS_IS_OK(status)) {
723 /* Kill the intermediate vuid */
724 invalidate_vuid(vuid);
725 return ERROR_NT(nt_status_squash(status));
728 status = auth_ntlmssp_update(*auth_ntlmssp_state,
729 secblob, &chal);
731 data_blob_free(&secblob);
733 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
734 &chal, status, True);
736 data_blob_free(&chal);
738 /* already replied */
739 return -1;
742 /****************************************************************************
743 Reply to a session setup spnego auth packet.
744 ****************************************************************************/
746 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
747 uint16 vuid,
748 int length, int bufsize,
749 DATA_BLOB blob1,
750 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
752 DATA_BLOB auth = data_blob_null;
753 DATA_BLOB auth_reply = data_blob_null;
754 DATA_BLOB secblob = data_blob_null;
755 NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
757 if (!spnego_parse_auth(blob1, &auth)) {
758 #if 0
759 file_save("auth.dat", blob1.data, blob1.length);
760 #endif
761 /* Kill the intermediate vuid */
762 invalidate_vuid(vuid);
764 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
767 if (auth.data[0] == ASN1_APPLICATION(0)) {
768 /* Might be a second negTokenTarg packet */
770 BOOL got_krb5_mechanism = False;
771 status = parse_spnego_mechanisms(auth, &secblob, &got_krb5_mechanism);
772 if (NT_STATUS_IS_OK(status)) {
773 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n", (unsigned long)secblob.length));
774 #ifdef HAVE_KRB5
775 if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
776 BOOL destroy_vuid = True;
777 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
778 length, bufsize, &secblob, &destroy_vuid);
779 data_blob_free(&secblob);
780 data_blob_free(&auth);
781 if (destroy_vuid) {
782 /* Kill the intermediate vuid */
783 invalidate_vuid(vuid);
785 return ret;
787 #endif
791 /* If we get here it wasn't a negTokenTarg auth packet. */
792 data_blob_free(&secblob);
794 if (!*auth_ntlmssp_state) {
795 /* Kill the intermediate vuid */
796 invalidate_vuid(vuid);
798 /* auth before negotiatiate? */
799 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
802 status = auth_ntlmssp_update(*auth_ntlmssp_state,
803 auth, &auth_reply);
805 data_blob_free(&auth);
807 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
808 auth_ntlmssp_state,
809 &auth_reply, status, True);
811 data_blob_free(&auth_reply);
813 /* and tell smbd that we have already replied to this packet */
814 return -1;
817 /****************************************************************************
818 List to store partial SPNEGO auth fragments.
819 ****************************************************************************/
821 static struct pending_auth_data *pd_list;
823 /****************************************************************************
824 Delete an entry on the list.
825 ****************************************************************************/
827 static void delete_partial_auth(struct pending_auth_data *pad)
829 if (!pad) {
830 return;
832 DLIST_REMOVE(pd_list, pad);
833 data_blob_free(&pad->partial_data);
834 SAFE_FREE(pad);
837 /****************************************************************************
838 Search for a partial SPNEGO auth fragment matching an smbpid.
839 ****************************************************************************/
841 static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
843 struct pending_auth_data *pad;
845 for (pad = pd_list; pad; pad = pad->next) {
846 if (pad->smbpid == smbpid) {
847 break;
850 return pad;
853 /****************************************************************************
854 Check the size of an SPNEGO blob. If we need more return NT_STATUS_MORE_PROCESSING_REQUIRED,
855 else return NT_STATUS_OK. Don't allow the blob to be more than 64k.
856 ****************************************************************************/
858 static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB *pblob)
860 struct pending_auth_data *pad = NULL;
861 ASN1_DATA data;
862 size_t needed_len = 0;
864 pad = get_pending_auth_data(smbpid);
866 /* Ensure we have some data. */
867 if (pblob->length == 0) {
868 /* Caller can cope. */
869 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
870 delete_partial_auth(pad);
871 return NT_STATUS_OK;
874 /* Were we waiting for more data ? */
875 if (pad) {
876 DATA_BLOB tmp_blob;
877 size_t copy_len = MIN(65536, pblob->length);
879 /* Integer wrap paranoia.... */
881 if (pad->partial_data.length + copy_len < pad->partial_data.length ||
882 pad->partial_data.length + copy_len < copy_len) {
884 DEBUG(2,("check_spnego_blob_complete: integer wrap "
885 "pad->partial_data.length = %u, "
886 "copy_len = %u\n",
887 (unsigned int)pad->partial_data.length,
888 (unsigned int)copy_len ));
890 delete_partial_auth(pad);
891 return NT_STATUS_INVALID_PARAMETER;
894 DEBUG(10,("check_spnego_blob_complete: "
895 "pad->partial_data.length = %u, "
896 "pad->needed_len = %u, "
897 "copy_len = %u, "
898 "pblob->length = %u,\n",
899 (unsigned int)pad->partial_data.length,
900 (unsigned int)pad->needed_len,
901 (unsigned int)copy_len,
902 (unsigned int)pblob->length ));
904 tmp_blob = data_blob(NULL,
905 pad->partial_data.length + copy_len);
907 /* Concatenate the two (up to copy_len) bytes. */
908 memcpy(tmp_blob.data,
909 pad->partial_data.data,
910 pad->partial_data.length);
911 memcpy(tmp_blob.data + pad->partial_data.length,
912 pblob->data,
913 copy_len);
915 /* Replace the partial data. */
916 data_blob_free(&pad->partial_data);
917 pad->partial_data = tmp_blob;
918 ZERO_STRUCT(tmp_blob);
920 /* Are we done ? */
921 if (pblob->length >= pad->needed_len) {
922 /* Yes, replace pblob. */
923 data_blob_free(pblob);
924 *pblob = pad->partial_data;
925 ZERO_STRUCT(pad->partial_data);
926 delete_partial_auth(pad);
927 return NT_STATUS_OK;
930 /* Still need more data. */
931 pad->needed_len -= copy_len;
932 return NT_STATUS_MORE_PROCESSING_REQUIRED;
935 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
936 (pblob->data[0] != ASN1_CONTEXT(1))) {
937 /* Not something we can determine the
938 * length of.
940 return NT_STATUS_OK;
943 /* This is a new SPNEGO sessionsetup - see if
944 * the data given in this blob is enough.
947 asn1_load(&data, *pblob);
948 asn1_start_tag(&data, pblob->data[0]);
949 if (data.has_error || data.nesting == NULL) {
950 asn1_free(&data);
951 /* Let caller catch. */
952 return NT_STATUS_OK;
955 /* Integer wrap paranoia.... */
957 if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
958 data.nesting->taglen + data.nesting->start < data.nesting->start) {
960 DEBUG(2,("check_spnego_blob_complete: integer wrap "
961 "data.nesting->taglen = %u, "
962 "data.nesting->start = %u\n",
963 (unsigned int)data.nesting->taglen,
964 (unsigned int)data.nesting->start ));
966 asn1_free(&data);
967 return NT_STATUS_INVALID_PARAMETER;
970 /* Total length of the needed asn1 is the tag length
971 * plus the current offset. */
973 needed_len = data.nesting->taglen + data.nesting->start;
974 asn1_free(&data);
976 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
977 "pblob->length = %u\n",
978 (unsigned int)needed_len,
979 (unsigned int)pblob->length ));
981 if (needed_len <= pblob->length) {
982 /* Nothing to do - blob is complete. */
983 return NT_STATUS_OK;
986 /* Refuse the blob if it's bigger than 64k. */
987 if (needed_len > 65536) {
988 DEBUG(2,("check_spnego_blob_complete: needed_len too large (%u)\n",
989 (unsigned int)needed_len ));
990 return NT_STATUS_INVALID_PARAMETER;
993 /* We must store this blob until complete. */
994 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
995 return NT_STATUS_NO_MEMORY;
997 pad->needed_len = needed_len - pblob->length;
998 pad->partial_data = data_blob(pblob->data, pblob->length);
999 if (pad->partial_data.data == NULL) {
1000 SAFE_FREE(pad);
1001 return NT_STATUS_NO_MEMORY;
1003 pad->smbpid = smbpid;
1004 pad->vuid = vuid;
1005 DLIST_ADD(pd_list, pad);
1007 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1010 /****************************************************************************
1011 Reply to a session setup command.
1012 conn POINTER CAN BE NULL HERE !
1013 ****************************************************************************/
1015 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
1016 char *outbuf,
1017 int length,int bufsize)
1019 uint8 *p;
1020 DATA_BLOB blob1;
1021 int ret;
1022 size_t bufrem;
1023 fstring native_os, native_lanman, primary_domain;
1024 char *p2;
1025 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
1026 enum remote_arch_types ra_type = get_remote_arch();
1027 int vuid = SVAL(inbuf,smb_uid);
1028 user_struct *vuser = NULL;
1029 NTSTATUS status = NT_STATUS_OK;
1030 uint16 smbpid = SVAL(inbuf,smb_pid);
1031 uint16 smb_flag2 = SVAL(inbuf, smb_flg2);
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, smb_flag2, native_os, p2,
1061 sizeof(native_os), STR_TERMINATE);
1062 p2 += srvstr_pull_buf(inbuf, smb_flag2, native_lanman, p2,
1063 sizeof(native_lanman), STR_TERMINATE);
1064 p2 += srvstr_pull_buf(inbuf, smb_flag2, primary_domain, p2,
1065 sizeof(primary_domain), STR_TERMINATE);
1066 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1067 native_os, native_lanman, primary_domain));
1069 if ( ra_type == RA_WIN2K ) {
1070 /* Vista sets neither the OS or lanman strings */
1072 if ( !strlen(native_os) && !strlen(native_lanman) )
1073 set_remote_arch(RA_VISTA);
1075 /* Windows 2003 doesn't set the native lanman string,
1076 but does set primary domain which is a bug I think */
1078 if ( !strlen(native_lanman) ) {
1079 ra_lanman_string( primary_domain );
1080 } else {
1081 ra_lanman_string( native_lanman );
1085 vuser = get_partial_auth_user_struct(vuid);
1086 if (!vuser) {
1087 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
1088 if (pad) {
1089 DEBUG(10,("reply_sesssetup_and_X_spnego: found pending vuid %u\n",
1090 (unsigned int)pad->vuid ));
1091 vuid = pad->vuid;
1092 vuser = get_partial_auth_user_struct(vuid);
1096 if (!vuser) {
1097 vuid = register_vuid(NULL, data_blob_null, data_blob_null, NULL);
1098 if (vuid == UID_FIELD_INVALID ) {
1099 data_blob_free(&blob1);
1100 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1103 vuser = get_partial_auth_user_struct(vuid);
1106 if (!vuser) {
1107 data_blob_free(&blob1);
1108 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1111 SSVAL(outbuf,smb_uid,vuid);
1113 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1114 * sessionsetup requests as the Windows limit on the security blob
1115 * field is 4k. Bug #4400. JRA.
1118 status = check_spnego_blob_complete(smbpid, vuid, &blob1);
1119 if (!NT_STATUS_IS_OK(status)) {
1120 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1121 /* Real error - kill the intermediate vuid */
1122 invalidate_vuid(vuid);
1124 data_blob_free(&blob1);
1125 return ERROR_NT(nt_status_squash(status));
1128 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1129 /* its a negTokenTarg packet */
1130 ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
1131 &vuser->auth_ntlmssp_state);
1132 data_blob_free(&blob1);
1133 return ret;
1136 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1137 /* its a auth packet */
1138 ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
1139 &vuser->auth_ntlmssp_state);
1140 data_blob_free(&blob1);
1141 return ret;
1144 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1145 DATA_BLOB chal;
1146 if (!vuser->auth_ntlmssp_state) {
1147 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1148 if (!NT_STATUS_IS_OK(status)) {
1149 /* Kill the intermediate vuid */
1150 invalidate_vuid(vuid);
1151 data_blob_free(&blob1);
1152 return ERROR_NT(nt_status_squash(status));
1156 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1157 blob1, &chal);
1159 data_blob_free(&blob1);
1161 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
1162 &vuser->auth_ntlmssp_state,
1163 &chal, status, False);
1164 data_blob_free(&chal);
1165 return -1;
1168 /* what sort of packet is this? */
1169 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1171 data_blob_free(&blob1);
1173 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1176 /****************************************************************************
1177 On new VC == 0, shutdown *all* old connections and users.
1178 It seems that only NT4.x does this. At W2K and above (XP etc.).
1179 a new session setup with VC==0 is ignored.
1180 ****************************************************************************/
1182 static int shutdown_other_smbds(struct db_record *rec,
1183 const struct connections_key *key,
1184 const struct connections_data *crec,
1185 void *private_data)
1187 const char *ip = (const char *)private_data;
1189 if (!process_exists(crec->pid)) {
1190 return 0;
1193 if (procid_is_me(&crec->pid)) {
1194 return 0;
1197 if (strcmp(ip, crec->addr) != 0) {
1198 return 0;
1201 messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1202 &data_blob_null);
1203 return 0;
1206 static void setup_new_vc_session(void)
1208 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
1209 #if 0
1210 conn_close_all();
1211 invalidate_all_vuids();
1212 #endif
1213 if (lp_reset_on_zero_vc()) {
1214 connections_forall(shutdown_other_smbds, client_addr());
1218 /****************************************************************************
1219 Reply to a session setup command.
1220 ****************************************************************************/
1222 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
1223 int length,int bufsize)
1225 int sess_vuid;
1226 int smb_bufsize;
1227 DATA_BLOB lm_resp;
1228 DATA_BLOB nt_resp;
1229 DATA_BLOB plaintext_password;
1230 fstring user;
1231 fstring sub_user; /* Sainitised username for substituion */
1232 fstring domain;
1233 fstring native_os;
1234 fstring native_lanman;
1235 fstring primary_domain;
1236 static BOOL done_sesssetup = False;
1237 auth_usersupplied_info *user_info = NULL;
1238 auth_serversupplied_info *server_info = NULL;
1239 uint16 smb_flag2 = SVAL(inbuf, smb_flg2);
1241 NTSTATUS nt_status;
1243 BOOL doencrypt = global_encrypted_passwords_negotiated;
1245 DATA_BLOB session_key;
1247 START_PROFILE(SMBsesssetupX);
1249 ZERO_STRUCT(lm_resp);
1250 ZERO_STRUCT(nt_resp);
1251 ZERO_STRUCT(plaintext_password);
1253 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), smb_flag2));
1255 /* a SPNEGO session setup has 12 command words, whereas a normal
1256 NT1 session setup has 13. See the cifs spec. */
1257 if (CVAL(inbuf, smb_wct) == 12 &&
1258 (smb_flag2 & FLAGS2_EXTENDED_SECURITY)) {
1259 if (!global_spnego_negotiated) {
1260 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
1261 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1264 if (SVAL(inbuf,smb_vwv4) == 0) {
1265 setup_new_vc_session();
1267 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
1270 smb_bufsize = SVAL(inbuf,smb_vwv2);
1272 if (Protocol < PROTOCOL_NT1) {
1273 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
1275 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
1276 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1278 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
1279 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1282 if (doencrypt) {
1283 lm_resp = data_blob(smb_buf(inbuf), passlen1);
1284 } else {
1285 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
1286 /* Ensure null termination */
1287 plaintext_password.data[passlen1] = 0;
1290 srvstr_pull_buf(inbuf, smb_flag2, user,
1291 smb_buf(inbuf)+passlen1, sizeof(user),
1292 STR_TERMINATE);
1293 *domain = 0;
1295 } else {
1296 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
1297 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
1298 enum remote_arch_types ra_type = get_remote_arch();
1299 char *p = smb_buf(inbuf);
1300 char *save_p = smb_buf(inbuf);
1301 uint16 byte_count;
1304 if(global_client_caps == 0) {
1305 global_client_caps = IVAL(inbuf,smb_vwv11);
1307 if (!(global_client_caps & CAP_STATUS32)) {
1308 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1311 /* client_caps is used as final determination if client is NT or Win95.
1312 This is needed to return the correct error codes in some
1313 circumstances.
1316 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
1317 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
1318 set_remote_arch( RA_WIN95);
1323 if (!doencrypt) {
1324 /* both Win95 and WinNT stuff up the password lengths for
1325 non-encrypting systems. Uggh.
1327 if passlen1==24 its a win95 system, and its setting the
1328 password length incorrectly. Luckily it still works with the
1329 default code because Win95 will null terminate the password
1330 anyway
1332 if passlen1>0 and passlen2>0 then maybe its a NT box and its
1333 setting passlen2 to some random value which really stuffs
1334 things up. we need to fix that one. */
1336 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
1337 passlen2 = 0;
1340 /* check for nasty tricks */
1341 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
1342 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1345 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
1346 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1349 /* Save the lanman2 password and the NT md4 password. */
1351 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1352 doencrypt = False;
1355 if (doencrypt) {
1356 lm_resp = data_blob(p, passlen1);
1357 nt_resp = data_blob(p+passlen1, passlen2);
1358 } else {
1359 pstring pass;
1360 BOOL unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1362 #if 0
1363 /* This was the previous fix. Not sure if it's still valid. JRA. */
1364 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
1365 /* NT4.0 stuffs up plaintext unicode password lengths... */
1366 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
1367 sizeof(pass), passlen1, STR_TERMINATE);
1368 #endif
1370 if (unic && (passlen2 == 0) && passlen1) {
1371 /* Only a ascii plaintext password was sent. */
1372 srvstr_pull(inbuf, smb_flag2, pass,
1373 smb_buf(inbuf), sizeof(pass),
1374 passlen1, STR_TERMINATE|STR_ASCII);
1375 } else {
1376 srvstr_pull(inbuf, smb_flag2, pass,
1377 smb_buf(inbuf), sizeof(pass),
1378 unic ? passlen2 : passlen1,
1379 STR_TERMINATE);
1381 plaintext_password = data_blob(pass, strlen(pass)+1);
1384 p += passlen1 + passlen2;
1385 p += srvstr_pull_buf(inbuf, smb_flag2, user, p,
1386 sizeof(user), STR_TERMINATE);
1387 p += srvstr_pull_buf(inbuf, smb_flag2, domain, p,
1388 sizeof(domain), STR_TERMINATE);
1389 p += srvstr_pull_buf(inbuf, smb_flag2, native_os,
1390 p, sizeof(native_os), STR_TERMINATE);
1391 p += srvstr_pull_buf(inbuf, smb_flag2,
1392 native_lanman, p, sizeof(native_lanman),
1393 STR_TERMINATE);
1395 /* not documented or decoded by Ethereal but there is one more string
1396 in the extra bytes which is the same as the PrimaryDomain when using
1397 extended security. Windows NT 4 and 2003 use this string to store
1398 the native lanman string. Windows 9x does not include a string here
1399 at all so we have to check if we have any extra bytes left */
1401 byte_count = SVAL(inbuf, smb_vwv13);
1402 if ( PTR_DIFF(p, save_p) < byte_count)
1403 p += srvstr_pull_buf(inbuf, smb_flag2,
1404 primary_domain, p,
1405 sizeof(primary_domain),
1406 STR_TERMINATE);
1407 else
1408 fstrcpy( primary_domain, "null" );
1410 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1411 domain, native_os, native_lanman, primary_domain));
1413 if ( ra_type == RA_WIN2K ) {
1414 if ( strlen(native_lanman) == 0 )
1415 ra_lanman_string( primary_domain );
1416 else
1417 ra_lanman_string( native_lanman );
1422 if (SVAL(inbuf,smb_vwv4) == 0) {
1423 setup_new_vc_session();
1426 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
1428 if (*user) {
1429 if (global_spnego_negotiated) {
1431 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
1433 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
1434 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1436 fstrcpy(sub_user, user);
1437 } else {
1438 fstrcpy(sub_user, lp_guestaccount());
1441 sub_set_smb_name(sub_user);
1443 reload_services(True);
1445 if (lp_security() == SEC_SHARE) {
1446 /* in share level we should ignore any passwords */
1448 data_blob_free(&lm_resp);
1449 data_blob_free(&nt_resp);
1450 data_blob_clear_free(&plaintext_password);
1452 map_username(sub_user);
1453 add_session_user(sub_user);
1454 add_session_workgroup(domain);
1455 /* Then force it to null for the benfit of the code below */
1456 *user = 0;
1459 if (!*user) {
1461 nt_status = check_guest_password(&server_info);
1463 } else if (doencrypt) {
1464 if (!negprot_global_auth_context) {
1465 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
1466 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1468 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
1469 lm_resp, nt_resp);
1470 if (NT_STATUS_IS_OK(nt_status)) {
1471 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
1472 user_info,
1473 &server_info);
1475 } else {
1476 struct auth_context *plaintext_auth_context = NULL;
1477 const uint8 *chal;
1479 nt_status = make_auth_context_subsystem(&plaintext_auth_context);
1481 if (NT_STATUS_IS_OK(nt_status)) {
1482 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
1484 if (!make_user_info_for_reply(&user_info,
1485 user, domain, chal,
1486 plaintext_password)) {
1487 nt_status = NT_STATUS_NO_MEMORY;
1490 if (NT_STATUS_IS_OK(nt_status)) {
1491 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
1492 user_info,
1493 &server_info);
1495 (plaintext_auth_context->free)(&plaintext_auth_context);
1500 free_user_info(&user_info);
1502 if (!NT_STATUS_IS_OK(nt_status)) {
1503 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
1506 if (!NT_STATUS_IS_OK(nt_status)) {
1507 data_blob_free(&nt_resp);
1508 data_blob_free(&lm_resp);
1509 data_blob_clear_free(&plaintext_password);
1510 return ERROR_NT(nt_status_squash(nt_status));
1513 /* Ensure we can't possible take a code path leading to a null defref. */
1514 if (!server_info) {
1515 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1518 nt_status = create_local_token(server_info);
1519 if (!NT_STATUS_IS_OK(nt_status)) {
1520 DEBUG(10, ("create_local_token failed: %s\n",
1521 nt_errstr(nt_status)));
1522 data_blob_free(&nt_resp);
1523 data_blob_free(&lm_resp);
1524 data_blob_clear_free(&plaintext_password);
1525 return ERROR_NT(nt_status_squash(nt_status));
1528 if (server_info->user_session_key.data) {
1529 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
1530 } else {
1531 session_key = data_blob_null;
1534 data_blob_clear_free(&plaintext_password);
1536 /* it's ok - setup a reply */
1537 set_message(inbuf,outbuf,3,0,True);
1538 if (Protocol >= PROTOCOL_NT1) {
1539 char *p = smb_buf( outbuf );
1540 p += add_signature( outbuf, p );
1541 set_message_end(inbuf, outbuf, p );
1542 /* perhaps grab OS version here?? */
1545 if (server_info->guest) {
1546 SSVAL(outbuf,smb_vwv2,1);
1549 /* register the name and uid as being validated, so further connections
1550 to a uid can get through without a password, on the same VC */
1552 if (lp_security() == SEC_SHARE) {
1553 sess_vuid = UID_FIELD_INVALID;
1554 data_blob_free(&session_key);
1555 TALLOC_FREE(server_info);
1556 } else {
1557 /* register_vuid keeps the server info */
1558 sess_vuid = register_vuid(server_info, session_key,
1559 nt_resp.data ? nt_resp : lm_resp,
1560 sub_user);
1561 if (sess_vuid == UID_FIELD_INVALID) {
1562 data_blob_free(&nt_resp);
1563 data_blob_free(&lm_resp);
1564 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1567 /* current_user_info is changed on new vuid */
1568 reload_services( True );
1570 sessionsetup_start_signing_engine(server_info, inbuf);
1573 data_blob_free(&nt_resp);
1574 data_blob_free(&lm_resp);
1576 SSVAL(outbuf,smb_uid,sess_vuid);
1577 SSVAL(inbuf,smb_uid,sess_vuid);
1579 if (!done_sesssetup)
1580 max_send = MIN(max_send,smb_bufsize);
1582 done_sesssetup = True;
1584 END_PROFILE(SMBsesssetupX);
1585 return chain_reply(inbuf,outbuf,length,bufsize);