s3-rpc_server: Created a per connection spoolss pipe.
[Samba/ekacnet.git] / source3 / smbd / sesssetup.c
blobdf39aed0ed60af7ea3699e03dfbb2cd278eb530e
1 /*
2 Unix SMB/CIFS implementation.
3 handle SMBsessionsetup
4 Copyright (C) Andrew Tridgell 1998-2001
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
7 Copyright (C) Luke Howard 2003
8 Copyright (C) Volker Lendecke 2007
9 Copyright (C) Jeremy Allison 2007
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "smbd/globals.h"
27 #include "../libcli/auth/spnego.h"
28 #include "ntlmssp.h"
29 #include "librpc/gen_ndr/messaging.h"
31 /* For split krb5 SPNEGO blobs. */
32 struct pending_auth_data {
33 struct pending_auth_data *prev, *next;
34 uint16 vuid; /* Tag for this entry. */
35 uint16 smbpid; /* Alternate tag for this entry. */
36 size_t needed_len;
37 DATA_BLOB partial_data;
41 on a logon error possibly map the error to success if "map to guest"
42 is set approriately
44 static NTSTATUS do_map_to_guest(NTSTATUS status,
45 struct auth_serversupplied_info **server_info,
46 const char *user, const char *domain)
48 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
49 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
50 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
51 DEBUG(3,("No such user %s [%s] - using guest account\n",
52 user, domain));
53 status = make_server_info_guest(NULL, server_info);
57 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
58 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
59 DEBUG(3,("Registered username %s for guest access\n",
60 user));
61 status = make_server_info_guest(NULL, server_info);
65 return status;
68 /****************************************************************************
69 Add the standard 'Samba' signature to the end of the session setup.
70 ****************************************************************************/
72 static int push_signature(uint8 **outbuf)
74 char *lanman;
75 int result, tmp;
77 result = 0;
79 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
81 if (tmp == -1) return -1;
82 result += tmp;
84 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
85 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
86 SAFE_FREE(lanman);
88 else {
89 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
92 if (tmp == -1) return -1;
93 result += tmp;
95 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
97 if (tmp == -1) return -1;
98 result += tmp;
100 return result;
103 /****************************************************************************
104 Send a security blob via a session setup reply.
105 ****************************************************************************/
107 static void reply_sesssetup_blob(struct smb_request *req,
108 DATA_BLOB blob,
109 NTSTATUS nt_status)
111 if (!NT_STATUS_IS_OK(nt_status) &&
112 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
113 reply_nterror(req, nt_status_squash(nt_status));
114 return;
117 nt_status = nt_status_squash(nt_status);
118 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
119 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
120 SSVAL(req->outbuf, smb_vwv3, blob.length);
122 if ((message_push_blob(&req->outbuf, blob) == -1)
123 || (push_signature(&req->outbuf) == -1)) {
124 reply_nterror(req, NT_STATUS_NO_MEMORY);
128 /****************************************************************************
129 Do a 'guest' logon, getting back the
130 ****************************************************************************/
132 static NTSTATUS check_guest_password(struct auth_serversupplied_info **server_info)
134 struct auth_context *auth_context;
135 struct auth_usersupplied_info *user_info = NULL;
137 NTSTATUS nt_status;
138 unsigned char chal[8];
140 ZERO_STRUCT(chal);
142 DEBUG(3,("Got anonymous request\n"));
144 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context,
145 chal))) {
146 return nt_status;
149 if (!make_user_info_guest(&user_info)) {
150 (auth_context->free)(&auth_context);
151 return NT_STATUS_NO_MEMORY;
154 nt_status = auth_context->check_ntlm_password(auth_context,
155 user_info,
156 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 "
197 "for name %s: Error %s\n",
198 host_princ_s, error_message(kerr) ));
199 goto out;
202 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
203 host_princ, &reply);
204 if (kerr) {
205 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
206 "failed: Error %s\n",
207 error_message(kerr) ));
208 goto out;
211 *pblob_out = data_blob(reply.data, reply.length);
212 kerberos_free_data_contents(context,&reply);
213 ret = True;
215 out:
217 if (host_princ_s) {
218 SAFE_FREE(host_princ_s);
220 if (host_princ) {
221 krb5_free_principal(context, host_princ);
223 krb5_free_context(context);
224 return ret;
226 #endif
228 /****************************************************************************
229 Reply to a session setup spnego negotiate packet for kerberos.
230 ****************************************************************************/
232 static void reply_spnego_kerberos(struct smb_request *req,
233 DATA_BLOB *secblob,
234 const char *mechOID,
235 uint16 vuid,
236 bool *p_invalidate_vuid)
238 TALLOC_CTX *mem_ctx;
239 DATA_BLOB ticket;
240 char *client, *p, *domain;
241 fstring netbios_domain_name;
242 struct passwd *pw;
243 fstring user;
244 int sess_vuid = req->vuid;
245 NTSTATUS ret = NT_STATUS_OK;
246 DATA_BLOB ap_rep, ap_rep_wrapped, response;
247 struct auth_serversupplied_info *server_info = NULL;
248 DATA_BLOB session_key = data_blob_null;
249 uint8 tok_id[2];
250 DATA_BLOB nullblob = data_blob_null;
251 fstring real_username;
252 bool map_domainuser_to_guest = False;
253 bool username_was_mapped;
254 struct PAC_LOGON_INFO *logon_info = NULL;
255 struct smbd_server_connection *sconn = smbd_server_conn;
257 ZERO_STRUCT(ticket);
258 ZERO_STRUCT(ap_rep);
259 ZERO_STRUCT(ap_rep_wrapped);
260 ZERO_STRUCT(response);
262 /* Normally we will always invalidate the intermediate vuid. */
263 *p_invalidate_vuid = True;
265 mem_ctx = talloc_init("reply_spnego_kerberos");
266 if (mem_ctx == NULL) {
267 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
268 return;
271 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
272 talloc_destroy(mem_ctx);
273 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
274 return;
277 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
278 &client, &logon_info, &ap_rep,
279 &session_key, True);
281 data_blob_free(&ticket);
283 if (!NT_STATUS_IS_OK(ret)) {
284 #if 0
285 /* Experiment that failed.
286 * See "only happens with a KDC" comment below. */
288 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
291 * Windows in this case returns
292 * NT_STATUS_MORE_PROCESSING_REQUIRED
293 * with a negTokenTarg blob containing an krb5_error
294 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
295 * The client then fixes its clock and continues rather
296 * than giving an error. JRA.
297 * -- Looks like this only happens with a KDC. JRA.
300 bool ok = make_krb5_skew_error(&ap_rep);
301 if (!ok) {
302 talloc_destroy(mem_ctx);
303 return ERROR_NT(nt_status_squash(
304 NT_STATUS_LOGON_FAILURE));
306 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
307 TOK_ID_KRB_ERROR);
308 response = spnego_gen_auth_response(&ap_rep_wrapped,
309 ret, OID_KERBEROS5_OLD);
310 reply_sesssetup_blob(conn, inbuf, outbuf, response,
311 NT_STATUS_MORE_PROCESSING_REQUIRED);
314 * In this one case we don't invalidate the
315 * intermediate vuid as we're expecting the client
316 * to re-use it for the next sessionsetupX packet. JRA.
319 *p_invalidate_vuid = False;
321 data_blob_free(&ap_rep);
322 data_blob_free(&ap_rep_wrapped);
323 data_blob_free(&response);
324 talloc_destroy(mem_ctx);
325 return -1; /* already replied */
327 #else
328 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
329 ret = NT_STATUS_LOGON_FAILURE;
331 #endif
332 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
333 nt_errstr(ret)));
334 talloc_destroy(mem_ctx);
335 reply_nterror(req, nt_status_squash(ret));
336 return;
339 DEBUG(3,("Ticket name is [%s]\n", client));
341 p = strchr_m(client, '@');
342 if (!p) {
343 DEBUG(3,("Doesn't look like a valid principal\n"));
344 data_blob_free(&ap_rep);
345 data_blob_free(&session_key);
346 talloc_destroy(mem_ctx);
347 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
348 return;
351 *p = 0;
353 /* save the PAC data if we have it */
355 if (logon_info) {
356 netsamlogon_cache_store( client, &logon_info->info3 );
359 if (!strequal(p+1, lp_realm())) {
360 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
361 if (!lp_allow_trusted_domains()) {
362 data_blob_free(&ap_rep);
363 data_blob_free(&session_key);
364 talloc_destroy(mem_ctx);
365 reply_nterror(req, nt_status_squash(
366 NT_STATUS_LOGON_FAILURE));
367 return;
371 /* this gives a fully qualified user name (ie. with full realm).
372 that leads to very long usernames, but what else can we do? */
374 domain = p+1;
376 if (logon_info && logon_info->info3.base.domain.string) {
377 fstrcpy(netbios_domain_name,
378 logon_info->info3.base.domain.string);
379 domain = netbios_domain_name;
380 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
382 } else {
384 /* If we have winbind running, we can (and must) shorten the
385 username by using the short netbios name. Otherwise we will
386 have inconsistent user names. With Kerberos, we get the
387 fully qualified realm, with ntlmssp we get the short
388 name. And even w2k3 does use ntlmssp if you for example
389 connect to an ip address. */
391 wbcErr wbc_status;
392 struct wbcDomainInfo *info = NULL;
394 DEBUG(10, ("Mapping [%s] to short name\n", domain));
396 wbc_status = wbcDomainInfo(domain, &info);
398 if (WBC_ERROR_IS_OK(wbc_status)) {
400 fstrcpy(netbios_domain_name,
401 info->short_name);
403 wbcFreeMemory(info);
404 domain = netbios_domain_name;
405 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
406 } else {
407 DEBUG(3, ("Could not find short name: %s\n",
408 wbcErrorString(wbc_status)));
412 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
414 /* lookup the passwd struct, create a new user if necessary */
416 username_was_mapped = map_username(sconn, user);
418 pw = smb_getpwnam( mem_ctx, user, real_username, True );
420 if (pw) {
421 /* if a real user check pam account restrictions */
422 /* only really perfomed if "obey pam restriction" is true */
423 /* do this before an eventual mapping to guest occurs */
424 ret = smb_pam_accountcheck(pw->pw_name);
425 if ( !NT_STATUS_IS_OK(ret)) {
426 DEBUG(1,("PAM account restriction "
427 "prevents user login\n"));
428 data_blob_free(&ap_rep);
429 data_blob_free(&session_key);
430 TALLOC_FREE(mem_ctx);
431 reply_nterror(req, nt_status_squash(ret));
432 return;
436 if (!pw) {
438 /* this was originally the behavior of Samba 2.2, if a user
439 did not have a local uid but has been authenticated, then
440 map them to a guest account */
442 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
443 map_domainuser_to_guest = True;
444 fstrcpy(user,lp_guestaccount());
445 pw = smb_getpwnam( mem_ctx, user, real_username, True );
448 /* extra sanity check that the guest account is valid */
450 if ( !pw ) {
451 DEBUG(1,("Username %s is invalid on this system\n",
452 user));
453 data_blob_free(&ap_rep);
454 data_blob_free(&session_key);
455 TALLOC_FREE(mem_ctx);
456 reply_nterror(req, nt_status_squash(
457 NT_STATUS_LOGON_FAILURE));
458 return;
462 /* setup the string used by %U */
464 sub_set_smb_name( real_username );
465 reload_services(True);
467 if ( map_domainuser_to_guest ) {
468 make_server_info_guest(NULL, &server_info);
469 } else if (logon_info) {
470 /* pass the unmapped username here since map_username()
471 will be called again from inside make_server_info_info3() */
473 ret = make_server_info_info3(mem_ctx, client, domain,
474 &server_info, &logon_info->info3);
475 if ( !NT_STATUS_IS_OK(ret) ) {
476 DEBUG(1,("make_server_info_info3 failed: %s!\n",
477 nt_errstr(ret)));
478 data_blob_free(&ap_rep);
479 data_blob_free(&session_key);
480 TALLOC_FREE(mem_ctx);
481 reply_nterror(req, nt_status_squash(ret));
482 return;
485 } else {
487 * We didn't get a PAC, we have to make up the user
488 * ourselves. Try to ask the pdb backend to provide
489 * SID consistency with ntlmssp session setup
491 struct samu *sampass;
493 sampass = samu_new(talloc_tos());
494 if (sampass == NULL) {
495 ret = NT_STATUS_NO_MEMORY;
496 data_blob_free(&ap_rep);
497 data_blob_free(&session_key);
498 TALLOC_FREE(mem_ctx);
499 reply_nterror(req, nt_status_squash(ret));
500 return;
503 if (pdb_getsampwnam(sampass, real_username)) {
504 DEBUG(10, ("found user %s in passdb, calling "
505 "make_server_info_sam\n", real_username));
506 ret = make_server_info_sam(&server_info, sampass);
507 } else {
509 * User not in passdb, make it up artificially
511 TALLOC_FREE(sampass);
512 DEBUG(10, ("didn't find user %s in passdb, calling "
513 "make_server_info_pw\n", real_username));
514 ret = make_server_info_pw(&server_info, real_username,
515 pw);
518 if ( !NT_STATUS_IS_OK(ret) ) {
519 DEBUG(1,("make_server_info_[sam|pw] failed: %s!\n",
520 nt_errstr(ret)));
521 data_blob_free(&ap_rep);
522 data_blob_free(&session_key);
523 TALLOC_FREE(mem_ctx);
524 reply_nterror(req, nt_status_squash(ret));
525 return;
528 /* make_server_info_pw does not set the domain. Without this
529 * we end up with the local netbios name in substitutions for
530 * %D. */
532 if (server_info->sam_account != NULL) {
533 pdb_set_domain(server_info->sam_account,
534 domain, PDB_SET);
538 server_info->nss_token |= username_was_mapped;
540 /* we need to build the token for the user. make_server_info_guest()
541 already does this */
543 if ( !server_info->ptok ) {
544 ret = create_local_token( server_info );
545 if ( !NT_STATUS_IS_OK(ret) ) {
546 DEBUG(10,("failed to create local token: %s\n",
547 nt_errstr(ret)));
548 data_blob_free(&ap_rep);
549 data_blob_free(&session_key);
550 TALLOC_FREE( mem_ctx );
551 TALLOC_FREE( server_info );
552 reply_nterror(req, nt_status_squash(ret));
553 return;
557 if (!is_partial_auth_vuid(sconn, sess_vuid)) {
558 sess_vuid = register_initial_vuid(sconn);
561 data_blob_free(&server_info->user_session_key);
562 server_info->user_session_key = session_key;
563 session_key = data_blob_null;
565 /* register_existing_vuid keeps the server info */
566 /* register_existing_vuid takes ownership of session_key on success,
567 * no need to free after this on success. A better interface would copy
568 * it.... */
570 sess_vuid = register_existing_vuid(sconn,
571 sess_vuid,
572 server_info,
573 nullblob,
574 client);
576 reply_outbuf(req, 4, 0);
577 SSVAL(req->outbuf,smb_uid,sess_vuid);
579 if (sess_vuid == UID_FIELD_INVALID ) {
580 ret = NT_STATUS_LOGON_FAILURE;
581 } else {
582 /* current_user_info is changed on new vuid */
583 reload_services( True );
585 SSVAL(req->outbuf, smb_vwv3, 0);
587 if (server_info->guest) {
588 SSVAL(req->outbuf,smb_vwv2,1);
591 SSVAL(req->outbuf, smb_uid, sess_vuid);
593 /* Successful logon. Keep this vuid. */
594 *p_invalidate_vuid = False;
597 /* wrap that up in a nice GSS-API wrapping */
598 if (NT_STATUS_IS_OK(ret)) {
599 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
600 TOK_ID_KRB_AP_REP);
601 } else {
602 ap_rep_wrapped = data_blob_null;
604 response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
605 mechOID);
606 reply_sesssetup_blob(req, response, ret);
608 data_blob_free(&ap_rep);
609 data_blob_free(&ap_rep_wrapped);
610 data_blob_free(&response);
611 TALLOC_FREE(mem_ctx);
614 #endif
616 /****************************************************************************
617 Send a session setup reply, wrapped in SPNEGO.
618 Get vuid and check first.
619 End the NTLMSSP exchange context if we are OK/complete fail
620 This should be split into two functions, one to handle each
621 leg of the NTLM auth steps.
622 ***************************************************************************/
624 static void reply_spnego_ntlmssp(struct smb_request *req,
625 uint16 vuid,
626 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
627 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
628 const char *OID,
629 bool wrap)
631 DATA_BLOB response;
632 struct auth_serversupplied_info *server_info = NULL;
633 struct smbd_server_connection *sconn = smbd_server_conn;
635 if (NT_STATUS_IS_OK(nt_status)) {
636 server_info = (*auth_ntlmssp_state)->server_info;
637 } else {
638 nt_status = do_map_to_guest(nt_status,
639 &server_info,
640 (*auth_ntlmssp_state)->ntlmssp_state->user,
641 (*auth_ntlmssp_state)->ntlmssp_state->domain);
644 reply_outbuf(req, 4, 0);
646 SSVAL(req->outbuf, smb_uid, vuid);
648 if (NT_STATUS_IS_OK(nt_status)) {
649 DATA_BLOB nullblob = data_blob_null;
651 if (!is_partial_auth_vuid(sconn, vuid)) {
652 nt_status = NT_STATUS_LOGON_FAILURE;
653 goto out;
656 data_blob_free(&server_info->user_session_key);
657 server_info->user_session_key =
658 data_blob_talloc(
659 server_info,
660 (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
661 (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
663 /* register_existing_vuid keeps the server info */
664 if (register_existing_vuid(sconn, vuid,
665 server_info, nullblob,
666 (*auth_ntlmssp_state)->ntlmssp_state->user) !=
667 vuid) {
668 nt_status = NT_STATUS_LOGON_FAILURE;
669 goto out;
672 (*auth_ntlmssp_state)->server_info = NULL;
674 /* current_user_info is changed on new vuid */
675 reload_services( True );
677 SSVAL(req->outbuf, smb_vwv3, 0);
679 if (server_info->guest) {
680 SSVAL(req->outbuf,smb_vwv2,1);
684 out:
686 if (wrap) {
687 response = spnego_gen_auth_response(ntlmssp_blob,
688 nt_status, OID);
689 } else {
690 response = *ntlmssp_blob;
693 reply_sesssetup_blob(req, response, nt_status);
694 if (wrap) {
695 data_blob_free(&response);
698 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
699 and the other end, that we are not finished yet. */
701 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
702 /* NB. This is *NOT* an error case. JRA */
703 auth_ntlmssp_end(auth_ntlmssp_state);
704 if (!NT_STATUS_IS_OK(nt_status)) {
705 /* Kill the intermediate vuid */
706 invalidate_vuid(sconn, vuid);
711 /****************************************************************************
712 Is this a krb5 mechanism ?
713 ****************************************************************************/
715 NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in,
716 DATA_BLOB *pblob_out,
717 char **kerb_mechOID)
719 char *OIDs[ASN1_MAX_OIDS];
720 int i;
721 NTSTATUS ret = NT_STATUS_OK;
723 *kerb_mechOID = NULL;
725 /* parse out the OIDs and the first sec blob */
726 if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
727 return NT_STATUS_LOGON_FAILURE;
730 /* only look at the first OID for determining the mechToken --
731 according to RFC2478, we should choose the one we want
732 and renegotiate, but i smell a client bug here..
734 Problem observed when connecting to a member (samba box)
735 of an AD domain as a user in a Samba domain. Samba member
736 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
737 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
738 NTLMSSP mechtoken. --jerry */
740 #ifdef HAVE_KRB5
741 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
742 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
743 *kerb_mechOID = SMB_STRDUP(OIDs[0]);
744 if (*kerb_mechOID == NULL) {
745 ret = NT_STATUS_NO_MEMORY;
748 #endif
750 for (i=0;OIDs[i];i++) {
751 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
752 talloc_free(OIDs[i]);
754 return ret;
757 /****************************************************************************
758 Fall back from krb5 to NTLMSSP.
759 ****************************************************************************/
761 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
762 uint16 vuid)
764 DATA_BLOB response;
766 reply_outbuf(req, 4, 0);
767 SSVAL(req->outbuf,smb_uid,vuid);
769 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
770 "but set to downgrade to NTLMSSP\n"));
772 response = spnego_gen_auth_response(NULL,
773 NT_STATUS_MORE_PROCESSING_REQUIRED,
774 OID_NTLMSSP);
775 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
776 data_blob_free(&response);
779 /****************************************************************************
780 Reply to a session setup spnego negotiate packet.
781 ****************************************************************************/
783 static void reply_spnego_negotiate(struct smb_request *req,
784 uint16 vuid,
785 DATA_BLOB blob1,
786 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
788 DATA_BLOB secblob;
789 DATA_BLOB chal;
790 char *kerb_mech = NULL;
791 NTSTATUS status;
792 struct smbd_server_connection *sconn = smbd_server_conn;
794 status = parse_spnego_mechanisms(blob1, &secblob, &kerb_mech);
795 if (!NT_STATUS_IS_OK(status)) {
796 /* Kill the intermediate vuid */
797 invalidate_vuid(sconn, vuid);
798 reply_nterror(req, nt_status_squash(status));
799 return;
802 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
803 (unsigned long)secblob.length));
805 #ifdef HAVE_KRB5
806 if (kerb_mech && ((lp_security()==SEC_ADS) ||
807 USE_KERBEROS_KEYTAB) ) {
808 bool destroy_vuid = True;
809 reply_spnego_kerberos(req, &secblob, kerb_mech,
810 vuid, &destroy_vuid);
811 data_blob_free(&secblob);
812 if (destroy_vuid) {
813 /* Kill the intermediate vuid */
814 invalidate_vuid(sconn, vuid);
816 SAFE_FREE(kerb_mech);
817 return;
819 #endif
821 if (*auth_ntlmssp_state) {
822 auth_ntlmssp_end(auth_ntlmssp_state);
825 if (kerb_mech) {
826 data_blob_free(&secblob);
827 /* The mechtoken is a krb5 ticket, but
828 * we need to fall back to NTLM. */
829 reply_spnego_downgrade_to_ntlmssp(req, vuid);
830 SAFE_FREE(kerb_mech);
831 return;
834 status = auth_ntlmssp_start(auth_ntlmssp_state);
835 if (!NT_STATUS_IS_OK(status)) {
836 /* Kill the intermediate vuid */
837 invalidate_vuid(sconn, vuid);
838 reply_nterror(req, nt_status_squash(status));
839 return;
842 status = auth_ntlmssp_update(*auth_ntlmssp_state,
843 secblob, &chal);
845 data_blob_free(&secblob);
847 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
848 &chal, status, OID_NTLMSSP, true);
850 data_blob_free(&chal);
852 /* already replied */
853 return;
856 /****************************************************************************
857 Reply to a session setup spnego auth packet.
858 ****************************************************************************/
860 static void reply_spnego_auth(struct smb_request *req,
861 uint16 vuid,
862 DATA_BLOB blob1,
863 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
865 DATA_BLOB auth = data_blob_null;
866 DATA_BLOB auth_reply = data_blob_null;
867 DATA_BLOB secblob = data_blob_null;
868 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
869 struct smbd_server_connection *sconn = smbd_server_conn;
871 if (!spnego_parse_auth(blob1, &auth)) {
872 #if 0
873 file_save("auth.dat", blob1.data, blob1.length);
874 #endif
875 /* Kill the intermediate vuid */
876 invalidate_vuid(sconn, vuid);
878 reply_nterror(req, nt_status_squash(
879 NT_STATUS_LOGON_FAILURE));
880 return;
883 if (auth.data[0] == ASN1_APPLICATION(0)) {
884 /* Might be a second negTokenTarg packet */
885 char *kerb_mech = NULL;
887 status = parse_spnego_mechanisms(auth, &secblob, &kerb_mech);
889 if (!NT_STATUS_IS_OK(status)) {
890 /* Kill the intermediate vuid */
891 invalidate_vuid(sconn, vuid);
892 reply_nterror(req, nt_status_squash(status));
893 return;
896 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
897 (unsigned long)secblob.length));
898 #ifdef HAVE_KRB5
899 if (kerb_mech && ((lp_security()==SEC_ADS) ||
900 USE_KERBEROS_KEYTAB)) {
901 bool destroy_vuid = True;
902 reply_spnego_kerberos(req, &secblob, kerb_mech,
903 vuid, &destroy_vuid);
904 data_blob_free(&secblob);
905 data_blob_free(&auth);
906 if (destroy_vuid) {
907 /* Kill the intermediate vuid */
908 invalidate_vuid(sconn, vuid);
910 SAFE_FREE(kerb_mech);
911 return;
913 #endif
914 /* Can't blunder into NTLMSSP auth if we have
915 * a krb5 ticket. */
917 if (kerb_mech) {
918 /* Kill the intermediate vuid */
919 invalidate_vuid(sconn, vuid);
920 DEBUG(3,("reply_spnego_auth: network "
921 "misconfiguration, client sent us a "
922 "krb5 ticket and kerberos security "
923 "not enabled\n"));
924 reply_nterror(req, nt_status_squash(
925 NT_STATUS_LOGON_FAILURE));
926 SAFE_FREE(kerb_mech);
930 /* If we get here it wasn't a negTokenTarg auth packet. */
931 data_blob_free(&secblob);
933 if (!*auth_ntlmssp_state) {
934 status = auth_ntlmssp_start(auth_ntlmssp_state);
935 if (!NT_STATUS_IS_OK(status)) {
936 /* Kill the intermediate vuid */
937 invalidate_vuid(sconn, vuid);
938 reply_nterror(req, nt_status_squash(status));
939 return;
943 status = auth_ntlmssp_update(*auth_ntlmssp_state,
944 auth, &auth_reply);
946 data_blob_free(&auth);
948 /* Don't send the mechid as we've already sent this (RFC4178). */
950 reply_spnego_ntlmssp(req, vuid,
951 auth_ntlmssp_state,
952 &auth_reply, status, NULL, true);
954 data_blob_free(&auth_reply);
956 /* and tell smbd that we have already replied to this packet */
957 return;
960 /****************************************************************************
961 Delete an entry on the list.
962 ****************************************************************************/
964 static void delete_partial_auth(struct smbd_server_connection *sconn,
965 struct pending_auth_data *pad)
967 if (!pad) {
968 return;
970 DLIST_REMOVE(sconn->smb1.pd_list, pad);
971 data_blob_free(&pad->partial_data);
972 SAFE_FREE(pad);
975 /****************************************************************************
976 Search for a partial SPNEGO auth fragment matching an smbpid.
977 ****************************************************************************/
979 static struct pending_auth_data *get_pending_auth_data(
980 struct smbd_server_connection *sconn,
981 uint16_t smbpid)
983 struct pending_auth_data *pad;
985 * NOTE: using the smbpid here is completely wrong...
986 * see [MS-SMB]
987 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
989 for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
990 if (pad->smbpid == smbpid) {
991 break;
994 return pad;
997 /****************************************************************************
998 Check the size of an SPNEGO blob. If we need more return
999 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
1000 the blob to be more than 64k.
1001 ****************************************************************************/
1003 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
1004 uint16 smbpid, uint16 vuid,
1005 DATA_BLOB *pblob)
1007 struct pending_auth_data *pad = NULL;
1008 ASN1_DATA *data;
1009 size_t needed_len = 0;
1011 pad = get_pending_auth_data(sconn, smbpid);
1013 /* Ensure we have some data. */
1014 if (pblob->length == 0) {
1015 /* Caller can cope. */
1016 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
1017 delete_partial_auth(sconn, pad);
1018 return NT_STATUS_OK;
1021 /* Were we waiting for more data ? */
1022 if (pad) {
1023 DATA_BLOB tmp_blob;
1024 size_t copy_len = MIN(65536, pblob->length);
1026 /* Integer wrap paranoia.... */
1028 if (pad->partial_data.length + copy_len <
1029 pad->partial_data.length ||
1030 pad->partial_data.length + copy_len < copy_len) {
1032 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1033 "pad->partial_data.length = %u, "
1034 "copy_len = %u\n",
1035 (unsigned int)pad->partial_data.length,
1036 (unsigned int)copy_len ));
1038 delete_partial_auth(sconn, pad);
1039 return NT_STATUS_INVALID_PARAMETER;
1042 DEBUG(10,("check_spnego_blob_complete: "
1043 "pad->partial_data.length = %u, "
1044 "pad->needed_len = %u, "
1045 "copy_len = %u, "
1046 "pblob->length = %u,\n",
1047 (unsigned int)pad->partial_data.length,
1048 (unsigned int)pad->needed_len,
1049 (unsigned int)copy_len,
1050 (unsigned int)pblob->length ));
1052 tmp_blob = data_blob(NULL,
1053 pad->partial_data.length + copy_len);
1055 /* Concatenate the two (up to copy_len) bytes. */
1056 memcpy(tmp_blob.data,
1057 pad->partial_data.data,
1058 pad->partial_data.length);
1059 memcpy(tmp_blob.data + pad->partial_data.length,
1060 pblob->data,
1061 copy_len);
1063 /* Replace the partial data. */
1064 data_blob_free(&pad->partial_data);
1065 pad->partial_data = tmp_blob;
1066 ZERO_STRUCT(tmp_blob);
1068 /* Are we done ? */
1069 if (pblob->length >= pad->needed_len) {
1070 /* Yes, replace pblob. */
1071 data_blob_free(pblob);
1072 *pblob = pad->partial_data;
1073 ZERO_STRUCT(pad->partial_data);
1074 delete_partial_auth(sconn, pad);
1075 return NT_STATUS_OK;
1078 /* Still need more data. */
1079 pad->needed_len -= copy_len;
1080 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1083 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
1084 (pblob->data[0] != ASN1_CONTEXT(1))) {
1085 /* Not something we can determine the
1086 * length of.
1088 return NT_STATUS_OK;
1091 /* This is a new SPNEGO sessionsetup - see if
1092 * the data given in this blob is enough.
1095 data = asn1_init(NULL);
1096 if (data == NULL) {
1097 return NT_STATUS_NO_MEMORY;
1100 asn1_load(data, *pblob);
1101 asn1_start_tag(data, pblob->data[0]);
1102 if (data->has_error || data->nesting == NULL) {
1103 asn1_free(data);
1104 /* Let caller catch. */
1105 return NT_STATUS_OK;
1108 /* Integer wrap paranoia.... */
1110 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
1111 data->nesting->taglen + data->nesting->start < data->nesting->start) {
1113 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1114 "data.nesting->taglen = %u, "
1115 "data.nesting->start = %u\n",
1116 (unsigned int)data->nesting->taglen,
1117 (unsigned int)data->nesting->start ));
1119 asn1_free(data);
1120 return NT_STATUS_INVALID_PARAMETER;
1123 /* Total length of the needed asn1 is the tag length
1124 * plus the current offset. */
1126 needed_len = data->nesting->taglen + data->nesting->start;
1127 asn1_free(data);
1129 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1130 "pblob->length = %u\n",
1131 (unsigned int)needed_len,
1132 (unsigned int)pblob->length ));
1134 if (needed_len <= pblob->length) {
1135 /* Nothing to do - blob is complete. */
1136 return NT_STATUS_OK;
1139 /* Refuse the blob if it's bigger than 64k. */
1140 if (needed_len > 65536) {
1141 DEBUG(2,("check_spnego_blob_complete: needed_len "
1142 "too large (%u)\n",
1143 (unsigned int)needed_len ));
1144 return NT_STATUS_INVALID_PARAMETER;
1147 /* We must store this blob until complete. */
1148 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1149 return NT_STATUS_NO_MEMORY;
1151 pad->needed_len = needed_len - pblob->length;
1152 pad->partial_data = data_blob(pblob->data, pblob->length);
1153 if (pad->partial_data.data == NULL) {
1154 SAFE_FREE(pad);
1155 return NT_STATUS_NO_MEMORY;
1157 pad->smbpid = smbpid;
1158 pad->vuid = vuid;
1159 DLIST_ADD(sconn->smb1.pd_list, pad);
1161 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1164 /****************************************************************************
1165 Reply to a session setup command.
1166 conn POINTER CAN BE NULL HERE !
1167 ****************************************************************************/
1169 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1171 const uint8 *p;
1172 DATA_BLOB blob1;
1173 size_t bufrem;
1174 char *tmp;
1175 const char *native_os;
1176 const char *native_lanman;
1177 const char *primary_domain;
1178 const char *p2;
1179 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1180 enum remote_arch_types ra_type = get_remote_arch();
1181 int vuid = req->vuid;
1182 user_struct *vuser = NULL;
1183 NTSTATUS status = NT_STATUS_OK;
1184 uint16 smbpid = req->smbpid;
1185 struct smbd_server_connection *sconn = smbd_server_conn;
1187 DEBUG(3,("Doing spnego session setup\n"));
1189 if (global_client_caps == 0) {
1190 global_client_caps = IVAL(req->vwv+10, 0);
1192 if (!(global_client_caps & CAP_STATUS32)) {
1193 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1198 p = req->buf;
1200 if (data_blob_len == 0) {
1201 /* an invalid request */
1202 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1203 return;
1206 bufrem = smbreq_bufrem(req, p);
1207 /* pull the spnego blob */
1208 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1210 #if 0
1211 file_save("negotiate.dat", blob1.data, blob1.length);
1212 #endif
1214 p2 = (char *)req->buf + blob1.length;
1216 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1217 STR_TERMINATE);
1218 native_os = tmp ? tmp : "";
1220 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1221 STR_TERMINATE);
1222 native_lanman = tmp ? tmp : "";
1224 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1225 STR_TERMINATE);
1226 primary_domain = tmp ? tmp : "";
1228 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1229 native_os, native_lanman, primary_domain));
1231 if ( ra_type == RA_WIN2K ) {
1232 /* Vista sets neither the OS or lanman strings */
1234 if ( !strlen(native_os) && !strlen(native_lanman) )
1235 set_remote_arch(RA_VISTA);
1237 /* Windows 2003 doesn't set the native lanman string,
1238 but does set primary domain which is a bug I think */
1240 if ( !strlen(native_lanman) ) {
1241 ra_lanman_string( primary_domain );
1242 } else {
1243 ra_lanman_string( native_lanman );
1247 /* Did we get a valid vuid ? */
1248 if (!is_partial_auth_vuid(sconn, vuid)) {
1249 /* No, then try and see if this is an intermediate sessionsetup
1250 * for a large SPNEGO packet. */
1251 struct pending_auth_data *pad;
1252 pad = get_pending_auth_data(sconn, smbpid);
1253 if (pad) {
1254 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1255 "pending vuid %u\n",
1256 (unsigned int)pad->vuid ));
1257 vuid = pad->vuid;
1261 /* Do we have a valid vuid now ? */
1262 if (!is_partial_auth_vuid(sconn, vuid)) {
1263 /* No, start a new authentication setup. */
1264 vuid = register_initial_vuid(sconn);
1265 if (vuid == UID_FIELD_INVALID) {
1266 data_blob_free(&blob1);
1267 reply_nterror(req, nt_status_squash(
1268 NT_STATUS_INVALID_PARAMETER));
1269 return;
1273 vuser = get_partial_auth_user_struct(sconn, vuid);
1274 /* This MUST be valid. */
1275 if (!vuser) {
1276 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1279 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1280 * sessionsetup requests as the Windows limit on the security blob
1281 * field is 4k. Bug #4400. JRA.
1284 status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1285 if (!NT_STATUS_IS_OK(status)) {
1286 if (!NT_STATUS_EQUAL(status,
1287 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1288 /* Real error - kill the intermediate vuid */
1289 invalidate_vuid(sconn, vuid);
1291 data_blob_free(&blob1);
1292 reply_nterror(req, nt_status_squash(status));
1293 return;
1296 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1298 /* its a negTokenTarg packet */
1300 reply_spnego_negotiate(req, vuid, blob1,
1301 &vuser->auth_ntlmssp_state);
1302 data_blob_free(&blob1);
1303 return;
1306 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1308 /* its a auth packet */
1310 reply_spnego_auth(req, vuid, blob1,
1311 &vuser->auth_ntlmssp_state);
1312 data_blob_free(&blob1);
1313 return;
1316 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1317 DATA_BLOB chal;
1319 if (!vuser->auth_ntlmssp_state) {
1320 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1321 if (!NT_STATUS_IS_OK(status)) {
1322 /* Kill the intermediate vuid */
1323 invalidate_vuid(sconn, vuid);
1324 data_blob_free(&blob1);
1325 reply_nterror(req, nt_status_squash(status));
1326 return;
1330 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1331 blob1, &chal);
1333 data_blob_free(&blob1);
1335 reply_spnego_ntlmssp(req, vuid,
1336 &vuser->auth_ntlmssp_state,
1337 &chal, status, OID_NTLMSSP, false);
1338 data_blob_free(&chal);
1339 return;
1342 /* what sort of packet is this? */
1343 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1345 data_blob_free(&blob1);
1347 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1350 /****************************************************************************
1351 On new VC == 0, shutdown *all* old connections and users.
1352 It seems that only NT4.x does this. At W2K and above (XP etc.).
1353 a new session setup with VC==0 is ignored.
1354 ****************************************************************************/
1356 static int shutdown_other_smbds(const struct connections_key *key,
1357 const struct connections_data *crec,
1358 void *private_data)
1360 const char *ip = (const char *)private_data;
1362 if (!process_exists(crec->pid)) {
1363 return 0;
1366 if (procid_is_me(&crec->pid)) {
1367 return 0;
1370 if (strcmp(ip, crec->addr) != 0) {
1371 return 0;
1374 DEBUG(0,("shutdown_other_smbds: shutting down pid %u "
1375 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid), ip));
1377 messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1378 &data_blob_null);
1379 return 0;
1382 static void setup_new_vc_session(void)
1384 char addr[INET6_ADDRSTRLEN];
1386 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1387 "compatible we would close all old resources.\n"));
1388 #if 0
1389 conn_close_all();
1390 invalidate_all_vuids();
1391 #endif
1392 if (lp_reset_on_zero_vc()) {
1393 connections_forall_read(shutdown_other_smbds,
1394 CONST_DISCARD(void *,
1395 client_addr(get_client_fd(),addr,sizeof(addr))));
1399 /****************************************************************************
1400 Reply to a session setup command.
1401 ****************************************************************************/
1403 void reply_sesssetup_and_X(struct smb_request *req)
1405 int sess_vuid;
1406 int smb_bufsize;
1407 DATA_BLOB lm_resp;
1408 DATA_BLOB nt_resp;
1409 DATA_BLOB plaintext_password;
1410 char *tmp;
1411 const char *user;
1412 fstring sub_user; /* Sainitised username for substituion */
1413 const char *domain;
1414 const char *native_os;
1415 const char *native_lanman;
1416 const char *primary_domain;
1417 struct auth_usersupplied_info *user_info = NULL;
1418 struct auth_serversupplied_info *server_info = NULL;
1419 uint16 smb_flag2 = req->flags2;
1421 NTSTATUS nt_status;
1422 struct smbd_server_connection *sconn = smbd_server_conn;
1424 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1426 START_PROFILE(SMBsesssetupX);
1428 ZERO_STRUCT(lm_resp);
1429 ZERO_STRUCT(nt_resp);
1430 ZERO_STRUCT(plaintext_password);
1432 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1434 /* a SPNEGO session setup has 12 command words, whereas a normal
1435 NT1 session setup has 13. See the cifs spec. */
1436 if (req->wct == 12 &&
1437 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1439 if (!sconn->smb1.negprot.spnego) {
1440 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1441 "at SPNEGO session setup when it was not "
1442 "negotiated.\n"));
1443 reply_nterror(req, nt_status_squash(
1444 NT_STATUS_LOGON_FAILURE));
1445 END_PROFILE(SMBsesssetupX);
1446 return;
1449 if (SVAL(req->vwv+4, 0) == 0) {
1450 setup_new_vc_session();
1453 reply_sesssetup_and_X_spnego(req);
1454 END_PROFILE(SMBsesssetupX);
1455 return;
1458 smb_bufsize = SVAL(req->vwv+2, 0);
1460 if (get_Protocol() < PROTOCOL_NT1) {
1461 uint16 passlen1 = SVAL(req->vwv+7, 0);
1463 /* Never do NT status codes with protocols before NT1 as we
1464 * don't get client caps. */
1465 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1467 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1468 reply_nterror(req, nt_status_squash(
1469 NT_STATUS_INVALID_PARAMETER));
1470 END_PROFILE(SMBsesssetupX);
1471 return;
1474 if (doencrypt) {
1475 lm_resp = data_blob(req->buf, passlen1);
1476 } else {
1477 plaintext_password = data_blob(req->buf, passlen1+1);
1478 /* Ensure null termination */
1479 plaintext_password.data[passlen1] = 0;
1482 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1483 req->buf + passlen1, STR_TERMINATE);
1484 user = tmp ? tmp : "";
1486 domain = "";
1488 } else {
1489 uint16 passlen1 = SVAL(req->vwv+7, 0);
1490 uint16 passlen2 = SVAL(req->vwv+8, 0);
1491 enum remote_arch_types ra_type = get_remote_arch();
1492 const uint8_t *p = req->buf;
1493 const uint8_t *save_p = req->buf;
1494 uint16 byte_count;
1497 if(global_client_caps == 0) {
1498 global_client_caps = IVAL(req->vwv+11, 0);
1500 if (!(global_client_caps & CAP_STATUS32)) {
1501 remove_from_common_flags2(
1502 FLAGS2_32_BIT_ERROR_CODES);
1505 /* client_caps is used as final determination if
1506 * client is NT or Win95. This is needed to return
1507 * the correct error codes in some circumstances.
1510 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1511 ra_type == RA_WIN95) {
1512 if(!(global_client_caps & (CAP_NT_SMBS|
1513 CAP_STATUS32))) {
1514 set_remote_arch( RA_WIN95);
1519 if (!doencrypt) {
1520 /* both Win95 and WinNT stuff up the password
1521 * lengths for non-encrypting systems. Uggh.
1523 if passlen1==24 its a win95 system, and its setting
1524 the password length incorrectly. Luckily it still
1525 works with the default code because Win95 will null
1526 terminate the password anyway
1528 if passlen1>0 and passlen2>0 then maybe its a NT box
1529 and its setting passlen2 to some random value which
1530 really stuffs things up. we need to fix that one. */
1532 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1533 passlen2 != 1) {
1534 passlen2 = 0;
1538 /* check for nasty tricks */
1539 if (passlen1 > MAX_PASS_LEN
1540 || passlen1 > smbreq_bufrem(req, p)) {
1541 reply_nterror(req, nt_status_squash(
1542 NT_STATUS_INVALID_PARAMETER));
1543 END_PROFILE(SMBsesssetupX);
1544 return;
1547 if (passlen2 > MAX_PASS_LEN
1548 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1549 reply_nterror(req, nt_status_squash(
1550 NT_STATUS_INVALID_PARAMETER));
1551 END_PROFILE(SMBsesssetupX);
1552 return;
1555 /* Save the lanman2 password and the NT md4 password. */
1557 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1558 doencrypt = False;
1561 if (doencrypt) {
1562 lm_resp = data_blob(p, passlen1);
1563 nt_resp = data_blob(p+passlen1, passlen2);
1564 } else if (lp_security() != SEC_SHARE) {
1566 * In share level we should ignore any passwords, so
1567 * only read them if we're not.
1569 char *pass = NULL;
1570 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1572 if (unic && (passlen2 == 0) && passlen1) {
1573 /* Only a ascii plaintext password was sent. */
1574 (void)srvstr_pull_talloc(talloc_tos(),
1575 req->inbuf,
1576 req->flags2,
1577 &pass,
1578 req->buf,
1579 passlen1,
1580 STR_TERMINATE|STR_ASCII);
1581 } else {
1582 (void)srvstr_pull_talloc(talloc_tos(),
1583 req->inbuf,
1584 req->flags2,
1585 &pass,
1586 req->buf,
1587 unic ? passlen2 : passlen1,
1588 STR_TERMINATE);
1590 if (!pass) {
1591 reply_nterror(req, nt_status_squash(
1592 NT_STATUS_INVALID_PARAMETER));
1593 END_PROFILE(SMBsesssetupX);
1594 return;
1596 plaintext_password = data_blob(pass, strlen(pass)+1);
1599 p += passlen1 + passlen2;
1601 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1602 STR_TERMINATE);
1603 user = tmp ? tmp : "";
1605 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1606 STR_TERMINATE);
1607 domain = tmp ? tmp : "";
1609 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1610 STR_TERMINATE);
1611 native_os = tmp ? tmp : "";
1613 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1614 STR_TERMINATE);
1615 native_lanman = tmp ? tmp : "";
1617 /* not documented or decoded by Ethereal but there is one more
1618 * string in the extra bytes which is the same as the
1619 * PrimaryDomain when using extended security. Windows NT 4
1620 * and 2003 use this string to store the native lanman string.
1621 * Windows 9x does not include a string here at all so we have
1622 * to check if we have any extra bytes left */
1624 byte_count = SVAL(req->vwv+13, 0);
1625 if ( PTR_DIFF(p, save_p) < byte_count) {
1626 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1627 STR_TERMINATE);
1628 primary_domain = tmp ? tmp : "";
1629 } else {
1630 primary_domain = talloc_strdup(talloc_tos(), "null");
1633 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1634 "PrimaryDomain=[%s]\n",
1635 domain, native_os, native_lanman, primary_domain));
1637 if ( ra_type == RA_WIN2K ) {
1638 if ( strlen(native_lanman) == 0 )
1639 ra_lanman_string( primary_domain );
1640 else
1641 ra_lanman_string( native_lanman );
1646 if (SVAL(req->vwv+4, 0) == 0) {
1647 setup_new_vc_session();
1650 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1651 domain, user, get_remote_machine_name()));
1653 if (*user) {
1654 if (sconn->smb1.negprot.spnego) {
1656 /* This has to be here, because this is a perfectly
1657 * valid behaviour for guest logons :-( */
1659 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1660 "at 'normal' session setup after "
1661 "negotiating spnego.\n"));
1662 reply_nterror(req, nt_status_squash(
1663 NT_STATUS_LOGON_FAILURE));
1664 END_PROFILE(SMBsesssetupX);
1665 return;
1667 fstrcpy(sub_user, user);
1668 } else {
1669 fstrcpy(sub_user, lp_guestaccount());
1672 sub_set_smb_name(sub_user);
1674 reload_services(True);
1676 if (lp_security() == SEC_SHARE) {
1677 /* In share level we should ignore any passwords */
1679 data_blob_free(&lm_resp);
1680 data_blob_free(&nt_resp);
1681 data_blob_clear_free(&plaintext_password);
1683 map_username(sconn, sub_user);
1684 add_session_user(sconn, sub_user);
1685 add_session_workgroup(sconn, domain);
1686 /* Then force it to null for the benfit of the code below */
1687 user = "";
1690 if (!*user) {
1692 nt_status = check_guest_password(&server_info);
1694 } else if (doencrypt) {
1695 struct auth_context *negprot_auth_context = NULL;
1696 negprot_auth_context = sconn->smb1.negprot.auth_context;
1697 if (!negprot_auth_context) {
1698 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1699 "session setup without negprot denied!\n"));
1700 reply_nterror(req, nt_status_squash(
1701 NT_STATUS_LOGON_FAILURE));
1702 END_PROFILE(SMBsesssetupX);
1703 return;
1705 nt_status = make_user_info_for_reply_enc(&user_info, user,
1706 domain,
1707 lm_resp, nt_resp);
1708 if (NT_STATUS_IS_OK(nt_status)) {
1709 nt_status = negprot_auth_context->check_ntlm_password(
1710 negprot_auth_context,
1711 user_info,
1712 &server_info);
1714 } else {
1715 struct auth_context *plaintext_auth_context = NULL;
1717 nt_status = make_auth_context_subsystem(
1718 &plaintext_auth_context);
1720 if (NT_STATUS_IS_OK(nt_status)) {
1721 uint8_t chal[8];
1723 plaintext_auth_context->get_ntlm_challenge(
1724 plaintext_auth_context, chal);
1726 if (!make_user_info_for_reply(&user_info,
1727 user, domain, chal,
1728 plaintext_password)) {
1729 nt_status = NT_STATUS_NO_MEMORY;
1732 if (NT_STATUS_IS_OK(nt_status)) {
1733 nt_status = plaintext_auth_context->check_ntlm_password(
1734 plaintext_auth_context,
1735 user_info,
1736 &server_info);
1738 (plaintext_auth_context->free)(
1739 &plaintext_auth_context);
1744 free_user_info(&user_info);
1746 if (!NT_STATUS_IS_OK(nt_status)) {
1747 nt_status = do_map_to_guest(nt_status, &server_info,
1748 user, domain);
1751 if (!NT_STATUS_IS_OK(nt_status)) {
1752 data_blob_free(&nt_resp);
1753 data_blob_free(&lm_resp);
1754 data_blob_clear_free(&plaintext_password);
1755 reply_nterror(req, nt_status_squash(nt_status));
1756 END_PROFILE(SMBsesssetupX);
1757 return;
1760 /* Ensure we can't possible take a code path leading to a
1761 * null defref. */
1762 if (!server_info) {
1763 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1764 END_PROFILE(SMBsesssetupX);
1765 return;
1768 if (!server_info->ptok) {
1769 nt_status = create_local_token(server_info);
1771 if (!NT_STATUS_IS_OK(nt_status)) {
1772 DEBUG(10, ("create_local_token failed: %s\n",
1773 nt_errstr(nt_status)));
1774 data_blob_free(&nt_resp);
1775 data_blob_free(&lm_resp);
1776 data_blob_clear_free(&plaintext_password);
1777 reply_nterror(req, nt_status_squash(nt_status));
1778 END_PROFILE(SMBsesssetupX);
1779 return;
1783 data_blob_clear_free(&plaintext_password);
1785 /* it's ok - setup a reply */
1786 reply_outbuf(req, 3, 0);
1787 if (get_Protocol() >= PROTOCOL_NT1) {
1788 push_signature(&req->outbuf);
1789 /* perhaps grab OS version here?? */
1792 if (server_info->guest) {
1793 SSVAL(req->outbuf,smb_vwv2,1);
1796 /* register the name and uid as being validated, so further connections
1797 to a uid can get through without a password, on the same VC */
1799 if (lp_security() == SEC_SHARE) {
1800 sess_vuid = UID_FIELD_INVALID;
1801 TALLOC_FREE(server_info);
1802 } else {
1803 /* Ignore the initial vuid. */
1804 sess_vuid = register_initial_vuid(sconn);
1805 if (sess_vuid == UID_FIELD_INVALID) {
1806 data_blob_free(&nt_resp);
1807 data_blob_free(&lm_resp);
1808 reply_nterror(req, nt_status_squash(
1809 NT_STATUS_LOGON_FAILURE));
1810 END_PROFILE(SMBsesssetupX);
1811 return;
1813 /* register_existing_vuid keeps the server info */
1814 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1815 server_info,
1816 nt_resp.data ? nt_resp : lm_resp,
1817 sub_user);
1818 if (sess_vuid == UID_FIELD_INVALID) {
1819 data_blob_free(&nt_resp);
1820 data_blob_free(&lm_resp);
1821 reply_nterror(req, nt_status_squash(
1822 NT_STATUS_LOGON_FAILURE));
1823 END_PROFILE(SMBsesssetupX);
1824 return;
1827 /* current_user_info is changed on new vuid */
1828 reload_services( True );
1831 data_blob_free(&nt_resp);
1832 data_blob_free(&lm_resp);
1834 SSVAL(req->outbuf,smb_uid,sess_vuid);
1835 SSVAL(req->inbuf,smb_uid,sess_vuid);
1836 req->vuid = sess_vuid;
1838 if (!sconn->smb1.sessions.done_sesssetup) {
1839 sconn->smb1.sessions.max_send =
1840 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1842 sconn->smb1.sessions.done_sesssetup = true;
1844 END_PROFILE(SMBsesssetupX);
1845 chain_reply(req);
1846 return;