Remove "session_key" from "struct user_struct"
[Samba/bb.git] / source / smbd / sesssetup.c
blob99bf0dcbb9cd21cc1ce26178110667195e24a389
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"
27 extern struct auth_context *negprot_global_auth_context;
28 extern bool global_encrypted_passwords_negotiated;
29 extern bool global_spnego_negotiated;
30 extern enum protocol_types Protocol;
31 extern int max_send;
33 uint32 global_client_caps = 0;
36 on a logon error possibly map the error to success if "map to guest"
37 is set approriately
39 static NTSTATUS do_map_to_guest(NTSTATUS status,
40 auth_serversupplied_info **server_info,
41 const char *user, const char *domain)
43 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
44 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
45 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
46 DEBUG(3,("No such user %s [%s] - using guest account\n",
47 user, domain));
48 status = make_server_info_guest(server_info);
52 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
53 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
54 DEBUG(3,("Registered username %s for guest access\n",
55 user));
56 status = make_server_info_guest(server_info);
60 return status;
63 /****************************************************************************
64 Add the standard 'Samba' signature to the end of the session setup.
65 ****************************************************************************/
67 static int push_signature(uint8 **outbuf)
69 char *lanman;
70 int result, tmp;
72 result = 0;
74 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
76 if (tmp == -1) return -1;
77 result += tmp;
79 if (asprintf(&lanman, "Samba %s", SAMBA_VERSION_STRING) != -1) {
80 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
81 SAFE_FREE(lanman);
83 else {
84 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
87 if (tmp == -1) return -1;
88 result += tmp;
90 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
92 if (tmp == -1) return -1;
93 result += tmp;
95 return result;
98 /****************************************************************************
99 Start the signing engine if needed. Don't fail signing here.
100 ****************************************************************************/
102 static void sessionsetup_start_signing_engine(
103 const auth_serversupplied_info *server_info,
104 const uint8 *inbuf)
106 if (!server_info->guest && !srv_signing_started()) {
107 /* We need to start the signing engine
108 * here but a W2K client sends the old
109 * "BSRSPYL " signature instead of the
110 * correct one. Subsequent packets will
111 * be correct.
113 srv_check_sign_mac((char *)inbuf, False);
117 /****************************************************************************
118 Send a security blob via a session setup reply.
119 ****************************************************************************/
121 static void reply_sesssetup_blob(struct smb_request *req,
122 DATA_BLOB blob,
123 NTSTATUS nt_status)
125 if (!NT_STATUS_IS_OK(nt_status) &&
126 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
127 reply_nterror(req, nt_status_squash(nt_status));
128 } else {
129 nt_status = nt_status_squash(nt_status);
130 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
131 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
132 SSVAL(req->outbuf, smb_vwv3, blob.length);
134 if ((message_push_blob(&req->outbuf, blob) == -1)
135 || (push_signature(&req->outbuf) == -1)) {
136 reply_nterror(req, NT_STATUS_NO_MEMORY);
140 show_msg((char *)req->outbuf);
141 srv_send_smb(smbd_server_fd(),(char *)req->outbuf,req->encrypted);
142 TALLOC_FREE(req->outbuf);
145 /****************************************************************************
146 Do a 'guest' logon, getting back the
147 ****************************************************************************/
149 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
151 struct auth_context *auth_context;
152 auth_usersupplied_info *user_info = NULL;
154 NTSTATUS nt_status;
155 unsigned char chal[8];
157 ZERO_STRUCT(chal);
159 DEBUG(3,("Got anonymous request\n"));
161 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context,
162 chal))) {
163 return nt_status;
166 if (!make_user_info_guest(&user_info)) {
167 (auth_context->free)(&auth_context);
168 return NT_STATUS_NO_MEMORY;
171 nt_status = auth_context->check_ntlm_password(auth_context,
172 user_info,
173 server_info);
174 (auth_context->free)(&auth_context);
175 free_user_info(&user_info);
176 return nt_status;
180 #ifdef HAVE_KRB5
182 #if 0
183 /* Experiment that failed. See "only happens with a KDC" comment below. */
184 /****************************************************************************
185 Cerate a clock skew error blob for a Windows client.
186 ****************************************************************************/
188 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
190 krb5_context context = NULL;
191 krb5_error_code kerr = 0;
192 krb5_data reply;
193 krb5_principal host_princ = NULL;
194 char *host_princ_s = NULL;
195 bool ret = False;
197 *pblob_out = data_blob_null;
199 initialize_krb5_error_table();
200 kerr = krb5_init_context(&context);
201 if (kerr) {
202 return False;
204 /* Create server principal. */
205 asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
206 if (!host_princ_s) {
207 goto out;
209 strlower_m(host_princ_s);
211 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
212 if (kerr) {
213 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
214 "for name %s: Error %s\n",
215 host_princ_s, error_message(kerr) ));
216 goto out;
219 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
220 host_princ, &reply);
221 if (kerr) {
222 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
223 "failed: Error %s\n",
224 error_message(kerr) ));
225 goto out;
228 *pblob_out = data_blob(reply.data, reply.length);
229 kerberos_free_data_contents(context,&reply);
230 ret = True;
232 out:
234 if (host_princ_s) {
235 SAFE_FREE(host_princ_s);
237 if (host_princ) {
238 krb5_free_principal(context, host_princ);
240 krb5_free_context(context);
241 return ret;
243 #endif
245 /****************************************************************************
246 Reply to a session setup spnego negotiate packet for kerberos.
247 ****************************************************************************/
249 static void reply_spnego_kerberos(struct smb_request *req,
250 DATA_BLOB *secblob,
251 const char *mechOID,
252 uint16 vuid,
253 bool *p_invalidate_vuid)
255 TALLOC_CTX *mem_ctx;
256 DATA_BLOB ticket;
257 char *client, *p, *domain;
258 fstring netbios_domain_name;
259 struct passwd *pw;
260 fstring user;
261 int sess_vuid = req->vuid;
262 NTSTATUS ret = NT_STATUS_OK;
263 struct PAC_DATA *pac_data = NULL;
264 DATA_BLOB ap_rep, ap_rep_wrapped, response;
265 auth_serversupplied_info *server_info = NULL;
266 DATA_BLOB session_key = data_blob_null;
267 uint8 tok_id[2];
268 DATA_BLOB nullblob = data_blob_null;
269 fstring real_username;
270 bool map_domainuser_to_guest = False;
271 bool username_was_mapped;
272 struct PAC_LOGON_INFO *logon_info = NULL;
274 ZERO_STRUCT(ticket);
275 ZERO_STRUCT(ap_rep);
276 ZERO_STRUCT(ap_rep_wrapped);
277 ZERO_STRUCT(response);
279 /* Normally we will always invalidate the intermediate vuid. */
280 *p_invalidate_vuid = True;
282 mem_ctx = talloc_init("reply_spnego_kerberos");
283 if (mem_ctx == NULL) {
284 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
285 return;
288 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
289 talloc_destroy(mem_ctx);
290 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
291 return;
294 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
295 &client, &pac_data, &ap_rep,
296 &session_key, True);
298 data_blob_free(&ticket);
300 if (!NT_STATUS_IS_OK(ret)) {
301 #if 0
302 /* Experiment that failed.
303 * See "only happens with a KDC" comment below. */
305 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
308 * Windows in this case returns
309 * NT_STATUS_MORE_PROCESSING_REQUIRED
310 * with a negTokenTarg blob containing an krb5_error
311 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
312 * The client then fixes its clock and continues rather
313 * than giving an error. JRA.
314 * -- Looks like this only happens with a KDC. JRA.
317 bool ok = make_krb5_skew_error(&ap_rep);
318 if (!ok) {
319 talloc_destroy(mem_ctx);
320 return ERROR_NT(nt_status_squash(
321 NT_STATUS_LOGON_FAILURE));
323 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
324 TOK_ID_KRB_ERROR);
325 response = spnego_gen_auth_response(&ap_rep_wrapped,
326 ret, OID_KERBEROS5_OLD);
327 reply_sesssetup_blob(conn, inbuf, outbuf, response,
328 NT_STATUS_MORE_PROCESSING_REQUIRED);
331 * In this one case we don't invalidate the
332 * intermediate vuid as we're expecting the client
333 * to re-use it for the next sessionsetupX packet. JRA.
336 *p_invalidate_vuid = False;
338 data_blob_free(&ap_rep);
339 data_blob_free(&ap_rep_wrapped);
340 data_blob_free(&response);
341 talloc_destroy(mem_ctx);
342 return -1; /* already replied */
344 #else
345 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
346 ret = NT_STATUS_LOGON_FAILURE;
348 #endif
349 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
350 nt_errstr(ret)));
351 talloc_destroy(mem_ctx);
352 reply_nterror(req, nt_status_squash(ret));
353 return;
356 DEBUG(3,("Ticket name is [%s]\n", client));
358 p = strchr_m(client, '@');
359 if (!p) {
360 DEBUG(3,("Doesn't look like a valid principal\n"));
361 data_blob_free(&ap_rep);
362 data_blob_free(&session_key);
363 SAFE_FREE(client);
364 talloc_destroy(mem_ctx);
365 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
366 return;
369 *p = 0;
371 /* save the PAC data if we have it */
373 if (pac_data) {
374 logon_info = get_logon_info_from_pac(pac_data);
375 if (logon_info) {
376 netsamlogon_cache_store( client, &logon_info->info3 );
380 if (!strequal(p+1, lp_realm())) {
381 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
382 if (!lp_allow_trusted_domains()) {
383 data_blob_free(&ap_rep);
384 data_blob_free(&session_key);
385 SAFE_FREE(client);
386 talloc_destroy(mem_ctx);
387 reply_nterror(req, nt_status_squash(
388 NT_STATUS_LOGON_FAILURE));
389 return;
393 /* this gives a fully qualified user name (ie. with full realm).
394 that leads to very long usernames, but what else can we do? */
396 domain = p+1;
398 if (logon_info && logon_info->info3.base.domain.string) {
399 fstrcpy(netbios_domain_name,
400 logon_info->info3.base.domain.string);
401 domain = netbios_domain_name;
402 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
404 } else {
406 /* If we have winbind running, we can (and must) shorten the
407 username by using the short netbios name. Otherwise we will
408 have inconsistent user names. With Kerberos, we get the
409 fully qualified realm, with ntlmssp we get the short
410 name. And even w2k3 does use ntlmssp if you for example
411 connect to an ip address. */
413 wbcErr wbc_status;
414 struct wbcDomainInfo *info = NULL;
416 DEBUG(10, ("Mapping [%s] to short name\n", domain));
418 wbc_status = wbcDomainInfo(domain, &info);
420 if (WBC_ERROR_IS_OK(wbc_status)) {
422 fstrcpy(netbios_domain_name,
423 info->short_name);
425 wbcFreeMemory(info);
426 domain = netbios_domain_name;
427 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
428 } else {
429 DEBUG(3, ("Could not find short name: %s\n",
430 wbcErrorString(wbc_status)));
434 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
436 /* lookup the passwd struct, create a new user if necessary */
438 username_was_mapped = map_username( user );
440 pw = smb_getpwnam( mem_ctx, user, real_username, True );
442 if (pw) {
443 /* if a real user check pam account restrictions */
444 /* only really perfomed if "obey pam restriction" is true */
445 /* do this before an eventual mappign to guest occurs */
446 ret = smb_pam_accountcheck(pw->pw_name);
447 if ( !NT_STATUS_IS_OK(ret)) {
448 DEBUG(1,("PAM account restriction "
449 "prevents user login\n"));
450 data_blob_free(&ap_rep);
451 data_blob_free(&session_key);
452 TALLOC_FREE(mem_ctx);
453 reply_nterror(req, nt_status_squash(ret));
454 return;
458 if (!pw) {
460 /* this was originally the behavior of Samba 2.2, if a user
461 did not have a local uid but has been authenticated, then
462 map them to a guest account */
464 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
465 map_domainuser_to_guest = True;
466 fstrcpy(user,lp_guestaccount());
467 pw = smb_getpwnam( mem_ctx, user, real_username, True );
470 /* extra sanity check that the guest account is valid */
472 if ( !pw ) {
473 DEBUG(1,("Username %s is invalid on this system\n",
474 user));
475 SAFE_FREE(client);
476 data_blob_free(&ap_rep);
477 data_blob_free(&session_key);
478 TALLOC_FREE(mem_ctx);
479 reply_nterror(req, nt_status_squash(
480 NT_STATUS_LOGON_FAILURE));
481 return;
485 /* setup the string used by %U */
487 sub_set_smb_name( real_username );
488 reload_services(True);
490 if ( map_domainuser_to_guest ) {
491 make_server_info_guest(&server_info);
492 } else if (logon_info) {
493 /* pass the unmapped username here since map_username()
494 will be called again from inside make_server_info_info3() */
496 ret = make_server_info_info3(mem_ctx, client, domain,
497 &server_info, &logon_info->info3);
498 if ( !NT_STATUS_IS_OK(ret) ) {
499 DEBUG(1,("make_server_info_info3 failed: %s!\n",
500 nt_errstr(ret)));
501 SAFE_FREE(client);
502 data_blob_free(&ap_rep);
503 data_blob_free(&session_key);
504 TALLOC_FREE(mem_ctx);
505 reply_nterror(req, nt_status_squash(ret));
506 return;
509 } else {
510 ret = make_server_info_pw(&server_info, real_username, pw);
512 if ( !NT_STATUS_IS_OK(ret) ) {
513 DEBUG(1,("make_server_info_pw failed: %s!\n",
514 nt_errstr(ret)));
515 SAFE_FREE(client);
516 data_blob_free(&ap_rep);
517 data_blob_free(&session_key);
518 TALLOC_FREE(mem_ctx);
519 reply_nterror(req, nt_status_squash(ret));
520 return;
523 /* make_server_info_pw does not set the domain. Without this
524 * we end up with the local netbios name in substitutions for
525 * %D. */
527 if (server_info->sam_account != NULL) {
528 pdb_set_domain(server_info->sam_account,
529 domain, PDB_SET);
533 if (username_was_mapped) {
534 server_info->was_mapped = username_was_mapped;
537 /* we need to build the token for the user. make_server_info_guest()
538 already does this */
540 if ( !server_info->ptok ) {
541 ret = create_local_token( server_info );
542 if ( !NT_STATUS_IS_OK(ret) ) {
543 DEBUG(10,("failed to create local token: %s\n",
544 nt_errstr(ret)));
545 SAFE_FREE(client);
546 data_blob_free(&ap_rep);
547 data_blob_free(&session_key);
548 TALLOC_FREE( mem_ctx );
549 TALLOC_FREE( server_info );
550 reply_nterror(req, nt_status_squash(ret));
551 return;
555 /* register_existing_vuid keeps the server info */
556 /* register_existing_vuid takes ownership of session_key on success,
557 * no need to free after this on success. A better interface would copy
558 * it.... */
560 if (!is_partial_auth_vuid(sess_vuid)) {
561 sess_vuid = register_initial_vuid();
564 data_blob_free(&server_info->user_session_key);
565 server_info->user_session_key = session_key;
566 session_key = data_blob_null;
568 sess_vuid = register_existing_vuid(sess_vuid,
569 server_info,
570 nullblob,
571 client);
573 SAFE_FREE(client);
575 reply_outbuf(req, 4, 0);
576 SSVAL(req->outbuf,smb_uid,sess_vuid);
578 if (sess_vuid == UID_FIELD_INVALID ) {
579 ret = NT_STATUS_LOGON_FAILURE;
580 } else {
581 /* current_user_info is changed on new vuid */
582 reload_services( True );
584 SSVAL(req->outbuf, smb_vwv3, 0);
586 if (server_info->guest) {
587 SSVAL(req->outbuf,smb_vwv2,1);
590 SSVAL(req->outbuf, smb_uid, sess_vuid);
592 sessionsetup_start_signing_engine(server_info, req->inbuf);
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;
634 if (NT_STATUS_IS_OK(nt_status)) {
635 server_info = (*auth_ntlmssp_state)->server_info;
636 } else {
637 nt_status = do_map_to_guest(nt_status,
638 &server_info,
639 (*auth_ntlmssp_state)->ntlmssp_state->user,
640 (*auth_ntlmssp_state)->ntlmssp_state->domain);
643 reply_outbuf(req, 4, 0);
645 SSVAL(req->outbuf, smb_uid, vuid);
647 if (NT_STATUS_IS_OK(nt_status)) {
648 DATA_BLOB nullblob = data_blob_null;
649 DATA_BLOB session_key =
650 data_blob(
651 (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
652 (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
654 if (!is_partial_auth_vuid(vuid)) {
655 nt_status = NT_STATUS_LOGON_FAILURE;
656 goto out;
659 data_blob_free(&server_info->user_session_key);
660 server_info->user_session_key =
661 data_blob(
662 (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
663 (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
665 /* register_existing_vuid keeps the server info */
666 if (register_existing_vuid(vuid,
667 server_info, nullblob,
668 (*auth_ntlmssp_state)->ntlmssp_state->user) !=
669 vuid) {
670 data_blob_free(&session_key);
671 nt_status = NT_STATUS_LOGON_FAILURE;
672 goto out;
675 (*auth_ntlmssp_state)->server_info = NULL;
677 /* current_user_info is changed on new vuid */
678 reload_services( True );
680 SSVAL(req->outbuf, smb_vwv3, 0);
682 if (server_info->guest) {
683 SSVAL(req->outbuf,smb_vwv2,1);
686 sessionsetup_start_signing_engine(server_info,
687 (uint8 *)req->inbuf);
690 out:
692 if (wrap) {
693 response = spnego_gen_auth_response(ntlmssp_blob,
694 nt_status, OID);
695 } else {
696 response = *ntlmssp_blob;
699 reply_sesssetup_blob(req, response, nt_status);
700 if (wrap) {
701 data_blob_free(&response);
704 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
705 and the other end, that we are not finished yet. */
707 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
708 /* NB. This is *NOT* an error case. JRA */
709 auth_ntlmssp_end(auth_ntlmssp_state);
710 if (!NT_STATUS_IS_OK(nt_status)) {
711 /* Kill the intermediate vuid */
712 invalidate_vuid(vuid);
717 /****************************************************************************
718 Is this a krb5 mechanism ?
719 ****************************************************************************/
721 NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in,
722 DATA_BLOB *pblob_out,
723 char **kerb_mechOID)
725 char *OIDs[ASN1_MAX_OIDS];
726 int i;
727 NTSTATUS ret = NT_STATUS_OK;
729 *kerb_mechOID = NULL;
731 /* parse out the OIDs and the first sec blob */
732 if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
733 return NT_STATUS_LOGON_FAILURE;
736 /* only look at the first OID for determining the mechToken --
737 according to RFC2478, we should choose the one we want
738 and renegotiate, but i smell a client bug here..
740 Problem observed when connecting to a member (samba box)
741 of an AD domain as a user in a Samba domain. Samba member
742 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
743 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
744 NTLMSSP mechtoken. --jerry */
746 #ifdef HAVE_KRB5
747 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
748 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
749 *kerb_mechOID = SMB_STRDUP(OIDs[0]);
750 if (*kerb_mechOID == NULL) {
751 ret = NT_STATUS_NO_MEMORY;
754 #endif
756 for (i=0;OIDs[i];i++) {
757 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
758 free(OIDs[i]);
760 return ret;
763 /****************************************************************************
764 Fall back from krb5 to NTLMSSP.
765 ****************************************************************************/
767 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
768 uint16 vuid)
770 DATA_BLOB response;
772 reply_outbuf(req, 4, 0);
773 SSVAL(req->outbuf,smb_uid,vuid);
775 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
776 "but set to downgrade to NTLMSSP\n"));
778 response = spnego_gen_auth_response(NULL,
779 NT_STATUS_MORE_PROCESSING_REQUIRED,
780 OID_NTLMSSP);
781 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
782 data_blob_free(&response);
785 /****************************************************************************
786 Reply to a session setup spnego negotiate packet.
787 ****************************************************************************/
789 static void reply_spnego_negotiate(struct smb_request *req,
790 uint16 vuid,
791 DATA_BLOB blob1,
792 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
794 DATA_BLOB secblob;
795 DATA_BLOB chal;
796 char *kerb_mech = NULL;
797 NTSTATUS status;
799 status = parse_spnego_mechanisms(blob1, &secblob, &kerb_mech);
800 if (!NT_STATUS_IS_OK(status)) {
801 /* Kill the intermediate vuid */
802 invalidate_vuid(vuid);
803 reply_nterror(req, nt_status_squash(status));
804 return;
807 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
808 (unsigned long)secblob.length));
810 #ifdef HAVE_KRB5
811 if (kerb_mech && ((lp_security()==SEC_ADS) ||
812 lp_use_kerberos_keytab()) ) {
813 bool destroy_vuid = True;
814 reply_spnego_kerberos(req, &secblob, kerb_mech,
815 vuid, &destroy_vuid);
816 data_blob_free(&secblob);
817 if (destroy_vuid) {
818 /* Kill the intermediate vuid */
819 invalidate_vuid(vuid);
821 SAFE_FREE(kerb_mech);
822 return;
824 #endif
826 if (*auth_ntlmssp_state) {
827 auth_ntlmssp_end(auth_ntlmssp_state);
830 if (kerb_mech) {
831 data_blob_free(&secblob);
832 /* The mechtoken is a krb5 ticket, but
833 * we need to fall back to NTLM. */
834 reply_spnego_downgrade_to_ntlmssp(req, vuid);
835 SAFE_FREE(kerb_mech);
836 return;
839 status = auth_ntlmssp_start(auth_ntlmssp_state);
840 if (!NT_STATUS_IS_OK(status)) {
841 /* Kill the intermediate vuid */
842 invalidate_vuid(vuid);
843 reply_nterror(req, nt_status_squash(status));
844 return;
847 status = auth_ntlmssp_update(*auth_ntlmssp_state,
848 secblob, &chal);
850 data_blob_free(&secblob);
852 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
853 &chal, status, OID_NTLMSSP, true);
855 data_blob_free(&chal);
857 /* already replied */
858 return;
861 /****************************************************************************
862 Reply to a session setup spnego auth packet.
863 ****************************************************************************/
865 static void reply_spnego_auth(struct smb_request *req,
866 uint16 vuid,
867 DATA_BLOB blob1,
868 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
870 DATA_BLOB auth = data_blob_null;
871 DATA_BLOB auth_reply = data_blob_null;
872 DATA_BLOB secblob = data_blob_null;
873 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
875 if (!spnego_parse_auth(blob1, &auth)) {
876 #if 0
877 file_save("auth.dat", blob1.data, blob1.length);
878 #endif
879 /* Kill the intermediate vuid */
880 invalidate_vuid(vuid);
882 reply_nterror(req, nt_status_squash(
883 NT_STATUS_LOGON_FAILURE));
884 return;
887 if (auth.data[0] == ASN1_APPLICATION(0)) {
888 /* Might be a second negTokenTarg packet */
889 char *kerb_mech = NULL;
891 status = parse_spnego_mechanisms(auth, &secblob, &kerb_mech);
893 if (!NT_STATUS_IS_OK(status)) {
894 /* Kill the intermediate vuid */
895 invalidate_vuid(vuid);
896 reply_nterror(req, nt_status_squash(status));
897 return;
900 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
901 (unsigned long)secblob.length));
902 #ifdef HAVE_KRB5
903 if (kerb_mech && ((lp_security()==SEC_ADS) ||
904 lp_use_kerberos_keytab()) ) {
905 bool destroy_vuid = True;
906 reply_spnego_kerberos(req, &secblob, kerb_mech,
907 vuid, &destroy_vuid);
908 data_blob_free(&secblob);
909 data_blob_free(&auth);
910 if (destroy_vuid) {
911 /* Kill the intermediate vuid */
912 invalidate_vuid(vuid);
914 SAFE_FREE(kerb_mech);
915 return;
917 #endif
918 /* Can't blunder into NTLMSSP auth if we have
919 * a krb5 ticket. */
921 if (kerb_mech) {
922 /* Kill the intermediate vuid */
923 invalidate_vuid(vuid);
924 DEBUG(3,("reply_spnego_auth: network "
925 "misconfiguration, client sent us a "
926 "krb5 ticket and kerberos security "
927 "not enabled"));
928 reply_nterror(req, nt_status_squash(
929 NT_STATUS_LOGON_FAILURE));
930 SAFE_FREE(kerb_mech);
934 /* If we get here it wasn't a negTokenTarg auth packet. */
935 data_blob_free(&secblob);
937 if (!*auth_ntlmssp_state) {
938 status = auth_ntlmssp_start(auth_ntlmssp_state);
939 if (!NT_STATUS_IS_OK(status)) {
940 /* Kill the intermediate vuid */
941 invalidate_vuid(vuid);
942 reply_nterror(req, nt_status_squash(status));
943 return;
947 status = auth_ntlmssp_update(*auth_ntlmssp_state,
948 auth, &auth_reply);
950 data_blob_free(&auth);
952 /* Don't send the mechid as we've already sent this (RFC4178). */
954 reply_spnego_ntlmssp(req, vuid,
955 auth_ntlmssp_state,
956 &auth_reply, status, NULL, true);
958 data_blob_free(&auth_reply);
960 /* and tell smbd that we have already replied to this packet */
961 return;
964 /****************************************************************************
965 List to store partial SPNEGO auth fragments.
966 ****************************************************************************/
968 static struct pending_auth_data *pd_list;
970 /****************************************************************************
971 Delete an entry on the list.
972 ****************************************************************************/
974 static void delete_partial_auth(struct pending_auth_data *pad)
976 if (!pad) {
977 return;
979 DLIST_REMOVE(pd_list, pad);
980 data_blob_free(&pad->partial_data);
981 SAFE_FREE(pad);
984 /****************************************************************************
985 Search for a partial SPNEGO auth fragment matching an smbpid.
986 ****************************************************************************/
988 static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
990 struct pending_auth_data *pad;
992 for (pad = pd_list; pad; pad = pad->next) {
993 if (pad->smbpid == smbpid) {
994 break;
997 return pad;
1000 /****************************************************************************
1001 Check the size of an SPNEGO blob. If we need more return
1002 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
1003 the blob to be more than 64k.
1004 ****************************************************************************/
1006 static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid,
1007 DATA_BLOB *pblob)
1009 struct pending_auth_data *pad = NULL;
1010 ASN1_DATA data;
1011 size_t needed_len = 0;
1013 pad = get_pending_auth_data(smbpid);
1015 /* Ensure we have some data. */
1016 if (pblob->length == 0) {
1017 /* Caller can cope. */
1018 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
1019 delete_partial_auth(pad);
1020 return NT_STATUS_OK;
1023 /* Were we waiting for more data ? */
1024 if (pad) {
1025 DATA_BLOB tmp_blob;
1026 size_t copy_len = MIN(65536, pblob->length);
1028 /* Integer wrap paranoia.... */
1030 if (pad->partial_data.length + copy_len <
1031 pad->partial_data.length ||
1032 pad->partial_data.length + copy_len < copy_len) {
1034 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1035 "pad->partial_data.length = %u, "
1036 "copy_len = %u\n",
1037 (unsigned int)pad->partial_data.length,
1038 (unsigned int)copy_len ));
1040 delete_partial_auth(pad);
1041 return NT_STATUS_INVALID_PARAMETER;
1044 DEBUG(10,("check_spnego_blob_complete: "
1045 "pad->partial_data.length = %u, "
1046 "pad->needed_len = %u, "
1047 "copy_len = %u, "
1048 "pblob->length = %u,\n",
1049 (unsigned int)pad->partial_data.length,
1050 (unsigned int)pad->needed_len,
1051 (unsigned int)copy_len,
1052 (unsigned int)pblob->length ));
1054 tmp_blob = data_blob(NULL,
1055 pad->partial_data.length + copy_len);
1057 /* Concatenate the two (up to copy_len) bytes. */
1058 memcpy(tmp_blob.data,
1059 pad->partial_data.data,
1060 pad->partial_data.length);
1061 memcpy(tmp_blob.data + pad->partial_data.length,
1062 pblob->data,
1063 copy_len);
1065 /* Replace the partial data. */
1066 data_blob_free(&pad->partial_data);
1067 pad->partial_data = tmp_blob;
1068 ZERO_STRUCT(tmp_blob);
1070 /* Are we done ? */
1071 if (pblob->length >= pad->needed_len) {
1072 /* Yes, replace pblob. */
1073 data_blob_free(pblob);
1074 *pblob = pad->partial_data;
1075 ZERO_STRUCT(pad->partial_data);
1076 delete_partial_auth(pad);
1077 return NT_STATUS_OK;
1080 /* Still need more data. */
1081 pad->needed_len -= copy_len;
1082 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1085 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
1086 (pblob->data[0] != ASN1_CONTEXT(1))) {
1087 /* Not something we can determine the
1088 * length of.
1090 return NT_STATUS_OK;
1093 /* This is a new SPNEGO sessionsetup - see if
1094 * the data given in this blob is enough.
1097 asn1_load(&data, *pblob);
1098 asn1_start_tag(&data, pblob->data[0]);
1099 if (data.has_error || data.nesting == NULL) {
1100 asn1_free(&data);
1101 /* Let caller catch. */
1102 return NT_STATUS_OK;
1105 /* Integer wrap paranoia.... */
1107 if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
1108 data.nesting->taglen + data.nesting->start < data.nesting->start) {
1110 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1111 "data.nesting->taglen = %u, "
1112 "data.nesting->start = %u\n",
1113 (unsigned int)data.nesting->taglen,
1114 (unsigned int)data.nesting->start ));
1116 asn1_free(&data);
1117 return NT_STATUS_INVALID_PARAMETER;
1120 /* Total length of the needed asn1 is the tag length
1121 * plus the current offset. */
1123 needed_len = data.nesting->taglen + data.nesting->start;
1124 asn1_free(&data);
1126 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1127 "pblob->length = %u\n",
1128 (unsigned int)needed_len,
1129 (unsigned int)pblob->length ));
1131 if (needed_len <= pblob->length) {
1132 /* Nothing to do - blob is complete. */
1133 return NT_STATUS_OK;
1136 /* Refuse the blob if it's bigger than 64k. */
1137 if (needed_len > 65536) {
1138 DEBUG(2,("check_spnego_blob_complete: needed_len "
1139 "too large (%u)\n",
1140 (unsigned int)needed_len ));
1141 return NT_STATUS_INVALID_PARAMETER;
1144 /* We must store this blob until complete. */
1145 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1146 return NT_STATUS_NO_MEMORY;
1148 pad->needed_len = needed_len - pblob->length;
1149 pad->partial_data = data_blob(pblob->data, pblob->length);
1150 if (pad->partial_data.data == NULL) {
1151 SAFE_FREE(pad);
1152 return NT_STATUS_NO_MEMORY;
1154 pad->smbpid = smbpid;
1155 pad->vuid = vuid;
1156 DLIST_ADD(pd_list, pad);
1158 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1161 /****************************************************************************
1162 Reply to a session setup command.
1163 conn POINTER CAN BE NULL HERE !
1164 ****************************************************************************/
1166 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1168 uint8 *p;
1169 DATA_BLOB blob1;
1170 size_t bufrem;
1171 fstring native_os, native_lanman, primary_domain;
1172 const char *p2;
1173 uint16 data_blob_len = SVAL(req->inbuf, smb_vwv7);
1174 enum remote_arch_types ra_type = get_remote_arch();
1175 int vuid = SVAL(req->inbuf,smb_uid);
1176 user_struct *vuser = NULL;
1177 NTSTATUS status = NT_STATUS_OK;
1178 uint16 smbpid = req->smbpid;
1179 uint16 smb_flag2 = req->flags2;
1181 DEBUG(3,("Doing spnego session setup\n"));
1183 if (global_client_caps == 0) {
1184 global_client_caps = IVAL(req->inbuf,smb_vwv10);
1186 if (!(global_client_caps & CAP_STATUS32)) {
1187 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1192 p = (uint8 *)smb_buf(req->inbuf);
1194 if (data_blob_len == 0) {
1195 /* an invalid request */
1196 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1197 return;
1200 bufrem = smb_bufrem(req->inbuf, p);
1201 /* pull the spnego blob */
1202 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1204 #if 0
1205 file_save("negotiate.dat", blob1.data, blob1.length);
1206 #endif
1208 p2 = (char *)req->inbuf + smb_vwv13 + data_blob_len;
1209 p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_os, p2,
1210 sizeof(native_os), STR_TERMINATE);
1211 p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_lanman, p2,
1212 sizeof(native_lanman), STR_TERMINATE);
1213 p2 += srvstr_pull_buf(req->inbuf, smb_flag2, primary_domain, p2,
1214 sizeof(primary_domain), STR_TERMINATE);
1215 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1216 native_os, native_lanman, primary_domain));
1218 if ( ra_type == RA_WIN2K ) {
1219 /* Vista sets neither the OS or lanman strings */
1221 if ( !strlen(native_os) && !strlen(native_lanman) )
1222 set_remote_arch(RA_VISTA);
1224 /* Windows 2003 doesn't set the native lanman string,
1225 but does set primary domain which is a bug I think */
1227 if ( !strlen(native_lanman) ) {
1228 ra_lanman_string( primary_domain );
1229 } else {
1230 ra_lanman_string( native_lanman );
1234 /* Did we get a valid vuid ? */
1235 if (!is_partial_auth_vuid(vuid)) {
1236 /* No, then try and see if this is an intermediate sessionsetup
1237 * for a large SPNEGO packet. */
1238 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
1239 if (pad) {
1240 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1241 "pending vuid %u\n",
1242 (unsigned int)pad->vuid ));
1243 vuid = pad->vuid;
1247 /* Do we have a valid vuid now ? */
1248 if (!is_partial_auth_vuid(vuid)) {
1249 /* No, start a new authentication setup. */
1250 vuid = register_initial_vuid();
1251 if (vuid == UID_FIELD_INVALID) {
1252 data_blob_free(&blob1);
1253 reply_nterror(req, nt_status_squash(
1254 NT_STATUS_INVALID_PARAMETER));
1255 return;
1259 vuser = get_partial_auth_user_struct(vuid);
1260 /* This MUST be valid. */
1261 if (!vuser) {
1262 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1265 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1266 * sessionsetup requests as the Windows limit on the security blob
1267 * field is 4k. Bug #4400. JRA.
1270 status = check_spnego_blob_complete(smbpid, vuid, &blob1);
1271 if (!NT_STATUS_IS_OK(status)) {
1272 if (!NT_STATUS_EQUAL(status,
1273 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1274 /* Real error - kill the intermediate vuid */
1275 invalidate_vuid(vuid);
1277 data_blob_free(&blob1);
1278 reply_nterror(req, nt_status_squash(status));
1279 return;
1282 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1284 /* its a negTokenTarg packet */
1286 reply_spnego_negotiate(req, vuid, blob1,
1287 &vuser->auth_ntlmssp_state);
1288 data_blob_free(&blob1);
1289 return;
1292 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1294 /* its a auth packet */
1296 reply_spnego_auth(req, vuid, blob1,
1297 &vuser->auth_ntlmssp_state);
1298 data_blob_free(&blob1);
1299 return;
1302 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1303 DATA_BLOB chal;
1305 if (!vuser->auth_ntlmssp_state) {
1306 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1307 if (!NT_STATUS_IS_OK(status)) {
1308 /* Kill the intermediate vuid */
1309 invalidate_vuid(vuid);
1310 data_blob_free(&blob1);
1311 reply_nterror(req, nt_status_squash(status));
1312 return;
1316 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1317 blob1, &chal);
1319 data_blob_free(&blob1);
1321 reply_spnego_ntlmssp(req, vuid,
1322 &vuser->auth_ntlmssp_state,
1323 &chal, status, OID_NTLMSSP, false);
1324 data_blob_free(&chal);
1325 return;
1328 /* what sort of packet is this? */
1329 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1331 data_blob_free(&blob1);
1333 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1336 /****************************************************************************
1337 On new VC == 0, shutdown *all* old connections and users.
1338 It seems that only NT4.x does this. At W2K and above (XP etc.).
1339 a new session setup with VC==0 is ignored.
1340 ****************************************************************************/
1342 static int shutdown_other_smbds(struct db_record *rec,
1343 const struct connections_key *key,
1344 const struct connections_data *crec,
1345 void *private_data)
1347 const char *ip = (const char *)private_data;
1349 if (!process_exists(crec->pid)) {
1350 return 0;
1353 if (procid_is_me(&crec->pid)) {
1354 return 0;
1357 if (strcmp(ip, crec->addr) != 0) {
1358 return 0;
1361 messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1362 &data_blob_null);
1363 return 0;
1366 static void setup_new_vc_session(void)
1368 char addr[INET6_ADDRSTRLEN];
1370 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1371 "compatible we would close all old resources.\n"));
1372 #if 0
1373 conn_close_all();
1374 invalidate_all_vuids();
1375 #endif
1376 if (lp_reset_on_zero_vc()) {
1377 connections_forall(shutdown_other_smbds,
1378 CONST_DISCARD(void *,
1379 client_addr(get_client_fd(),addr,sizeof(addr))));
1383 /****************************************************************************
1384 Reply to a session setup command.
1385 ****************************************************************************/
1387 void reply_sesssetup_and_X(struct smb_request *req)
1389 int sess_vuid;
1390 int smb_bufsize;
1391 DATA_BLOB lm_resp;
1392 DATA_BLOB nt_resp;
1393 DATA_BLOB plaintext_password;
1394 fstring user;
1395 fstring sub_user; /* Sainitised username for substituion */
1396 fstring domain;
1397 fstring native_os;
1398 fstring native_lanman;
1399 fstring primary_domain;
1400 static bool done_sesssetup = False;
1401 auth_usersupplied_info *user_info = NULL;
1402 auth_serversupplied_info *server_info = NULL;
1403 uint16 smb_flag2 = req->flags2;
1405 NTSTATUS nt_status;
1407 bool doencrypt = global_encrypted_passwords_negotiated;
1409 START_PROFILE(SMBsesssetupX);
1411 ZERO_STRUCT(lm_resp);
1412 ZERO_STRUCT(nt_resp);
1413 ZERO_STRUCT(plaintext_password);
1415 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1417 /* a SPNEGO session setup has 12 command words, whereas a normal
1418 NT1 session setup has 13. See the cifs spec. */
1419 if (req->wct == 12 &&
1420 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1422 if (!global_spnego_negotiated) {
1423 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1424 "at SPNEGO session setup when it was not "
1425 "negotiated.\n"));
1426 reply_nterror(req, nt_status_squash(
1427 NT_STATUS_LOGON_FAILURE));
1428 END_PROFILE(SMBsesssetupX);
1429 return;
1432 if (SVAL(req->inbuf,smb_vwv4) == 0) {
1433 setup_new_vc_session();
1436 reply_sesssetup_and_X_spnego(req);
1437 END_PROFILE(SMBsesssetupX);
1438 return;
1441 smb_bufsize = SVAL(req->inbuf,smb_vwv2);
1443 if (Protocol < PROTOCOL_NT1) {
1444 uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
1446 /* Never do NT status codes with protocols before NT1 as we
1447 * don't get client caps. */
1448 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1450 if ((passlen1 > MAX_PASS_LEN)
1451 || (passlen1 > smb_bufrem(req->inbuf,
1452 smb_buf(req->inbuf)))) {
1453 reply_nterror(req, nt_status_squash(
1454 NT_STATUS_INVALID_PARAMETER));
1455 END_PROFILE(SMBsesssetupX);
1456 return;
1459 if (doencrypt) {
1460 lm_resp = data_blob(smb_buf(req->inbuf), passlen1);
1461 } else {
1462 plaintext_password = data_blob(smb_buf(req->inbuf),
1463 passlen1+1);
1464 /* Ensure null termination */
1465 plaintext_password.data[passlen1] = 0;
1468 srvstr_pull_buf(req->inbuf, req->flags2, user,
1469 smb_buf(req->inbuf)+passlen1, sizeof(user),
1470 STR_TERMINATE);
1471 *domain = 0;
1473 } else {
1474 uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
1475 uint16 passlen2 = SVAL(req->inbuf,smb_vwv8);
1476 enum remote_arch_types ra_type = get_remote_arch();
1477 char *p = smb_buf(req->inbuf);
1478 char *save_p = smb_buf(req->inbuf);
1479 uint16 byte_count;
1482 if(global_client_caps == 0) {
1483 global_client_caps = IVAL(req->inbuf,smb_vwv11);
1485 if (!(global_client_caps & CAP_STATUS32)) {
1486 remove_from_common_flags2(
1487 FLAGS2_32_BIT_ERROR_CODES);
1490 /* client_caps is used as final determination if
1491 * client is NT or Win95. This is needed to return
1492 * the correct error codes in some circumstances.
1495 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1496 ra_type == RA_WIN95) {
1497 if(!(global_client_caps & (CAP_NT_SMBS|
1498 CAP_STATUS32))) {
1499 set_remote_arch( RA_WIN95);
1504 if (!doencrypt) {
1505 /* both Win95 and WinNT stuff up the password
1506 * lengths for non-encrypting systems. Uggh.
1508 if passlen1==24 its a win95 system, and its setting
1509 the password length incorrectly. Luckily it still
1510 works with the default code because Win95 will null
1511 terminate the password anyway
1513 if passlen1>0 and passlen2>0 then maybe its a NT box
1514 and its setting passlen2 to some random value which
1515 really stuffs things up. we need to fix that one. */
1517 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1518 passlen2 != 1) {
1519 passlen2 = 0;
1523 /* check for nasty tricks */
1524 if (passlen1 > MAX_PASS_LEN
1525 || passlen1 > smb_bufrem(req->inbuf, p)) {
1526 reply_nterror(req, nt_status_squash(
1527 NT_STATUS_INVALID_PARAMETER));
1528 END_PROFILE(SMBsesssetupX);
1529 return;
1532 if (passlen2 > MAX_PASS_LEN
1533 || passlen2 > smb_bufrem(req->inbuf, p+passlen1)) {
1534 reply_nterror(req, nt_status_squash(
1535 NT_STATUS_INVALID_PARAMETER));
1536 END_PROFILE(SMBsesssetupX);
1537 return;
1540 /* Save the lanman2 password and the NT md4 password. */
1542 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1543 doencrypt = False;
1546 if (doencrypt) {
1547 lm_resp = data_blob(p, passlen1);
1548 nt_resp = data_blob(p+passlen1, passlen2);
1549 } else if (lp_security() != SEC_SHARE) {
1551 * In share level we should ignore any passwords, so
1552 * only read them if we're not.
1554 char *pass = NULL;
1555 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1557 if (unic && (passlen2 == 0) && passlen1) {
1558 /* Only a ascii plaintext password was sent. */
1559 (void)srvstr_pull_talloc(talloc_tos(),
1560 req->inbuf,
1561 req->flags2,
1562 &pass,
1563 smb_buf(req->inbuf),
1564 passlen1,
1565 STR_TERMINATE|STR_ASCII);
1566 } else {
1567 (void)srvstr_pull_talloc(talloc_tos(),
1568 req->inbuf,
1569 req->flags2,
1570 &pass,
1571 smb_buf(req->inbuf),
1572 unic ? passlen2 : passlen1,
1573 STR_TERMINATE);
1575 if (!pass) {
1576 reply_nterror(req, nt_status_squash(
1577 NT_STATUS_INVALID_PARAMETER));
1578 END_PROFILE(SMBsesssetupX);
1579 return;
1581 plaintext_password = data_blob(pass, strlen(pass)+1);
1584 p += passlen1 + passlen2;
1585 p += srvstr_pull_buf(req->inbuf, req->flags2, user, p,
1586 sizeof(user), STR_TERMINATE);
1587 p += srvstr_pull_buf(req->inbuf, req->flags2, domain, p,
1588 sizeof(domain), STR_TERMINATE);
1589 p += srvstr_pull_buf(req->inbuf, req->flags2, native_os,
1590 p, sizeof(native_os), STR_TERMINATE);
1591 p += srvstr_pull_buf(req->inbuf, req->flags2,
1592 native_lanman, p, sizeof(native_lanman),
1593 STR_TERMINATE);
1595 /* not documented or decoded by Ethereal but there is one more
1596 * string in the extra bytes which is the same as the
1597 * PrimaryDomain when using extended security. Windows NT 4
1598 * and 2003 use this string to store the native lanman string.
1599 * Windows 9x does not include a string here at all so we have
1600 * to check if we have any extra bytes left */
1602 byte_count = SVAL(req->inbuf, smb_vwv13);
1603 if ( PTR_DIFF(p, save_p) < byte_count) {
1604 p += srvstr_pull_buf(req->inbuf, req->flags2,
1605 primary_domain, p,
1606 sizeof(primary_domain),
1607 STR_TERMINATE);
1608 } else {
1609 fstrcpy( primary_domain, "null" );
1612 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1613 "PrimaryDomain=[%s]\n",
1614 domain, native_os, native_lanman, primary_domain));
1616 if ( ra_type == RA_WIN2K ) {
1617 if ( strlen(native_lanman) == 0 )
1618 ra_lanman_string( primary_domain );
1619 else
1620 ra_lanman_string( native_lanman );
1625 if (SVAL(req->inbuf,smb_vwv4) == 0) {
1626 setup_new_vc_session();
1629 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1630 domain, user, get_remote_machine_name()));
1632 if (*user) {
1633 if (global_spnego_negotiated) {
1635 /* This has to be here, because this is a perfectly
1636 * valid behaviour for guest logons :-( */
1638 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1639 "at 'normal' session setup after "
1640 "negotiating spnego.\n"));
1641 reply_nterror(req, nt_status_squash(
1642 NT_STATUS_LOGON_FAILURE));
1643 END_PROFILE(SMBsesssetupX);
1644 return;
1646 fstrcpy(sub_user, user);
1647 } else {
1648 fstrcpy(sub_user, lp_guestaccount());
1651 sub_set_smb_name(sub_user);
1653 reload_services(True);
1655 if (lp_security() == SEC_SHARE) {
1656 /* In share level we should ignore any passwords */
1658 data_blob_free(&lm_resp);
1659 data_blob_free(&nt_resp);
1660 data_blob_clear_free(&plaintext_password);
1662 map_username(sub_user);
1663 add_session_user(sub_user);
1664 add_session_workgroup(domain);
1665 /* Then force it to null for the benfit of the code below */
1666 *user = 0;
1669 if (!*user) {
1671 nt_status = check_guest_password(&server_info);
1673 } else if (doencrypt) {
1674 if (!negprot_global_auth_context) {
1675 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1676 "session setup without negprot denied!\n"));
1677 reply_nterror(req, nt_status_squash(
1678 NT_STATUS_LOGON_FAILURE));
1679 END_PROFILE(SMBsesssetupX);
1680 return;
1682 nt_status = make_user_info_for_reply_enc(&user_info, user,
1683 domain,
1684 lm_resp, nt_resp);
1685 if (NT_STATUS_IS_OK(nt_status)) {
1686 nt_status = negprot_global_auth_context->check_ntlm_password(
1687 negprot_global_auth_context,
1688 user_info,
1689 &server_info);
1691 } else {
1692 struct auth_context *plaintext_auth_context = NULL;
1693 const uint8 *chal;
1695 nt_status = make_auth_context_subsystem(
1696 &plaintext_auth_context);
1698 if (NT_STATUS_IS_OK(nt_status)) {
1699 chal = plaintext_auth_context->get_ntlm_challenge(
1700 plaintext_auth_context);
1702 if (!make_user_info_for_reply(&user_info,
1703 user, domain, chal,
1704 plaintext_password)) {
1705 nt_status = NT_STATUS_NO_MEMORY;
1708 if (NT_STATUS_IS_OK(nt_status)) {
1709 nt_status = plaintext_auth_context->check_ntlm_password(
1710 plaintext_auth_context,
1711 user_info,
1712 &server_info);
1714 (plaintext_auth_context->free)(
1715 &plaintext_auth_context);
1720 free_user_info(&user_info);
1722 if (!NT_STATUS_IS_OK(nt_status)) {
1723 nt_status = do_map_to_guest(nt_status, &server_info,
1724 user, domain);
1727 if (!NT_STATUS_IS_OK(nt_status)) {
1728 data_blob_free(&nt_resp);
1729 data_blob_free(&lm_resp);
1730 data_blob_clear_free(&plaintext_password);
1731 reply_nterror(req, nt_status_squash(nt_status));
1732 END_PROFILE(SMBsesssetupX);
1733 return;
1736 /* Ensure we can't possible take a code path leading to a
1737 * null defref. */
1738 if (!server_info) {
1739 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1740 END_PROFILE(SMBsesssetupX);
1741 return;
1744 nt_status = create_local_token(server_info);
1745 if (!NT_STATUS_IS_OK(nt_status)) {
1746 DEBUG(10, ("create_local_token failed: %s\n",
1747 nt_errstr(nt_status)));
1748 data_blob_free(&nt_resp);
1749 data_blob_free(&lm_resp);
1750 data_blob_clear_free(&plaintext_password);
1751 reply_nterror(req, nt_status_squash(nt_status));
1752 END_PROFILE(SMBsesssetupX);
1753 return;
1756 data_blob_clear_free(&plaintext_password);
1758 /* it's ok - setup a reply */
1759 reply_outbuf(req, 3, 0);
1760 if (Protocol >= PROTOCOL_NT1) {
1761 push_signature(&req->outbuf);
1762 /* perhaps grab OS version here?? */
1765 if (server_info->guest) {
1766 SSVAL(req->outbuf,smb_vwv2,1);
1769 /* register the name and uid as being validated, so further connections
1770 to a uid can get through without a password, on the same VC */
1772 if (lp_security() == SEC_SHARE) {
1773 sess_vuid = UID_FIELD_INVALID;
1774 TALLOC_FREE(server_info);
1775 } else {
1776 /* Ignore the initial vuid. */
1777 sess_vuid = register_initial_vuid();
1778 if (sess_vuid == UID_FIELD_INVALID) {
1779 data_blob_free(&nt_resp);
1780 data_blob_free(&lm_resp);
1781 reply_nterror(req, nt_status_squash(
1782 NT_STATUS_LOGON_FAILURE));
1783 END_PROFILE(SMBsesssetupX);
1784 return;
1786 /* register_existing_vuid keeps the server info */
1787 sess_vuid = register_existing_vuid(sess_vuid,
1788 server_info,
1789 nt_resp.data ? nt_resp : lm_resp,
1790 sub_user);
1791 if (sess_vuid == UID_FIELD_INVALID) {
1792 data_blob_free(&nt_resp);
1793 data_blob_free(&lm_resp);
1794 reply_nterror(req, nt_status_squash(
1795 NT_STATUS_LOGON_FAILURE));
1796 END_PROFILE(SMBsesssetupX);
1797 return;
1800 /* current_user_info is changed on new vuid */
1801 reload_services( True );
1803 sessionsetup_start_signing_engine(server_info, req->inbuf);
1806 data_blob_free(&nt_resp);
1807 data_blob_free(&lm_resp);
1809 SSVAL(req->outbuf,smb_uid,sess_vuid);
1810 SSVAL(req->inbuf,smb_uid,sess_vuid);
1812 if (!done_sesssetup)
1813 max_send = MIN(max_send,smb_bufsize);
1815 done_sesssetup = True;
1817 END_PROFILE(SMBsesssetupX);
1818 chain_reply(req);
1819 return;