s3-waf: Set HAVE_GSSAPI if gssapi libs were found
[Samba/gebeck_regimport.git] / source3 / smbd / sesssetup.c
blob9d0c68512c9ba9cac9b8f9f696dc1d6c430ada00
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 TALLOC_FREE(sampass);
508 } else {
510 * User not in passdb, make it up artificially
512 TALLOC_FREE(sampass);
513 DEBUG(10, ("didn't find user %s in passdb, calling "
514 "make_server_info_pw\n", real_username));
515 ret = make_server_info_pw(&server_info, real_username,
516 pw);
519 if ( !NT_STATUS_IS_OK(ret) ) {
520 DEBUG(1,("make_server_info_[sam|pw] failed: %s!\n",
521 nt_errstr(ret)));
522 data_blob_free(&ap_rep);
523 data_blob_free(&session_key);
524 TALLOC_FREE(mem_ctx);
525 reply_nterror(req, nt_status_squash(ret));
526 return;
529 /* make_server_info_pw does not set the domain. Without this
530 * we end up with the local netbios name in substitutions for
531 * %D. */
533 if (server_info->info3 != NULL) {
534 server_info->info3->base.domain.string =
535 talloc_strdup(server_info->info3, domain);
539 server_info->nss_token |= username_was_mapped;
541 /* we need to build the token for the user. make_server_info_guest()
542 already does this */
544 if ( !server_info->ptok ) {
545 ret = create_local_token( server_info );
546 if ( !NT_STATUS_IS_OK(ret) ) {
547 DEBUG(10,("failed to create local token: %s\n",
548 nt_errstr(ret)));
549 data_blob_free(&ap_rep);
550 data_blob_free(&session_key);
551 TALLOC_FREE( mem_ctx );
552 TALLOC_FREE( server_info );
553 reply_nterror(req, nt_status_squash(ret));
554 return;
558 if (!is_partial_auth_vuid(sconn, sess_vuid)) {
559 sess_vuid = register_initial_vuid(sconn);
562 data_blob_free(&server_info->user_session_key);
563 server_info->user_session_key = session_key;
564 session_key = data_blob_null;
566 /* register_existing_vuid keeps the server info */
567 /* register_existing_vuid takes ownership of session_key on success,
568 * no need to free after this on success. A better interface would copy
569 * it.... */
571 sess_vuid = register_existing_vuid(sconn,
572 sess_vuid,
573 server_info,
574 nullblob,
575 client);
577 reply_outbuf(req, 4, 0);
578 SSVAL(req->outbuf,smb_uid,sess_vuid);
580 if (sess_vuid == UID_FIELD_INVALID ) {
581 ret = NT_STATUS_LOGON_FAILURE;
582 } else {
583 /* current_user_info is changed on new vuid */
584 reload_services( True );
586 SSVAL(req->outbuf, smb_vwv3, 0);
588 if (server_info->guest) {
589 SSVAL(req->outbuf,smb_vwv2,1);
592 SSVAL(req->outbuf, smb_uid, sess_vuid);
594 /* Successful logon. Keep this vuid. */
595 *p_invalidate_vuid = False;
598 /* wrap that up in a nice GSS-API wrapping */
599 if (NT_STATUS_IS_OK(ret)) {
600 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
601 TOK_ID_KRB_AP_REP);
602 } else {
603 ap_rep_wrapped = data_blob_null;
605 response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
606 mechOID);
607 reply_sesssetup_blob(req, response, ret);
609 data_blob_free(&ap_rep);
610 data_blob_free(&ap_rep_wrapped);
611 data_blob_free(&response);
612 TALLOC_FREE(mem_ctx);
615 #endif
617 /****************************************************************************
618 Send a session setup reply, wrapped in SPNEGO.
619 Get vuid and check first.
620 End the NTLMSSP exchange context if we are OK/complete fail
621 This should be split into two functions, one to handle each
622 leg of the NTLM auth steps.
623 ***************************************************************************/
625 static void reply_spnego_ntlmssp(struct smb_request *req,
626 uint16 vuid,
627 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
628 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
629 const char *OID,
630 bool wrap)
632 DATA_BLOB response;
633 struct auth_serversupplied_info *server_info = NULL;
634 struct smbd_server_connection *sconn = smbd_server_conn;
636 if (NT_STATUS_IS_OK(nt_status)) {
637 server_info = (*auth_ntlmssp_state)->server_info;
638 } else {
639 nt_status = do_map_to_guest(nt_status,
640 &server_info,
641 (*auth_ntlmssp_state)->ntlmssp_state->user,
642 (*auth_ntlmssp_state)->ntlmssp_state->domain);
645 reply_outbuf(req, 4, 0);
647 SSVAL(req->outbuf, smb_uid, vuid);
649 if (NT_STATUS_IS_OK(nt_status)) {
650 DATA_BLOB nullblob = data_blob_null;
652 if (!is_partial_auth_vuid(sconn, vuid)) {
653 nt_status = NT_STATUS_LOGON_FAILURE;
654 goto out;
657 data_blob_free(&server_info->user_session_key);
658 server_info->user_session_key =
659 data_blob_talloc(
660 server_info,
661 (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
662 (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
664 /* register_existing_vuid keeps the server info */
665 if (register_existing_vuid(sconn, vuid,
666 server_info, nullblob,
667 (*auth_ntlmssp_state)->ntlmssp_state->user) !=
668 vuid) {
669 nt_status = NT_STATUS_LOGON_FAILURE;
670 goto out;
673 (*auth_ntlmssp_state)->server_info = NULL;
675 /* current_user_info is changed on new vuid */
676 reload_services( True );
678 SSVAL(req->outbuf, smb_vwv3, 0);
680 if (server_info->guest) {
681 SSVAL(req->outbuf,smb_vwv2,1);
685 out:
687 if (wrap) {
688 response = spnego_gen_auth_response(ntlmssp_blob,
689 nt_status, OID);
690 } else {
691 response = *ntlmssp_blob;
694 reply_sesssetup_blob(req, response, nt_status);
695 if (wrap) {
696 data_blob_free(&response);
699 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
700 and the other end, that we are not finished yet. */
702 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
703 /* NB. This is *NOT* an error case. JRA */
704 auth_ntlmssp_end(auth_ntlmssp_state);
705 if (!NT_STATUS_IS_OK(nt_status)) {
706 /* Kill the intermediate vuid */
707 invalidate_vuid(sconn, vuid);
712 /****************************************************************************
713 Is this a krb5 mechanism ?
714 ****************************************************************************/
716 NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in,
717 DATA_BLOB *pblob_out,
718 char **kerb_mechOID)
720 char *OIDs[ASN1_MAX_OIDS];
721 int i;
722 NTSTATUS ret = NT_STATUS_OK;
724 *kerb_mechOID = NULL;
726 /* parse out the OIDs and the first sec blob */
727 if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
728 return NT_STATUS_LOGON_FAILURE;
731 /* only look at the first OID for determining the mechToken --
732 according to RFC2478, we should choose the one we want
733 and renegotiate, but i smell a client bug here..
735 Problem observed when connecting to a member (samba box)
736 of an AD domain as a user in a Samba domain. Samba member
737 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
738 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
739 NTLMSSP mechtoken. --jerry */
741 #ifdef HAVE_KRB5
742 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
743 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
744 *kerb_mechOID = SMB_STRDUP(OIDs[0]);
745 if (*kerb_mechOID == NULL) {
746 ret = NT_STATUS_NO_MEMORY;
749 #endif
751 for (i=0;OIDs[i];i++) {
752 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
753 talloc_free(OIDs[i]);
755 return ret;
758 /****************************************************************************
759 Fall back from krb5 to NTLMSSP.
760 ****************************************************************************/
762 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
763 uint16 vuid)
765 DATA_BLOB response;
767 reply_outbuf(req, 4, 0);
768 SSVAL(req->outbuf,smb_uid,vuid);
770 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
771 "but set to downgrade to NTLMSSP\n"));
773 response = spnego_gen_auth_response(NULL,
774 NT_STATUS_MORE_PROCESSING_REQUIRED,
775 OID_NTLMSSP);
776 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
777 data_blob_free(&response);
780 /****************************************************************************
781 Reply to a session setup spnego negotiate packet.
782 ****************************************************************************/
784 static void reply_spnego_negotiate(struct smb_request *req,
785 uint16 vuid,
786 DATA_BLOB blob1,
787 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
789 DATA_BLOB secblob;
790 DATA_BLOB chal;
791 char *kerb_mech = NULL;
792 NTSTATUS status;
793 struct smbd_server_connection *sconn = smbd_server_conn;
795 status = parse_spnego_mechanisms(blob1, &secblob, &kerb_mech);
796 if (!NT_STATUS_IS_OK(status)) {
797 /* Kill the intermediate vuid */
798 invalidate_vuid(sconn, vuid);
799 reply_nterror(req, nt_status_squash(status));
800 return;
803 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
804 (unsigned long)secblob.length));
806 #ifdef HAVE_KRB5
807 if (kerb_mech && ((lp_security()==SEC_ADS) ||
808 USE_KERBEROS_KEYTAB) ) {
809 bool destroy_vuid = True;
810 reply_spnego_kerberos(req, &secblob, kerb_mech,
811 vuid, &destroy_vuid);
812 data_blob_free(&secblob);
813 if (destroy_vuid) {
814 /* Kill the intermediate vuid */
815 invalidate_vuid(sconn, vuid);
817 SAFE_FREE(kerb_mech);
818 return;
820 #endif
822 if (*auth_ntlmssp_state) {
823 auth_ntlmssp_end(auth_ntlmssp_state);
826 if (kerb_mech) {
827 data_blob_free(&secblob);
828 /* The mechtoken is a krb5 ticket, but
829 * we need to fall back to NTLM. */
830 reply_spnego_downgrade_to_ntlmssp(req, vuid);
831 SAFE_FREE(kerb_mech);
832 return;
835 status = auth_ntlmssp_start(auth_ntlmssp_state);
836 if (!NT_STATUS_IS_OK(status)) {
837 /* Kill the intermediate vuid */
838 invalidate_vuid(sconn, vuid);
839 reply_nterror(req, nt_status_squash(status));
840 return;
843 status = auth_ntlmssp_update(*auth_ntlmssp_state,
844 secblob, &chal);
846 data_blob_free(&secblob);
848 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
849 &chal, status, OID_NTLMSSP, true);
851 data_blob_free(&chal);
853 /* already replied */
854 return;
857 /****************************************************************************
858 Reply to a session setup spnego auth packet.
859 ****************************************************************************/
861 static void reply_spnego_auth(struct smb_request *req,
862 uint16 vuid,
863 DATA_BLOB blob1,
864 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
866 DATA_BLOB auth = data_blob_null;
867 DATA_BLOB auth_reply = data_blob_null;
868 DATA_BLOB secblob = data_blob_null;
869 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
870 struct smbd_server_connection *sconn = smbd_server_conn;
872 if (!spnego_parse_auth(blob1, &auth)) {
873 #if 0
874 file_save("auth.dat", blob1.data, blob1.length);
875 #endif
876 /* Kill the intermediate vuid */
877 invalidate_vuid(sconn, vuid);
879 reply_nterror(req, nt_status_squash(
880 NT_STATUS_LOGON_FAILURE));
881 return;
884 if (auth.data[0] == ASN1_APPLICATION(0)) {
885 /* Might be a second negTokenTarg packet */
886 char *kerb_mech = NULL;
888 status = parse_spnego_mechanisms(auth, &secblob, &kerb_mech);
890 if (!NT_STATUS_IS_OK(status)) {
891 /* Kill the intermediate vuid */
892 invalidate_vuid(sconn, vuid);
893 reply_nterror(req, nt_status_squash(status));
894 return;
897 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
898 (unsigned long)secblob.length));
899 #ifdef HAVE_KRB5
900 if (kerb_mech && ((lp_security()==SEC_ADS) ||
901 USE_KERBEROS_KEYTAB)) {
902 bool destroy_vuid = True;
903 reply_spnego_kerberos(req, &secblob, kerb_mech,
904 vuid, &destroy_vuid);
905 data_blob_free(&secblob);
906 data_blob_free(&auth);
907 if (destroy_vuid) {
908 /* Kill the intermediate vuid */
909 invalidate_vuid(sconn, vuid);
911 SAFE_FREE(kerb_mech);
912 return;
914 #endif
915 /* Can't blunder into NTLMSSP auth if we have
916 * a krb5 ticket. */
918 if (kerb_mech) {
919 /* Kill the intermediate vuid */
920 invalidate_vuid(sconn, vuid);
921 DEBUG(3,("reply_spnego_auth: network "
922 "misconfiguration, client sent us a "
923 "krb5 ticket and kerberos security "
924 "not enabled\n"));
925 reply_nterror(req, nt_status_squash(
926 NT_STATUS_LOGON_FAILURE));
927 SAFE_FREE(kerb_mech);
931 /* If we get here it wasn't a negTokenTarg auth packet. */
932 data_blob_free(&secblob);
934 if (!*auth_ntlmssp_state) {
935 status = auth_ntlmssp_start(auth_ntlmssp_state);
936 if (!NT_STATUS_IS_OK(status)) {
937 /* Kill the intermediate vuid */
938 invalidate_vuid(sconn, vuid);
939 reply_nterror(req, nt_status_squash(status));
940 return;
944 status = auth_ntlmssp_update(*auth_ntlmssp_state,
945 auth, &auth_reply);
947 data_blob_free(&auth);
949 /* Don't send the mechid as we've already sent this (RFC4178). */
951 reply_spnego_ntlmssp(req, vuid,
952 auth_ntlmssp_state,
953 &auth_reply, status, NULL, true);
955 data_blob_free(&auth_reply);
957 /* and tell smbd that we have already replied to this packet */
958 return;
961 /****************************************************************************
962 Delete an entry on the list.
963 ****************************************************************************/
965 static void delete_partial_auth(struct smbd_server_connection *sconn,
966 struct pending_auth_data *pad)
968 if (!pad) {
969 return;
971 DLIST_REMOVE(sconn->smb1.pd_list, pad);
972 data_blob_free(&pad->partial_data);
973 SAFE_FREE(pad);
976 /****************************************************************************
977 Search for a partial SPNEGO auth fragment matching an smbpid.
978 ****************************************************************************/
980 static struct pending_auth_data *get_pending_auth_data(
981 struct smbd_server_connection *sconn,
982 uint16_t smbpid)
984 struct pending_auth_data *pad;
986 * NOTE: using the smbpid here is completely wrong...
987 * see [MS-SMB]
988 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
990 for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
991 if (pad->smbpid == smbpid) {
992 break;
995 return pad;
998 /****************************************************************************
999 Check the size of an SPNEGO blob. If we need more return
1000 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
1001 the blob to be more than 64k.
1002 ****************************************************************************/
1004 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
1005 uint16 smbpid, uint16 vuid,
1006 DATA_BLOB *pblob)
1008 struct pending_auth_data *pad = NULL;
1009 ASN1_DATA *data;
1010 size_t needed_len = 0;
1012 pad = get_pending_auth_data(sconn, smbpid);
1014 /* Ensure we have some data. */
1015 if (pblob->length == 0) {
1016 /* Caller can cope. */
1017 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
1018 delete_partial_auth(sconn, pad);
1019 return NT_STATUS_OK;
1022 /* Were we waiting for more data ? */
1023 if (pad) {
1024 DATA_BLOB tmp_blob;
1025 size_t copy_len = MIN(65536, pblob->length);
1027 /* Integer wrap paranoia.... */
1029 if (pad->partial_data.length + copy_len <
1030 pad->partial_data.length ||
1031 pad->partial_data.length + copy_len < copy_len) {
1033 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1034 "pad->partial_data.length = %u, "
1035 "copy_len = %u\n",
1036 (unsigned int)pad->partial_data.length,
1037 (unsigned int)copy_len ));
1039 delete_partial_auth(sconn, pad);
1040 return NT_STATUS_INVALID_PARAMETER;
1043 DEBUG(10,("check_spnego_blob_complete: "
1044 "pad->partial_data.length = %u, "
1045 "pad->needed_len = %u, "
1046 "copy_len = %u, "
1047 "pblob->length = %u,\n",
1048 (unsigned int)pad->partial_data.length,
1049 (unsigned int)pad->needed_len,
1050 (unsigned int)copy_len,
1051 (unsigned int)pblob->length ));
1053 tmp_blob = data_blob(NULL,
1054 pad->partial_data.length + copy_len);
1056 /* Concatenate the two (up to copy_len) bytes. */
1057 memcpy(tmp_blob.data,
1058 pad->partial_data.data,
1059 pad->partial_data.length);
1060 memcpy(tmp_blob.data + pad->partial_data.length,
1061 pblob->data,
1062 copy_len);
1064 /* Replace the partial data. */
1065 data_blob_free(&pad->partial_data);
1066 pad->partial_data = tmp_blob;
1067 ZERO_STRUCT(tmp_blob);
1069 /* Are we done ? */
1070 if (pblob->length >= pad->needed_len) {
1071 /* Yes, replace pblob. */
1072 data_blob_free(pblob);
1073 *pblob = pad->partial_data;
1074 ZERO_STRUCT(pad->partial_data);
1075 delete_partial_auth(sconn, pad);
1076 return NT_STATUS_OK;
1079 /* Still need more data. */
1080 pad->needed_len -= copy_len;
1081 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1084 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
1085 (pblob->data[0] != ASN1_CONTEXT(1))) {
1086 /* Not something we can determine the
1087 * length of.
1089 return NT_STATUS_OK;
1092 /* This is a new SPNEGO sessionsetup - see if
1093 * the data given in this blob is enough.
1096 data = asn1_init(NULL);
1097 if (data == NULL) {
1098 return NT_STATUS_NO_MEMORY;
1101 asn1_load(data, *pblob);
1102 asn1_start_tag(data, pblob->data[0]);
1103 if (data->has_error || data->nesting == NULL) {
1104 asn1_free(data);
1105 /* Let caller catch. */
1106 return NT_STATUS_OK;
1109 /* Integer wrap paranoia.... */
1111 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
1112 data->nesting->taglen + data->nesting->start < data->nesting->start) {
1114 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1115 "data.nesting->taglen = %u, "
1116 "data.nesting->start = %u\n",
1117 (unsigned int)data->nesting->taglen,
1118 (unsigned int)data->nesting->start ));
1120 asn1_free(data);
1121 return NT_STATUS_INVALID_PARAMETER;
1124 /* Total length of the needed asn1 is the tag length
1125 * plus the current offset. */
1127 needed_len = data->nesting->taglen + data->nesting->start;
1128 asn1_free(data);
1130 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1131 "pblob->length = %u\n",
1132 (unsigned int)needed_len,
1133 (unsigned int)pblob->length ));
1135 if (needed_len <= pblob->length) {
1136 /* Nothing to do - blob is complete. */
1137 return NT_STATUS_OK;
1140 /* Refuse the blob if it's bigger than 64k. */
1141 if (needed_len > 65536) {
1142 DEBUG(2,("check_spnego_blob_complete: needed_len "
1143 "too large (%u)\n",
1144 (unsigned int)needed_len ));
1145 return NT_STATUS_INVALID_PARAMETER;
1148 /* We must store this blob until complete. */
1149 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1150 return NT_STATUS_NO_MEMORY;
1152 pad->needed_len = needed_len - pblob->length;
1153 pad->partial_data = data_blob(pblob->data, pblob->length);
1154 if (pad->partial_data.data == NULL) {
1155 SAFE_FREE(pad);
1156 return NT_STATUS_NO_MEMORY;
1158 pad->smbpid = smbpid;
1159 pad->vuid = vuid;
1160 DLIST_ADD(sconn->smb1.pd_list, pad);
1162 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1165 /****************************************************************************
1166 Reply to a session setup command.
1167 conn POINTER CAN BE NULL HERE !
1168 ****************************************************************************/
1170 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1172 const uint8 *p;
1173 DATA_BLOB blob1;
1174 size_t bufrem;
1175 char *tmp;
1176 const char *native_os;
1177 const char *native_lanman;
1178 const char *primary_domain;
1179 const char *p2;
1180 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1181 enum remote_arch_types ra_type = get_remote_arch();
1182 int vuid = req->vuid;
1183 user_struct *vuser = NULL;
1184 NTSTATUS status = NT_STATUS_OK;
1185 uint16 smbpid = req->smbpid;
1186 struct smbd_server_connection *sconn = smbd_server_conn;
1188 DEBUG(3,("Doing spnego session setup\n"));
1190 if (global_client_caps == 0) {
1191 global_client_caps = IVAL(req->vwv+10, 0);
1193 if (!(global_client_caps & CAP_STATUS32)) {
1194 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1199 p = req->buf;
1201 if (data_blob_len == 0) {
1202 /* an invalid request */
1203 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1204 return;
1207 bufrem = smbreq_bufrem(req, p);
1208 /* pull the spnego blob */
1209 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1211 #if 0
1212 file_save("negotiate.dat", blob1.data, blob1.length);
1213 #endif
1215 p2 = (char *)req->buf + blob1.length;
1217 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1218 STR_TERMINATE);
1219 native_os = tmp ? tmp : "";
1221 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1222 STR_TERMINATE);
1223 native_lanman = tmp ? tmp : "";
1225 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1226 STR_TERMINATE);
1227 primary_domain = tmp ? tmp : "";
1229 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1230 native_os, native_lanman, primary_domain));
1232 if ( ra_type == RA_WIN2K ) {
1233 /* Vista sets neither the OS or lanman strings */
1235 if ( !strlen(native_os) && !strlen(native_lanman) )
1236 set_remote_arch(RA_VISTA);
1238 /* Windows 2003 doesn't set the native lanman string,
1239 but does set primary domain which is a bug I think */
1241 if ( !strlen(native_lanman) ) {
1242 ra_lanman_string( primary_domain );
1243 } else {
1244 ra_lanman_string( native_lanman );
1248 /* Did we get a valid vuid ? */
1249 if (!is_partial_auth_vuid(sconn, vuid)) {
1250 /* No, then try and see if this is an intermediate sessionsetup
1251 * for a large SPNEGO packet. */
1252 struct pending_auth_data *pad;
1253 pad = get_pending_auth_data(sconn, smbpid);
1254 if (pad) {
1255 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1256 "pending vuid %u\n",
1257 (unsigned int)pad->vuid ));
1258 vuid = pad->vuid;
1262 /* Do we have a valid vuid now ? */
1263 if (!is_partial_auth_vuid(sconn, vuid)) {
1264 /* No, start a new authentication setup. */
1265 vuid = register_initial_vuid(sconn);
1266 if (vuid == UID_FIELD_INVALID) {
1267 data_blob_free(&blob1);
1268 reply_nterror(req, nt_status_squash(
1269 NT_STATUS_INVALID_PARAMETER));
1270 return;
1274 vuser = get_partial_auth_user_struct(sconn, vuid);
1275 /* This MUST be valid. */
1276 if (!vuser) {
1277 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1280 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1281 * sessionsetup requests as the Windows limit on the security blob
1282 * field is 4k. Bug #4400. JRA.
1285 status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1286 if (!NT_STATUS_IS_OK(status)) {
1287 if (!NT_STATUS_EQUAL(status,
1288 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1289 /* Real error - kill the intermediate vuid */
1290 invalidate_vuid(sconn, vuid);
1292 data_blob_free(&blob1);
1293 reply_nterror(req, nt_status_squash(status));
1294 return;
1297 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1299 /* its a negTokenTarg packet */
1301 reply_spnego_negotiate(req, vuid, blob1,
1302 &vuser->auth_ntlmssp_state);
1303 data_blob_free(&blob1);
1304 return;
1307 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1309 /* its a auth packet */
1311 reply_spnego_auth(req, vuid, blob1,
1312 &vuser->auth_ntlmssp_state);
1313 data_blob_free(&blob1);
1314 return;
1317 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1318 DATA_BLOB chal;
1320 if (!vuser->auth_ntlmssp_state) {
1321 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1322 if (!NT_STATUS_IS_OK(status)) {
1323 /* Kill the intermediate vuid */
1324 invalidate_vuid(sconn, vuid);
1325 data_blob_free(&blob1);
1326 reply_nterror(req, nt_status_squash(status));
1327 return;
1331 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1332 blob1, &chal);
1334 data_blob_free(&blob1);
1336 reply_spnego_ntlmssp(req, vuid,
1337 &vuser->auth_ntlmssp_state,
1338 &chal, status, OID_NTLMSSP, false);
1339 data_blob_free(&chal);
1340 return;
1343 /* what sort of packet is this? */
1344 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1346 data_blob_free(&blob1);
1348 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1351 /****************************************************************************
1352 On new VC == 0, shutdown *all* old connections and users.
1353 It seems that only NT4.x does this. At W2K and above (XP etc.).
1354 a new session setup with VC==0 is ignored.
1355 ****************************************************************************/
1357 static int shutdown_other_smbds(const struct connections_key *key,
1358 const struct connections_data *crec,
1359 void *private_data)
1361 const char *ip = (const char *)private_data;
1363 if (!process_exists(crec->pid)) {
1364 return 0;
1367 if (procid_is_me(&crec->pid)) {
1368 return 0;
1371 if (strcmp(ip, crec->addr) != 0) {
1372 return 0;
1375 DEBUG(0,("shutdown_other_smbds: shutting down pid %u "
1376 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid), ip));
1378 messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1379 &data_blob_null);
1380 return 0;
1383 static void setup_new_vc_session(void)
1385 char addr[INET6_ADDRSTRLEN];
1387 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1388 "compatible we would close all old resources.\n"));
1389 #if 0
1390 conn_close_all();
1391 invalidate_all_vuids();
1392 #endif
1393 if (lp_reset_on_zero_vc()) {
1394 connections_forall_read(shutdown_other_smbds,
1395 CONST_DISCARD(void *,
1396 client_addr(get_client_fd(),addr,sizeof(addr))));
1400 /****************************************************************************
1401 Reply to a session setup command.
1402 ****************************************************************************/
1404 void reply_sesssetup_and_X(struct smb_request *req)
1406 int sess_vuid;
1407 int smb_bufsize;
1408 DATA_BLOB lm_resp;
1409 DATA_BLOB nt_resp;
1410 DATA_BLOB plaintext_password;
1411 char *tmp;
1412 const char *user;
1413 fstring sub_user; /* Sainitised username for substituion */
1414 const char *domain;
1415 const char *native_os;
1416 const char *native_lanman;
1417 const char *primary_domain;
1418 struct auth_usersupplied_info *user_info = NULL;
1419 struct auth_serversupplied_info *server_info = NULL;
1420 uint16 smb_flag2 = req->flags2;
1422 NTSTATUS nt_status;
1423 struct smbd_server_connection *sconn = smbd_server_conn;
1425 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1427 START_PROFILE(SMBsesssetupX);
1429 ZERO_STRUCT(lm_resp);
1430 ZERO_STRUCT(nt_resp);
1431 ZERO_STRUCT(plaintext_password);
1433 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1435 /* a SPNEGO session setup has 12 command words, whereas a normal
1436 NT1 session setup has 13. See the cifs spec. */
1437 if (req->wct == 12 &&
1438 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1440 if (!sconn->smb1.negprot.spnego) {
1441 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1442 "at SPNEGO session setup when it was not "
1443 "negotiated.\n"));
1444 reply_nterror(req, nt_status_squash(
1445 NT_STATUS_LOGON_FAILURE));
1446 END_PROFILE(SMBsesssetupX);
1447 return;
1450 if (SVAL(req->vwv+4, 0) == 0) {
1451 setup_new_vc_session();
1454 reply_sesssetup_and_X_spnego(req);
1455 END_PROFILE(SMBsesssetupX);
1456 return;
1459 smb_bufsize = SVAL(req->vwv+2, 0);
1461 if (get_Protocol() < PROTOCOL_NT1) {
1462 uint16 passlen1 = SVAL(req->vwv+7, 0);
1464 /* Never do NT status codes with protocols before NT1 as we
1465 * don't get client caps. */
1466 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1468 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1469 reply_nterror(req, nt_status_squash(
1470 NT_STATUS_INVALID_PARAMETER));
1471 END_PROFILE(SMBsesssetupX);
1472 return;
1475 if (doencrypt) {
1476 lm_resp = data_blob(req->buf, passlen1);
1477 } else {
1478 plaintext_password = data_blob(req->buf, passlen1+1);
1479 /* Ensure null termination */
1480 plaintext_password.data[passlen1] = 0;
1483 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1484 req->buf + passlen1, STR_TERMINATE);
1485 user = tmp ? tmp : "";
1487 domain = "";
1489 } else {
1490 uint16 passlen1 = SVAL(req->vwv+7, 0);
1491 uint16 passlen2 = SVAL(req->vwv+8, 0);
1492 enum remote_arch_types ra_type = get_remote_arch();
1493 const uint8_t *p = req->buf;
1494 const uint8_t *save_p = req->buf;
1495 uint16 byte_count;
1498 if(global_client_caps == 0) {
1499 global_client_caps = IVAL(req->vwv+11, 0);
1501 if (!(global_client_caps & CAP_STATUS32)) {
1502 remove_from_common_flags2(
1503 FLAGS2_32_BIT_ERROR_CODES);
1506 /* client_caps is used as final determination if
1507 * client is NT or Win95. This is needed to return
1508 * the correct error codes in some circumstances.
1511 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1512 ra_type == RA_WIN95) {
1513 if(!(global_client_caps & (CAP_NT_SMBS|
1514 CAP_STATUS32))) {
1515 set_remote_arch( RA_WIN95);
1520 if (!doencrypt) {
1521 /* both Win95 and WinNT stuff up the password
1522 * lengths for non-encrypting systems. Uggh.
1524 if passlen1==24 its a win95 system, and its setting
1525 the password length incorrectly. Luckily it still
1526 works with the default code because Win95 will null
1527 terminate the password anyway
1529 if passlen1>0 and passlen2>0 then maybe its a NT box
1530 and its setting passlen2 to some random value which
1531 really stuffs things up. we need to fix that one. */
1533 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1534 passlen2 != 1) {
1535 passlen2 = 0;
1539 /* check for nasty tricks */
1540 if (passlen1 > MAX_PASS_LEN
1541 || passlen1 > smbreq_bufrem(req, p)) {
1542 reply_nterror(req, nt_status_squash(
1543 NT_STATUS_INVALID_PARAMETER));
1544 END_PROFILE(SMBsesssetupX);
1545 return;
1548 if (passlen2 > MAX_PASS_LEN
1549 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1550 reply_nterror(req, nt_status_squash(
1551 NT_STATUS_INVALID_PARAMETER));
1552 END_PROFILE(SMBsesssetupX);
1553 return;
1556 /* Save the lanman2 password and the NT md4 password. */
1558 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1559 doencrypt = False;
1562 if (doencrypt) {
1563 lm_resp = data_blob(p, passlen1);
1564 nt_resp = data_blob(p+passlen1, passlen2);
1565 } else if (lp_security() != SEC_SHARE) {
1567 * In share level we should ignore any passwords, so
1568 * only read them if we're not.
1570 char *pass = NULL;
1571 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1573 if (unic && (passlen2 == 0) && passlen1) {
1574 /* Only a ascii plaintext password was sent. */
1575 (void)srvstr_pull_talloc(talloc_tos(),
1576 req->inbuf,
1577 req->flags2,
1578 &pass,
1579 req->buf,
1580 passlen1,
1581 STR_TERMINATE|STR_ASCII);
1582 } else {
1583 (void)srvstr_pull_talloc(talloc_tos(),
1584 req->inbuf,
1585 req->flags2,
1586 &pass,
1587 req->buf,
1588 unic ? passlen2 : passlen1,
1589 STR_TERMINATE);
1591 if (!pass) {
1592 reply_nterror(req, nt_status_squash(
1593 NT_STATUS_INVALID_PARAMETER));
1594 END_PROFILE(SMBsesssetupX);
1595 return;
1597 plaintext_password = data_blob(pass, strlen(pass)+1);
1600 p += passlen1 + passlen2;
1602 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1603 STR_TERMINATE);
1604 user = tmp ? tmp : "";
1606 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1607 STR_TERMINATE);
1608 domain = tmp ? tmp : "";
1610 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1611 STR_TERMINATE);
1612 native_os = tmp ? tmp : "";
1614 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1615 STR_TERMINATE);
1616 native_lanman = tmp ? tmp : "";
1618 /* not documented or decoded by Ethereal but there is one more
1619 * string in the extra bytes which is the same as the
1620 * PrimaryDomain when using extended security. Windows NT 4
1621 * and 2003 use this string to store the native lanman string.
1622 * Windows 9x does not include a string here at all so we have
1623 * to check if we have any extra bytes left */
1625 byte_count = SVAL(req->vwv+13, 0);
1626 if ( PTR_DIFF(p, save_p) < byte_count) {
1627 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1628 STR_TERMINATE);
1629 primary_domain = tmp ? tmp : "";
1630 } else {
1631 primary_domain = talloc_strdup(talloc_tos(), "null");
1634 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1635 "PrimaryDomain=[%s]\n",
1636 domain, native_os, native_lanman, primary_domain));
1638 if ( ra_type == RA_WIN2K ) {
1639 if ( strlen(native_lanman) == 0 )
1640 ra_lanman_string( primary_domain );
1641 else
1642 ra_lanman_string( native_lanman );
1647 if (SVAL(req->vwv+4, 0) == 0) {
1648 setup_new_vc_session();
1651 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1652 domain, user, get_remote_machine_name()));
1654 if (*user) {
1655 if (sconn->smb1.negprot.spnego) {
1657 /* This has to be here, because this is a perfectly
1658 * valid behaviour for guest logons :-( */
1660 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1661 "at 'normal' session setup after "
1662 "negotiating spnego.\n"));
1663 reply_nterror(req, nt_status_squash(
1664 NT_STATUS_LOGON_FAILURE));
1665 END_PROFILE(SMBsesssetupX);
1666 return;
1668 fstrcpy(sub_user, user);
1669 } else {
1670 fstrcpy(sub_user, lp_guestaccount());
1673 sub_set_smb_name(sub_user);
1675 reload_services(True);
1677 if (lp_security() == SEC_SHARE) {
1678 /* In share level we should ignore any passwords */
1680 data_blob_free(&lm_resp);
1681 data_blob_free(&nt_resp);
1682 data_blob_clear_free(&plaintext_password);
1684 map_username(sconn, sub_user);
1685 add_session_user(sconn, sub_user);
1686 add_session_workgroup(sconn, domain);
1687 /* Then force it to null for the benfit of the code below */
1688 user = "";
1691 if (!*user) {
1693 nt_status = check_guest_password(&server_info);
1695 } else if (doencrypt) {
1696 struct auth_context *negprot_auth_context = NULL;
1697 negprot_auth_context = sconn->smb1.negprot.auth_context;
1698 if (!negprot_auth_context) {
1699 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1700 "session setup without negprot denied!\n"));
1701 reply_nterror(req, nt_status_squash(
1702 NT_STATUS_LOGON_FAILURE));
1703 END_PROFILE(SMBsesssetupX);
1704 return;
1706 nt_status = make_user_info_for_reply_enc(&user_info, user,
1707 domain,
1708 lm_resp, nt_resp);
1709 if (NT_STATUS_IS_OK(nt_status)) {
1710 nt_status = negprot_auth_context->check_ntlm_password(
1711 negprot_auth_context,
1712 user_info,
1713 &server_info);
1715 } else {
1716 struct auth_context *plaintext_auth_context = NULL;
1718 nt_status = make_auth_context_subsystem(
1719 &plaintext_auth_context);
1721 if (NT_STATUS_IS_OK(nt_status)) {
1722 uint8_t chal[8];
1724 plaintext_auth_context->get_ntlm_challenge(
1725 plaintext_auth_context, chal);
1727 if (!make_user_info_for_reply(&user_info,
1728 user, domain, chal,
1729 plaintext_password)) {
1730 nt_status = NT_STATUS_NO_MEMORY;
1733 if (NT_STATUS_IS_OK(nt_status)) {
1734 nt_status = plaintext_auth_context->check_ntlm_password(
1735 plaintext_auth_context,
1736 user_info,
1737 &server_info);
1739 (plaintext_auth_context->free)(
1740 &plaintext_auth_context);
1745 free_user_info(&user_info);
1747 if (!NT_STATUS_IS_OK(nt_status)) {
1748 nt_status = do_map_to_guest(nt_status, &server_info,
1749 user, domain);
1752 if (!NT_STATUS_IS_OK(nt_status)) {
1753 data_blob_free(&nt_resp);
1754 data_blob_free(&lm_resp);
1755 data_blob_clear_free(&plaintext_password);
1756 reply_nterror(req, nt_status_squash(nt_status));
1757 END_PROFILE(SMBsesssetupX);
1758 return;
1761 /* Ensure we can't possible take a code path leading to a
1762 * null defref. */
1763 if (!server_info) {
1764 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1765 END_PROFILE(SMBsesssetupX);
1766 return;
1769 if (!server_info->ptok) {
1770 nt_status = create_local_token(server_info);
1772 if (!NT_STATUS_IS_OK(nt_status)) {
1773 DEBUG(10, ("create_local_token failed: %s\n",
1774 nt_errstr(nt_status)));
1775 data_blob_free(&nt_resp);
1776 data_blob_free(&lm_resp);
1777 data_blob_clear_free(&plaintext_password);
1778 reply_nterror(req, nt_status_squash(nt_status));
1779 END_PROFILE(SMBsesssetupX);
1780 return;
1784 data_blob_clear_free(&plaintext_password);
1786 /* it's ok - setup a reply */
1787 reply_outbuf(req, 3, 0);
1788 if (get_Protocol() >= PROTOCOL_NT1) {
1789 push_signature(&req->outbuf);
1790 /* perhaps grab OS version here?? */
1793 if (server_info->guest) {
1794 SSVAL(req->outbuf,smb_vwv2,1);
1797 /* register the name and uid as being validated, so further connections
1798 to a uid can get through without a password, on the same VC */
1800 if (lp_security() == SEC_SHARE) {
1801 sess_vuid = UID_FIELD_INVALID;
1802 TALLOC_FREE(server_info);
1803 } else {
1804 /* Ignore the initial vuid. */
1805 sess_vuid = register_initial_vuid(sconn);
1806 if (sess_vuid == UID_FIELD_INVALID) {
1807 data_blob_free(&nt_resp);
1808 data_blob_free(&lm_resp);
1809 reply_nterror(req, nt_status_squash(
1810 NT_STATUS_LOGON_FAILURE));
1811 END_PROFILE(SMBsesssetupX);
1812 return;
1814 /* register_existing_vuid keeps the server info */
1815 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1816 server_info,
1817 nt_resp.data ? nt_resp : lm_resp,
1818 sub_user);
1819 if (sess_vuid == UID_FIELD_INVALID) {
1820 data_blob_free(&nt_resp);
1821 data_blob_free(&lm_resp);
1822 reply_nterror(req, nt_status_squash(
1823 NT_STATUS_LOGON_FAILURE));
1824 END_PROFILE(SMBsesssetupX);
1825 return;
1828 /* current_user_info is changed on new vuid */
1829 reload_services( True );
1832 data_blob_free(&nt_resp);
1833 data_blob_free(&lm_resp);
1835 SSVAL(req->outbuf,smb_uid,sess_vuid);
1836 SSVAL(req->inbuf,smb_uid,sess_vuid);
1837 req->vuid = sess_vuid;
1839 if (!sconn->smb1.sessions.done_sesssetup) {
1840 sconn->smb1.sessions.max_send =
1841 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1843 sconn->smb1.sessions.done_sesssetup = true;
1845 END_PROFILE(SMBsesssetupX);
1846 chain_reply(req);
1847 return;