2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1998-2001
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
7 Copyright (C) Luke Howard 2003
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 extern struct auth_context *negprot_global_auth_context;
27 extern BOOL global_encrypted_passwords_negotiated;
28 extern BOOL global_spnego_negotiated;
29 extern enum protocol_types Protocol;
32 uint32 global_client_caps = 0;
35 on a logon error possibly map the error to success if "map to guest"
38 static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **server_info,
39 const char *user, const char *domain)
41 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
42 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
43 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
44 DEBUG(3,("No such user %s [%s] - using guest account\n",
46 status = make_server_info_guest(server_info);
50 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
51 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
52 DEBUG(3,("Registered username %s for guest access\n",user));
53 status = make_server_info_guest(server_info);
60 /****************************************************************************
61 Add the standard 'Samba' signature to the end of the session setup.
62 ****************************************************************************/
64 static int add_signature(char *outbuf, char *p)
69 fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
71 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
72 p += srvstr_push(outbuf, p, lanman, -1, STR_TERMINATE);
73 p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
75 return PTR_DIFF(p, start);
78 /****************************************************************************
79 Start the signing engine if needed. Don't fail signing here.
80 ****************************************************************************/
82 static void sessionsetup_start_signing_engine(const auth_serversupplied_info *server_info, char *inbuf)
84 if (!server_info->guest && !srv_signing_started()) {
85 /* We need to start the signing engine
86 * here but a W2K client sends the old
87 * "BSRSPYL " signature instead of the
88 * correct one. Subsequent packets will
91 srv_check_sign_mac(inbuf, False);
95 /****************************************************************************
96 Send a security blob via a session setup reply.
97 ****************************************************************************/
99 static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
100 DATA_BLOB blob, NTSTATUS nt_status)
104 if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
105 ERROR_NT(nt_status_squash(nt_status));
107 set_message(outbuf,4,0,True);
109 nt_status = nt_status_squash(nt_status);
110 SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
111 SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
112 SSVAL(outbuf, smb_vwv3, blob.length);
115 /* should we cap this? */
116 memcpy(p, blob.data, blob.length);
119 p += add_signature( outbuf, p );
121 set_message_end(outbuf,p);
125 return send_smb(smbd_server_fd(),outbuf);
128 /****************************************************************************
129 Do a 'guest' logon, getting back the
130 ****************************************************************************/
132 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
134 struct auth_context *auth_context;
135 auth_usersupplied_info *user_info = NULL;
138 unsigned char chal[8];
142 DEBUG(3,("Got anonymous request\n"));
144 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) {
148 if (!make_user_info_guest(&user_info)) {
149 (auth_context->free)(&auth_context);
150 return NT_STATUS_NO_MEMORY;
153 nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info);
154 (auth_context->free)(&auth_context);
155 free_user_info(&user_info);
161 /****************************************************************************
162 reply to a session setup spnego negotiate packet for kerberos
163 ****************************************************************************/
164 static int reply_spnego_kerberos(connection_struct *conn,
165 char *inbuf, char *outbuf,
166 int length, int bufsize,
171 char *client, *p, *domain;
172 fstring netbios_domain_name;
178 DATA_BLOB ap_rep, ap_rep_wrapped, response;
179 auth_serversupplied_info *server_info = NULL;
180 DATA_BLOB session_key = data_blob(NULL, 0);
182 DATA_BLOB nullblob = data_blob(NULL, 0);
183 fstring real_username;
184 BOOL map_domainuser_to_guest = False;
185 BOOL username_was_mapped;
186 PAC_LOGON_INFO *logon_info = NULL;
189 ZERO_STRUCT(pac_data);
191 ZERO_STRUCT(ap_rep_wrapped);
192 ZERO_STRUCT(response);
194 mem_ctx = talloc_init("reply_spnego_kerberos");
196 return ERROR_NT(nt_status_squash(NT_STATUS_NO_MEMORY));
198 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
199 talloc_destroy(mem_ctx);
200 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
203 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket, &client, &pac_data, &ap_rep, &session_key);
205 data_blob_free(&ticket);
207 if (!NT_STATUS_IS_OK(ret)) {
208 DEBUG(1,("Failed to verify incoming ticket!\n"));
209 talloc_destroy(mem_ctx);
210 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
213 DEBUG(3,("Ticket name is [%s]\n", client));
215 p = strchr_m(client, '@');
217 DEBUG(3,("Doesn't look like a valid principal\n"));
218 data_blob_free(&ap_rep);
219 data_blob_free(&session_key);
221 talloc_destroy(mem_ctx);
222 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
227 /* save the PAC data if we have it */
230 logon_info = get_logon_info_from_pac(pac_data);
232 netsamlogon_cache_store( client, &logon_info->info3 );
236 if (!strequal(p+1, lp_realm())) {
237 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
238 if (!lp_allow_trusted_domains()) {
239 data_blob_free(&ap_rep);
240 data_blob_free(&session_key);
242 talloc_destroy(mem_ctx);
243 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
247 /* this gives a fully qualified user name (ie. with full realm).
248 that leads to very long usernames, but what else can we do? */
252 if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) {
254 unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, -1);
255 domain = netbios_domain_name;
256 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
260 /* If we have winbind running, we can (and must) shorten the
261 username by using the short netbios name. Otherwise we will
262 have inconsistent user names. With Kerberos, we get the
263 fully qualified realm, with ntlmssp we get the short
264 name. And even w2k3 does use ntlmssp if you for example
265 connect to an ip address. */
267 struct winbindd_request wb_request;
268 struct winbindd_response wb_response;
269 NSS_STATUS wb_result;
271 ZERO_STRUCT(wb_request);
272 ZERO_STRUCT(wb_response);
274 DEBUG(10, ("Mapping [%s] to short name\n", domain));
276 fstrcpy(wb_request.domain_name, domain);
278 wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
279 &wb_request, &wb_response);
281 if (wb_result == NSS_STATUS_SUCCESS) {
283 fstrcpy(netbios_domain_name,
284 wb_response.data.domain_info.name);
285 domain = netbios_domain_name;
287 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
289 DEBUG(3, ("Could not find short name -- winbind "
294 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
296 /* lookup the passwd struct, create a new user if necessary */
298 username_was_mapped = map_username( user );
300 pw = smb_getpwnam( mem_ctx, user, real_username, True );
303 /* if a real user check pam account restrictions */
304 /* only really perfomed if "obey pam restriction" is true */
305 /* do this before an eventual mappign to guest occurs */
306 ret = smb_pam_accountcheck(pw->pw_name);
307 if ( !NT_STATUS_IS_OK(ret)) {
308 DEBUG(1, ("PAM account restriction prevents user login\n"));
309 data_blob_free(&ap_rep);
310 data_blob_free(&session_key);
311 TALLOC_FREE(mem_ctx);
312 return ERROR_NT(nt_status_squash(ret));
318 /* this was originally the behavior of Samba 2.2, if a user
319 did not have a local uid but has been authenticated, then
320 map them to a guest account */
322 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
323 map_domainuser_to_guest = True;
324 fstrcpy(user,lp_guestaccount());
325 pw = smb_getpwnam( mem_ctx, user, real_username, True );
328 /* extra sanity check that the guest account is valid */
331 DEBUG(1,("Username %s is invalid on this system\n", user));
333 data_blob_free(&ap_rep);
334 data_blob_free(&session_key);
335 TALLOC_FREE(mem_ctx);
336 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
340 /* setup the string used by %U */
342 sub_set_smb_name( real_username );
343 reload_services(True);
345 if ( map_domainuser_to_guest ) {
346 make_server_info_guest(&server_info);
347 } else if (logon_info) {
348 /* pass the unmapped username here since map_username()
349 will be called again from inside make_server_info_info3() */
351 ret = make_server_info_info3(mem_ctx, client, domain,
352 &server_info, &logon_info->info3);
353 if ( !NT_STATUS_IS_OK(ret) ) {
354 DEBUG(1,("make_server_info_info3 failed: %s!\n",
357 data_blob_free(&ap_rep);
358 data_blob_free(&session_key);
359 TALLOC_FREE(mem_ctx);
360 return ERROR_NT(nt_status_squash(ret));
364 ret = make_server_info_pw(&server_info, real_username, pw);
366 if ( !NT_STATUS_IS_OK(ret) ) {
367 DEBUG(1,("make_server_info_pw failed: %s!\n",
370 data_blob_free(&ap_rep);
371 data_blob_free(&session_key);
372 TALLOC_FREE(mem_ctx);
373 return ERROR_NT(nt_status_squash(ret));
376 /* make_server_info_pw does not set the domain. Without this
377 * we end up with the local netbios name in substitutions for
380 if (server_info->sam_account != NULL) {
381 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
385 server_info->was_mapped |= username_was_mapped;
387 /* we need to build the token for the user. make_server_info_guest()
390 if ( !server_info->ptok ) {
391 ret = create_local_token( server_info );
392 if ( !NT_STATUS_IS_OK(ret) ) {
394 data_blob_free(&ap_rep);
395 data_blob_free(&session_key);
396 TALLOC_FREE( mem_ctx );
397 TALLOC_FREE( server_info );
398 return ERROR_NT(nt_status_squash(ret));
402 /* register_vuid keeps the server info */
403 /* register_vuid takes ownership of session_key, no need to free after this.
404 A better interface would copy it.... */
405 sess_vuid = register_vuid(server_info, session_key, nullblob, client);
409 if (sess_vuid == UID_FIELD_INVALID ) {
410 ret = NT_STATUS_LOGON_FAILURE;
412 /* current_user_info is changed on new vuid */
413 reload_services( True );
415 set_message(outbuf,4,0,True);
416 SSVAL(outbuf, smb_vwv3, 0);
418 if (server_info->guest) {
419 SSVAL(outbuf,smb_vwv2,1);
422 SSVAL(outbuf, smb_uid, sess_vuid);
424 sessionsetup_start_signing_engine(server_info, inbuf);
427 /* wrap that up in a nice GSS-API wrapping */
428 if (NT_STATUS_IS_OK(ret)) {
429 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
431 ap_rep_wrapped = data_blob(NULL, 0);
433 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
434 reply_sesssetup_blob(conn, outbuf, response, ret);
436 data_blob_free(&ap_rep);
437 data_blob_free(&ap_rep_wrapped);
438 data_blob_free(&response);
439 TALLOC_FREE(mem_ctx);
441 return -1; /* already replied */
445 /****************************************************************************
446 Send a session setup reply, wrapped in SPNEGO.
447 Get vuid and check first.
448 End the NTLMSSP exchange context if we are OK/complete fail
449 This should be split into two functions, one to handle each
450 leg of the NTLM auth steps.
451 ***************************************************************************/
453 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
455 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
456 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
461 struct auth_serversupplied_info *server_info = NULL;
463 if (NT_STATUS_IS_OK(nt_status)) {
464 server_info = (*auth_ntlmssp_state)->server_info;
466 nt_status = do_map_to_guest(nt_status,
468 (*auth_ntlmssp_state)->ntlmssp_state->user,
469 (*auth_ntlmssp_state)->ntlmssp_state->domain);
472 if (NT_STATUS_IS_OK(nt_status)) {
474 DATA_BLOB nullblob = data_blob(NULL, 0);
475 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
477 /* register_vuid keeps the server info */
478 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
479 (*auth_ntlmssp_state)->server_info = NULL;
481 if (sess_vuid == UID_FIELD_INVALID ) {
482 nt_status = NT_STATUS_LOGON_FAILURE;
485 /* current_user_info is changed on new vuid */
486 reload_services( True );
488 set_message(outbuf,4,0,True);
489 SSVAL(outbuf, smb_vwv3, 0);
491 if (server_info->guest) {
492 SSVAL(outbuf,smb_vwv2,1);
495 SSVAL(outbuf,smb_uid,sess_vuid);
497 sessionsetup_start_signing_engine(server_info, inbuf);
502 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
504 response = *ntlmssp_blob;
507 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
509 data_blob_free(&response);
512 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
513 and the other end, that we are not finished yet. */
515 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
516 /* NB. This is *NOT* an error case. JRA */
517 auth_ntlmssp_end(auth_ntlmssp_state);
518 /* Kill the intermediate vuid */
519 invalidate_vuid(vuid);
525 /****************************************************************************
526 Reply to a session setup spnego negotiate packet.
527 ****************************************************************************/
529 static int reply_spnego_negotiate(connection_struct *conn,
533 int length, int bufsize,
535 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
537 char *OIDs[ASN1_MAX_OIDS];
542 BOOL got_kerberos_mechanism = False;
546 /* parse out the OIDs and the first sec blob */
547 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
548 /* Kill the intermediate vuid */
549 invalidate_vuid(vuid);
551 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
554 /* only look at the first OID for determining the mechToken --
555 accoirding to RFC2478, we should choose the one we want
556 and renegotiate, but i smell a client bug here..
558 Problem observed when connecting to a member (samba box)
559 of an AD domain as a user in a Samba domain. Samba member
560 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
561 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
562 NTLMSSP mechtoken. --jerry */
565 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
566 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
567 got_kerberos_mechanism = True;
571 for (i=0;OIDs[i];i++) {
572 DEBUG(3,("Got OID %s\n", OIDs[i]));
575 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
578 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
579 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
580 length, bufsize, &secblob);
581 data_blob_free(&secblob);
582 /* Kill the intermediate vuid */
583 invalidate_vuid(vuid);
589 if (*auth_ntlmssp_state) {
590 auth_ntlmssp_end(auth_ntlmssp_state);
593 nt_status = auth_ntlmssp_start(auth_ntlmssp_state);
594 if (!NT_STATUS_IS_OK(nt_status)) {
595 /* Kill the intermediate vuid */
596 invalidate_vuid(vuid);
598 return ERROR_NT(nt_status_squash(nt_status));
601 nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
604 data_blob_free(&secblob);
606 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
607 &chal, nt_status, True);
609 data_blob_free(&chal);
611 /* already replied */
615 /****************************************************************************
616 Reply to a session setup spnego auth packet.
617 ****************************************************************************/
619 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
621 int length, int bufsize,
623 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
625 DATA_BLOB auth, auth_reply;
626 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
628 if (!spnego_parse_auth(blob1, &auth)) {
630 file_save("auth.dat", blob1.data, blob1.length);
632 /* Kill the intermediate vuid */
633 invalidate_vuid(vuid);
635 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
638 if (!*auth_ntlmssp_state) {
639 /* Kill the intermediate vuid */
640 invalidate_vuid(vuid);
642 /* auth before negotiatiate? */
643 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
646 nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
649 data_blob_free(&auth);
651 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
653 &auth_reply, nt_status, True);
655 data_blob_free(&auth_reply);
657 /* and tell smbd that we have already replied to this packet */
661 /****************************************************************************
662 List to store partial SPNEGO auth fragments.
663 ****************************************************************************/
665 static struct pending_auth_data *pd_list;
667 /****************************************************************************
668 Delete an entry on the list.
669 ****************************************************************************/
671 static void delete_partial_auth(struct pending_auth_data *pad)
673 DLIST_REMOVE(pd_list, pad);
674 data_blob_free(&pad->partial_data);
678 /****************************************************************************
679 Search for a partial SPNEGO auth fragment matching an smbpid.
680 ****************************************************************************/
682 static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
684 struct pending_auth_data *pad;
686 for (pad = pd_list; pad; pad = pad->next) {
687 if (pad->smbpid == smbpid) {
694 /****************************************************************************
695 Check the size of an SPNEGO blob. If we need more return NT_STATUS_MORE_PROCESSING_REQUIRED,
696 else return NT_STATUS_OK. Don't allow the blob to be more than 64k.
697 ****************************************************************************/
699 static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB *pblob)
701 struct pending_auth_data *pad;
703 size_t needed_len = 0;
705 /* Ensure we have some data. */
706 if (pblob->length == 0) {
707 /* Caller can cope. */
708 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
709 delete_partial_auth(pad);
713 pad = get_pending_auth_data(smbpid);
715 /* Were we waiting for more data ? */
718 size_t copy_len = MIN(65536, pblob->length);
720 /* Integer wrap paranoia.... */
722 if (pad->partial_data.length + copy_len < pad->partial_data.length ||
723 pad->partial_data.length + copy_len < copy_len) {
725 DEBUG(2,("check_spnego_blob_complete: integer wrap "
726 "pad->partial_data.length = %u, "
728 (unsigned int)pad->partial_data.length,
729 (unsigned int)copy_len ));
731 delete_partial_auth(pad);
732 return NT_STATUS_INVALID_PARAMETER;
735 DEBUG(10,("check_spnego_blob_complete: "
736 "pad->partial_data.length = %u, "
737 "pad->needed_len = %u, "
739 "pblob->length = %u,\n",
740 (unsigned int)pad->partial_data.length,
741 (unsigned int)pad->needed_len,
742 (unsigned int)copy_len,
743 (unsigned int)pblob->length ));
745 tmp_blob = data_blob(NULL,
746 pad->partial_data.length + copy_len);
748 /* Concatenate the two (up to copy_len) bytes. */
749 memcpy(tmp_blob.data,
750 pad->partial_data.data,
751 pad->partial_data.length);
752 memcpy(tmp_blob.data + pad->partial_data.length,
756 /* Replace the partial data. */
757 data_blob_free(&pad->partial_data);
758 pad->partial_data = tmp_blob;
759 ZERO_STRUCT(tmp_blob);
762 if (pblob->length >= pad->needed_len) {
763 /* Yes, replace pblob. */
764 data_blob_free(pblob);
765 *pblob = pad->partial_data;
766 ZERO_STRUCT(pad->partial_data);
767 delete_partial_auth(pad);
771 /* Still need more data. */
772 pad->needed_len -= copy_len;
773 return NT_STATUS_MORE_PROCESSING_REQUIRED;
776 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
777 (pblob->data[0] != ASN1_CONTEXT(1))) {
778 /* Not something we can determine the
784 /* This is a new SPNEGO sessionsetup - see if
785 * the data given in this blob is enough.
788 asn1_load(&data, *pblob);
789 asn1_start_tag(&data, pblob->data[0]);
790 if (data.has_error || data.nesting == NULL) {
792 /* Let caller catch. */
796 /* Integer wrap paranoia.... */
798 if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
799 data.nesting->taglen + data.nesting->start < data.nesting->start) {
801 DEBUG(2,("check_spnego_blob_complete: integer wrap "
802 "data.nesting->taglen = %u, "
803 "data.nesting->start = %u\n",
804 (unsigned int)data.nesting->taglen,
805 (unsigned int)data.nesting->start ));
808 return NT_STATUS_INVALID_PARAMETER;
811 /* Total length of the needed asn1 is the tag length
812 * plus the current offset. */
814 needed_len = data.nesting->taglen + data.nesting->start;
817 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
818 "pblob->length = %u\n",
819 (unsigned int)needed_len,
820 (unsigned int)pblob->length ));
822 if (needed_len <= pblob->length) {
823 /* Nothing to do - blob is complete. */
827 /* Refuse the blob if it's bigger than 64k. */
828 if (needed_len > 65536) {
829 DEBUG(2,("check_spnego_blob_complete: needed_len too large (%u)\n",
830 (unsigned int)needed_len ));
831 return NT_STATUS_INVALID_PARAMETER;
834 /* We must store this blob until complete. */
835 pad = SMB_MALLOC(sizeof(struct pending_auth_data));
837 return NT_STATUS_NO_MEMORY;
839 pad->needed_len = needed_len - pblob->length;
840 pad->partial_data = data_blob(pblob->data, pblob->length);
841 if (pad->partial_data.data == NULL) {
843 return NT_STATUS_NO_MEMORY;
845 pad->smbpid = smbpid;
847 DLIST_ADD(pd_list, pad);
849 return NT_STATUS_MORE_PROCESSING_REQUIRED;
852 /****************************************************************************
853 Reply to a session setup command.
854 conn POINTER CAN BE NULL HERE !
855 ****************************************************************************/
857 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
859 int length,int bufsize)
865 fstring native_os, native_lanman, primary_domain;
867 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
868 enum remote_arch_types ra_type = get_remote_arch();
869 int vuid = SVAL(inbuf,smb_uid);
870 user_struct *vuser = NULL;
871 NTSTATUS status = NT_STATUS_OK;
872 uint16 smbpid = SVAL(inbuf,smb_pid);
874 DEBUG(3,("Doing spnego session setup\n"));
876 if (global_client_caps == 0) {
877 global_client_caps = IVAL(inbuf,smb_vwv10);
879 if (!(global_client_caps & CAP_STATUS32)) {
880 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
885 p = (uint8 *)smb_buf(inbuf);
887 if (data_blob_len == 0) {
888 /* an invalid request */
889 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
892 bufrem = smb_bufrem(inbuf, p);
893 /* pull the spnego blob */
894 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
897 file_save("negotiate.dat", blob1.data, blob1.length);
900 p2 = inbuf + smb_vwv13 + data_blob_len;
901 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
902 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
903 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
904 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
905 native_os, native_lanman, primary_domain));
907 if ( ra_type == RA_WIN2K ) {
908 /* Windows 2003 doesn't set the native lanman string,
909 but does set primary domain which is a bug I think */
911 if ( !strlen(native_lanman) ) {
912 ra_lanman_string( primary_domain );
914 ra_lanman_string( native_lanman );
918 vuser = get_partial_auth_user_struct(vuid);
920 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
922 DEBUG(10,("reply_sesssetup_and_X_spnego: found pending vuid %u\n",
923 (unsigned int)pad->vuid ));
925 vuser = get_partial_auth_user_struct(vuid);
930 vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);
931 if (vuid == UID_FIELD_INVALID ) {
932 data_blob_free(&blob1);
933 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
936 vuser = get_partial_auth_user_struct(vuid);
940 data_blob_free(&blob1);
941 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
944 SSVAL(outbuf,smb_uid,vuid);
946 /* Large (greater than 4k) SPNEGO blobs are split into multiple
947 * sessionsetup requests as the Windows limit on the security blob
948 * field is 4k. Bug #4400. JRA.
951 status = check_spnego_blob_complete(smbpid, vuid, &blob1);
952 if (!NT_STATUS_IS_OK(status)) {
953 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
954 /* Real error - kill the intermediate vuid */
955 invalidate_vuid(vuid);
957 data_blob_free(&blob1);
958 return ERROR_NT(nt_status_squash(status));
961 if (blob1.data[0] == ASN1_APPLICATION(0)) {
962 /* its a negTokenTarg packet */
963 ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
964 &vuser->auth_ntlmssp_state);
965 data_blob_free(&blob1);
969 if (blob1.data[0] == ASN1_CONTEXT(1)) {
970 /* its a auth packet */
971 ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
972 &vuser->auth_ntlmssp_state);
973 data_blob_free(&blob1);
977 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
979 if (!vuser->auth_ntlmssp_state) {
980 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
981 if (!NT_STATUS_IS_OK(status)) {
982 /* Kill the intermediate vuid */
983 invalidate_vuid(vuid);
984 data_blob_free(&blob1);
985 return ERROR_NT(nt_status_squash(status));
989 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
992 data_blob_free(&blob1);
994 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
995 &vuser->auth_ntlmssp_state,
996 &chal, status, False);
997 data_blob_free(&chal);
1001 /* what sort of packet is this? */
1002 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1004 data_blob_free(&blob1);
1006 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1009 /****************************************************************************
1010 On new VC == 0, shutdown *all* old connections and users.
1011 It seems that only NT4.x does this. At W2K and above (XP etc.).
1012 a new session setup with VC==0 is ignored.
1013 ****************************************************************************/
1015 static int shutdown_other_smbds(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
1018 struct sessionid *sessionid = (struct sessionid *)dbuf.dptr;
1019 const char *ip = (const char *)p;
1021 if (!process_exists(pid_to_procid(sessionid->pid))) {
1025 if (sessionid->pid == sys_getpid()) {
1029 if (strcmp(ip, sessionid->ip_addr) != 0) {
1033 message_send_pid(pid_to_procid(sessionid->pid), MSG_SHUTDOWN,
1038 static void setup_new_vc_session(void)
1040 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
1043 invalidate_all_vuids();
1045 if (lp_reset_on_zero_vc()) {
1046 session_traverse(shutdown_other_smbds, client_addr());
1050 /****************************************************************************
1051 Reply to a session setup command.
1052 ****************************************************************************/
1054 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
1055 int length,int bufsize)
1061 DATA_BLOB plaintext_password;
1063 fstring sub_user; /* Sainitised username for substituion */
1066 fstring native_lanman;
1067 fstring primary_domain;
1068 static BOOL done_sesssetup = False;
1069 auth_usersupplied_info *user_info = NULL;
1070 auth_serversupplied_info *server_info = NULL;
1074 BOOL doencrypt = global_encrypted_passwords_negotiated;
1076 DATA_BLOB session_key;
1078 START_PROFILE(SMBsesssetupX);
1080 ZERO_STRUCT(lm_resp);
1081 ZERO_STRUCT(nt_resp);
1082 ZERO_STRUCT(plaintext_password);
1084 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
1086 /* a SPNEGO session setup has 12 command words, whereas a normal
1087 NT1 session setup has 13. See the cifs spec. */
1088 if (CVAL(inbuf, smb_wct) == 12 &&
1089 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
1090 if (!global_spnego_negotiated) {
1091 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
1092 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1095 if (SVAL(inbuf,smb_vwv4) == 0) {
1096 setup_new_vc_session();
1098 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
1101 smb_bufsize = SVAL(inbuf,smb_vwv2);
1103 if (Protocol < PROTOCOL_NT1) {
1104 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
1106 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
1107 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1109 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
1110 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1114 lm_resp = data_blob(smb_buf(inbuf), passlen1);
1116 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
1117 /* Ensure null termination */
1118 plaintext_password.data[passlen1] = 0;
1121 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
1125 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
1126 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
1127 enum remote_arch_types ra_type = get_remote_arch();
1128 char *p = smb_buf(inbuf);
1129 char *save_p = smb_buf(inbuf);
1133 if(global_client_caps == 0) {
1134 global_client_caps = IVAL(inbuf,smb_vwv11);
1136 if (!(global_client_caps & CAP_STATUS32)) {
1137 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1140 /* client_caps is used as final determination if client is NT or Win95.
1141 This is needed to return the correct error codes in some
1145 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
1146 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
1147 set_remote_arch( RA_WIN95);
1153 /* both Win95 and WinNT stuff up the password lengths for
1154 non-encrypting systems. Uggh.
1156 if passlen1==24 its a win95 system, and its setting the
1157 password length incorrectly. Luckily it still works with the
1158 default code because Win95 will null terminate the password
1161 if passlen1>0 and passlen2>0 then maybe its a NT box and its
1162 setting passlen2 to some random value which really stuffs
1163 things up. we need to fix that one. */
1165 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
1169 /* check for nasty tricks */
1170 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
1171 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1174 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
1175 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1178 /* Save the lanman2 password and the NT md4 password. */
1180 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1185 lm_resp = data_blob(p, passlen1);
1186 nt_resp = data_blob(p+passlen1, passlen2);
1189 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
1192 /* This was the previous fix. Not sure if it's still valid. JRA. */
1193 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
1194 /* NT4.0 stuffs up plaintext unicode password lengths... */
1195 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
1196 sizeof(pass), passlen1, STR_TERMINATE);
1199 if (unic && (passlen2 == 0) && passlen1) {
1200 /* Only a ascii plaintext password was sent. */
1201 srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
1202 passlen1, STR_TERMINATE|STR_ASCII);
1204 srvstr_pull(inbuf, pass, smb_buf(inbuf),
1205 sizeof(pass), unic ? passlen2 : passlen1,
1208 plaintext_password = data_blob(pass, strlen(pass)+1);
1211 p += passlen1 + passlen2;
1212 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
1213 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
1214 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
1215 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
1217 /* not documented or decoded by Ethereal but there is one more string
1218 in the extra bytes which is the same as the PrimaryDomain when using
1219 extended security. Windows NT 4 and 2003 use this string to store
1220 the native lanman string. Windows 9x does not include a string here
1221 at all so we have to check if we have any extra bytes left */
1223 byte_count = SVAL(inbuf, smb_vwv13);
1224 if ( PTR_DIFF(p, save_p) < byte_count)
1225 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
1227 fstrcpy( primary_domain, "null" );
1229 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1230 domain, native_os, native_lanman, primary_domain));
1232 if ( ra_type == RA_WIN2K ) {
1233 if ( strlen(native_lanman) == 0 )
1234 ra_lanman_string( primary_domain );
1236 ra_lanman_string( native_lanman );
1241 if (SVAL(inbuf,smb_vwv4) == 0) {
1242 setup_new_vc_session();
1245 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
1248 if (global_spnego_negotiated) {
1250 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
1252 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
1253 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1255 fstrcpy(sub_user, user);
1257 fstrcpy(sub_user, lp_guestaccount());
1260 sub_set_smb_name(sub_user);
1262 reload_services(True);
1264 if (lp_security() == SEC_SHARE) {
1265 /* in share level we should ignore any passwords */
1267 data_blob_free(&lm_resp);
1268 data_blob_free(&nt_resp);
1269 data_blob_clear_free(&plaintext_password);
1271 map_username(sub_user);
1272 add_session_user(sub_user);
1273 add_session_workgroup(domain);
1274 /* Then force it to null for the benfit of the code below */
1280 nt_status = check_guest_password(&server_info);
1282 } else if (doencrypt) {
1283 if (!negprot_global_auth_context) {
1284 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
1285 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1287 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
1289 if (NT_STATUS_IS_OK(nt_status)) {
1290 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
1295 struct auth_context *plaintext_auth_context = NULL;
1298 nt_status = make_auth_context_subsystem(&plaintext_auth_context);
1300 if (NT_STATUS_IS_OK(nt_status)) {
1301 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
1303 if (!make_user_info_for_reply(&user_info,
1305 plaintext_password)) {
1306 nt_status = NT_STATUS_NO_MEMORY;
1309 if (NT_STATUS_IS_OK(nt_status)) {
1310 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
1314 (plaintext_auth_context->free)(&plaintext_auth_context);
1319 free_user_info(&user_info);
1321 if (!NT_STATUS_IS_OK(nt_status)) {
1322 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
1325 if (!NT_STATUS_IS_OK(nt_status)) {
1326 data_blob_free(&nt_resp);
1327 data_blob_free(&lm_resp);
1328 data_blob_clear_free(&plaintext_password);
1329 return ERROR_NT(nt_status_squash(nt_status));
1332 /* Ensure we can't possible take a code path leading to a null defref. */
1334 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1337 nt_status = create_local_token(server_info);
1338 if (!NT_STATUS_IS_OK(nt_status)) {
1339 DEBUG(10, ("create_local_token failed: %s\n",
1340 nt_errstr(nt_status)));
1341 data_blob_free(&nt_resp);
1342 data_blob_free(&lm_resp);
1343 data_blob_clear_free(&plaintext_password);
1344 return ERROR_NT(nt_status_squash(nt_status));
1347 if (server_info->user_session_key.data) {
1348 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
1350 session_key = data_blob(NULL, 0);
1353 data_blob_clear_free(&plaintext_password);
1355 /* it's ok - setup a reply */
1356 set_message(outbuf,3,0,True);
1357 if (Protocol >= PROTOCOL_NT1) {
1358 char *p = smb_buf( outbuf );
1359 p += add_signature( outbuf, p );
1360 set_message_end( outbuf, p );
1361 /* perhaps grab OS version here?? */
1364 if (server_info->guest) {
1365 SSVAL(outbuf,smb_vwv2,1);
1368 /* register the name and uid as being validated, so further connections
1369 to a uid can get through without a password, on the same VC */
1371 if (lp_security() == SEC_SHARE) {
1372 sess_vuid = UID_FIELD_INVALID;
1373 data_blob_free(&session_key);
1374 TALLOC_FREE(server_info);
1376 /* register_vuid keeps the server info */
1377 sess_vuid = register_vuid(server_info, session_key,
1378 nt_resp.data ? nt_resp : lm_resp,
1380 if (sess_vuid == UID_FIELD_INVALID) {
1381 data_blob_free(&nt_resp);
1382 data_blob_free(&lm_resp);
1383 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1386 /* current_user_info is changed on new vuid */
1387 reload_services( True );
1389 sessionsetup_start_signing_engine(server_info, inbuf);
1392 data_blob_free(&nt_resp);
1393 data_blob_free(&lm_resp);
1395 SSVAL(outbuf,smb_uid,sess_vuid);
1396 SSVAL(inbuf,smb_uid,sess_vuid);
1398 if (!done_sesssetup)
1399 max_send = MIN(max_send,smb_bufsize);
1401 done_sesssetup = True;
1403 END_PROFILE(SMBsesssetupX);
1404 return chain_reply(inbuf,outbuf,length,bufsize);