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
)
676 DLIST_REMOVE(pd_list
, pad
);
677 data_blob_free(&pad
->partial_data
);
681 /****************************************************************************
682 Search for a partial SPNEGO auth fragment matching an smbpid.
683 ****************************************************************************/
685 static struct pending_auth_data
*get_pending_auth_data(uint16 smbpid
)
687 struct pending_auth_data
*pad
;
689 for (pad
= pd_list
; pad
; pad
= pad
->next
) {
690 if (pad
->smbpid
== smbpid
) {
697 /****************************************************************************
698 Check the size of an SPNEGO blob. If we need more return NT_STATUS_MORE_PROCESSING_REQUIRED,
699 else return NT_STATUS_OK. Don't allow the blob to be more than 64k.
700 ****************************************************************************/
702 static NTSTATUS
check_spnego_blob_complete(uint16 smbpid
, uint16 vuid
, DATA_BLOB
*pblob
)
704 struct pending_auth_data
*pad
= NULL
;
706 size_t needed_len
= 0;
708 pad
= get_pending_auth_data(smbpid
);
710 /* Ensure we have some data. */
711 if (pblob
->length
== 0) {
712 /* Caller can cope. */
713 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
714 delete_partial_auth(pad
);
718 /* Were we waiting for more data ? */
721 size_t copy_len
= MIN(65536, pblob
->length
);
723 /* Integer wrap paranoia.... */
725 if (pad
->partial_data
.length
+ copy_len
< pad
->partial_data
.length
||
726 pad
->partial_data
.length
+ copy_len
< copy_len
) {
728 DEBUG(2,("check_spnego_blob_complete: integer wrap "
729 "pad->partial_data.length = %u, "
731 (unsigned int)pad
->partial_data
.length
,
732 (unsigned int)copy_len
));
734 delete_partial_auth(pad
);
735 return NT_STATUS_INVALID_PARAMETER
;
738 DEBUG(10,("check_spnego_blob_complete: "
739 "pad->partial_data.length = %u, "
740 "pad->needed_len = %u, "
742 "pblob->length = %u,\n",
743 (unsigned int)pad
->partial_data
.length
,
744 (unsigned int)pad
->needed_len
,
745 (unsigned int)copy_len
,
746 (unsigned int)pblob
->length
));
748 tmp_blob
= data_blob(NULL
,
749 pad
->partial_data
.length
+ copy_len
);
751 /* Concatenate the two (up to copy_len) bytes. */
752 memcpy(tmp_blob
.data
,
753 pad
->partial_data
.data
,
754 pad
->partial_data
.length
);
755 memcpy(tmp_blob
.data
+ pad
->partial_data
.length
,
759 /* Replace the partial data. */
760 data_blob_free(&pad
->partial_data
);
761 pad
->partial_data
= tmp_blob
;
762 ZERO_STRUCT(tmp_blob
);
765 if (pblob
->length
>= pad
->needed_len
) {
766 /* Yes, replace pblob. */
767 data_blob_free(pblob
);
768 *pblob
= pad
->partial_data
;
769 ZERO_STRUCT(pad
->partial_data
);
770 delete_partial_auth(pad
);
774 /* Still need more data. */
775 pad
->needed_len
-= copy_len
;
776 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
779 if ((pblob
->data
[0] != ASN1_APPLICATION(0)) &&
780 (pblob
->data
[0] != ASN1_CONTEXT(1))) {
781 /* Not something we can determine the
787 /* This is a new SPNEGO sessionsetup - see if
788 * the data given in this blob is enough.
791 asn1_load(&data
, *pblob
);
792 asn1_start_tag(&data
, pblob
->data
[0]);
793 if (data
.has_error
|| data
.nesting
== NULL
) {
795 /* Let caller catch. */
799 /* Integer wrap paranoia.... */
801 if (data
.nesting
->taglen
+ data
.nesting
->start
< data
.nesting
->taglen
||
802 data
.nesting
->taglen
+ data
.nesting
->start
< data
.nesting
->start
) {
804 DEBUG(2,("check_spnego_blob_complete: integer wrap "
805 "data.nesting->taglen = %u, "
806 "data.nesting->start = %u\n",
807 (unsigned int)data
.nesting
->taglen
,
808 (unsigned int)data
.nesting
->start
));
811 return NT_STATUS_INVALID_PARAMETER
;
814 /* Total length of the needed asn1 is the tag length
815 * plus the current offset. */
817 needed_len
= data
.nesting
->taglen
+ data
.nesting
->start
;
820 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
821 "pblob->length = %u\n",
822 (unsigned int)needed_len
,
823 (unsigned int)pblob
->length
));
825 if (needed_len
<= pblob
->length
) {
826 /* Nothing to do - blob is complete. */
830 /* Refuse the blob if it's bigger than 64k. */
831 if (needed_len
> 65536) {
832 DEBUG(2,("check_spnego_blob_complete: needed_len too large (%u)\n",
833 (unsigned int)needed_len
));
834 return NT_STATUS_INVALID_PARAMETER
;
837 /* We must store this blob until complete. */
838 pad
= SMB_MALLOC(sizeof(struct pending_auth_data
));
840 return NT_STATUS_NO_MEMORY
;
842 pad
->needed_len
= needed_len
- pblob
->length
;
843 pad
->partial_data
= data_blob(pblob
->data
, pblob
->length
);
844 if (pad
->partial_data
.data
== NULL
) {
846 return NT_STATUS_NO_MEMORY
;
848 pad
->smbpid
= smbpid
;
850 DLIST_ADD(pd_list
, pad
);
852 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
855 /****************************************************************************
856 Reply to a session setup command.
857 conn POINTER CAN BE NULL HERE !
858 ****************************************************************************/
860 static int reply_sesssetup_and_X_spnego(connection_struct
*conn
, char *inbuf
,
862 int length
,int bufsize
)
868 fstring native_os
, native_lanman
, primary_domain
;
870 uint16 data_blob_len
= SVAL(inbuf
, smb_vwv7
);
871 enum remote_arch_types ra_type
= get_remote_arch();
872 int vuid
= SVAL(inbuf
,smb_uid
);
873 user_struct
*vuser
= NULL
;
874 NTSTATUS status
= NT_STATUS_OK
;
875 uint16 smbpid
= SVAL(inbuf
,smb_pid
);
877 DEBUG(3,("Doing spnego session setup\n"));
879 if (global_client_caps
== 0) {
880 global_client_caps
= IVAL(inbuf
,smb_vwv10
);
882 if (!(global_client_caps
& CAP_STATUS32
)) {
883 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
888 p
= (uint8
*)smb_buf(inbuf
);
890 if (data_blob_len
== 0) {
891 /* an invalid request */
892 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE
));
895 bufrem
= smb_bufrem(inbuf
, p
);
896 /* pull the spnego blob */
897 blob1
= data_blob(p
, MIN(bufrem
, data_blob_len
));
900 file_save("negotiate.dat", blob1
.data
, blob1
.length
);
903 p2
= inbuf
+ smb_vwv13
+ data_blob_len
;
904 p2
+= srvstr_pull_buf(inbuf
, native_os
, p2
, sizeof(native_os
), STR_TERMINATE
);
905 p2
+= srvstr_pull_buf(inbuf
, native_lanman
, p2
, sizeof(native_lanman
), STR_TERMINATE
);
906 p2
+= srvstr_pull_buf(inbuf
, primary_domain
, p2
, sizeof(primary_domain
), STR_TERMINATE
);
907 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
908 native_os
, native_lanman
, primary_domain
));
910 if ( ra_type
== RA_WIN2K
) {
911 /* Windows 2003 doesn't set the native lanman string,
912 but does set primary domain which is a bug I think */
914 if ( !strlen(native_lanman
) ) {
915 ra_lanman_string( primary_domain
);
917 ra_lanman_string( native_lanman
);
921 vuser
= get_partial_auth_user_struct(vuid
);
923 struct pending_auth_data
*pad
= get_pending_auth_data(smbpid
);
925 DEBUG(10,("reply_sesssetup_and_X_spnego: found pending vuid %u\n",
926 (unsigned int)pad
->vuid
));
928 vuser
= get_partial_auth_user_struct(vuid
);
933 vuid
= register_vuid(NULL
, data_blob(NULL
, 0), data_blob(NULL
, 0), NULL
);
934 if (vuid
== UID_FIELD_INVALID
) {
935 data_blob_free(&blob1
);
936 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER
));
939 vuser
= get_partial_auth_user_struct(vuid
);
943 data_blob_free(&blob1
);
944 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER
));
947 SSVAL(outbuf
,smb_uid
,vuid
);
949 /* Large (greater than 4k) SPNEGO blobs are split into multiple
950 * sessionsetup requests as the Windows limit on the security blob
951 * field is 4k. Bug #4400. JRA.
954 status
= check_spnego_blob_complete(smbpid
, vuid
, &blob1
);
955 if (!NT_STATUS_IS_OK(status
)) {
956 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
957 /* Real error - kill the intermediate vuid */
958 invalidate_vuid(vuid
);
960 data_blob_free(&blob1
);
961 return ERROR_NT(nt_status_squash(status
));
964 if (blob1
.data
[0] == ASN1_APPLICATION(0)) {
965 /* its a negTokenTarg packet */
966 ret
= reply_spnego_negotiate(conn
, inbuf
, outbuf
, vuid
, length
, bufsize
, blob1
,
967 &vuser
->auth_ntlmssp_state
);
968 data_blob_free(&blob1
);
972 if (blob1
.data
[0] == ASN1_CONTEXT(1)) {
973 /* its a auth packet */
974 ret
= reply_spnego_auth(conn
, inbuf
, outbuf
, vuid
, length
, bufsize
, blob1
,
975 &vuser
->auth_ntlmssp_state
);
976 data_blob_free(&blob1
);
980 if (strncmp((char *)(blob1
.data
), "NTLMSSP", 7) == 0) {
982 if (!vuser
->auth_ntlmssp_state
) {
983 status
= auth_ntlmssp_start(&vuser
->auth_ntlmssp_state
);
984 if (!NT_STATUS_IS_OK(status
)) {
985 /* Kill the intermediate vuid */
986 invalidate_vuid(vuid
);
987 data_blob_free(&blob1
);
988 return ERROR_NT(nt_status_squash(status
));
992 status
= auth_ntlmssp_update(vuser
->auth_ntlmssp_state
,
995 data_blob_free(&blob1
);
997 reply_spnego_ntlmssp(conn
, inbuf
, outbuf
, vuid
,
998 &vuser
->auth_ntlmssp_state
,
999 &chal
, status
, False
);
1000 data_blob_free(&chal
);
1004 /* what sort of packet is this? */
1005 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1007 data_blob_free(&blob1
);
1009 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1012 /****************************************************************************
1013 On new VC == 0, shutdown *all* old connections and users.
1014 It seems that only NT4.x does this. At W2K and above (XP etc.).
1015 a new session setup with VC==0 is ignored.
1016 ****************************************************************************/
1018 static int shutdown_other_smbds(TDB_CONTEXT
*tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
,
1021 struct sessionid
*sessionid
= (struct sessionid
*)dbuf
.dptr
;
1022 const char *ip
= (const char *)p
;
1024 if (!process_exists(pid_to_procid(sessionid
->pid
))) {
1028 if (sessionid
->pid
== sys_getpid()) {
1032 if (strcmp(ip
, sessionid
->ip_addr
) != 0) {
1036 message_send_pid(pid_to_procid(sessionid
->pid
), MSG_SHUTDOWN
,
1041 static void setup_new_vc_session(void)
1043 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
1046 invalidate_all_vuids();
1048 if (lp_reset_on_zero_vc()) {
1049 session_traverse(shutdown_other_smbds
, client_addr());
1053 /****************************************************************************
1054 Reply to a session setup command.
1055 ****************************************************************************/
1057 int reply_sesssetup_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,
1058 int length
,int bufsize
)
1064 DATA_BLOB plaintext_password
;
1066 fstring sub_user
; /* Sainitised username for substituion */
1069 fstring native_lanman
;
1070 fstring primary_domain
;
1071 static BOOL done_sesssetup
= False
;
1072 auth_usersupplied_info
*user_info
= NULL
;
1073 auth_serversupplied_info
*server_info
= NULL
;
1077 BOOL doencrypt
= global_encrypted_passwords_negotiated
;
1079 DATA_BLOB session_key
;
1081 START_PROFILE(SMBsesssetupX
);
1083 ZERO_STRUCT(lm_resp
);
1084 ZERO_STRUCT(nt_resp
);
1085 ZERO_STRUCT(plaintext_password
);
1087 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf
, smb_wct
), SVAL(inbuf
, smb_flg2
)));
1089 /* a SPNEGO session setup has 12 command words, whereas a normal
1090 NT1 session setup has 13. See the cifs spec. */
1091 if (CVAL(inbuf
, smb_wct
) == 12 &&
1092 (SVAL(inbuf
, smb_flg2
) & FLAGS2_EXTENDED_SECURITY
)) {
1093 if (!global_spnego_negotiated
) {
1094 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
1095 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1098 if (SVAL(inbuf
,smb_vwv4
) == 0) {
1099 setup_new_vc_session();
1101 return reply_sesssetup_and_X_spnego(conn
, inbuf
, outbuf
, length
, bufsize
);
1104 smb_bufsize
= SVAL(inbuf
,smb_vwv2
);
1106 if (Protocol
< PROTOCOL_NT1
) {
1107 uint16 passlen1
= SVAL(inbuf
,smb_vwv7
);
1109 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
1110 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
1112 if ((passlen1
> MAX_PASS_LEN
) || (passlen1
> smb_bufrem(inbuf
, smb_buf(inbuf
)))) {
1113 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER
));
1117 lm_resp
= data_blob(smb_buf(inbuf
), passlen1
);
1119 plaintext_password
= data_blob(smb_buf(inbuf
), passlen1
+1);
1120 /* Ensure null termination */
1121 plaintext_password
.data
[passlen1
] = 0;
1124 srvstr_pull_buf(inbuf
, user
, smb_buf(inbuf
)+passlen1
, sizeof(user
), STR_TERMINATE
);
1128 uint16 passlen1
= SVAL(inbuf
,smb_vwv7
);
1129 uint16 passlen2
= SVAL(inbuf
,smb_vwv8
);
1130 enum remote_arch_types ra_type
= get_remote_arch();
1131 char *p
= smb_buf(inbuf
);
1132 char *save_p
= smb_buf(inbuf
);
1136 if(global_client_caps
== 0) {
1137 global_client_caps
= IVAL(inbuf
,smb_vwv11
);
1139 if (!(global_client_caps
& CAP_STATUS32
)) {
1140 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
1143 /* client_caps is used as final determination if client is NT or Win95.
1144 This is needed to return the correct error codes in some
1148 if(ra_type
== RA_WINNT
|| ra_type
== RA_WIN2K
|| ra_type
== RA_WIN95
) {
1149 if(!(global_client_caps
& (CAP_NT_SMBS
| CAP_STATUS32
))) {
1150 set_remote_arch( RA_WIN95
);
1156 /* both Win95 and WinNT stuff up the password lengths for
1157 non-encrypting systems. Uggh.
1159 if passlen1==24 its a win95 system, and its setting the
1160 password length incorrectly. Luckily it still works with the
1161 default code because Win95 will null terminate the password
1164 if passlen1>0 and passlen2>0 then maybe its a NT box and its
1165 setting passlen2 to some random value which really stuffs
1166 things up. we need to fix that one. */
1168 if (passlen1
> 0 && passlen2
> 0 && passlen2
!= 24 && passlen2
!= 1)
1172 /* check for nasty tricks */
1173 if (passlen1
> MAX_PASS_LEN
|| passlen1
> smb_bufrem(inbuf
, p
)) {
1174 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER
));
1177 if (passlen2
> MAX_PASS_LEN
|| passlen2
> smb_bufrem(inbuf
, p
+passlen1
)) {
1178 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER
));
1181 /* Save the lanman2 password and the NT md4 password. */
1183 if ((doencrypt
) && (passlen1
!= 0) && (passlen1
!= 24)) {
1188 lm_resp
= data_blob(p
, passlen1
);
1189 nt_resp
= data_blob(p
+passlen1
, passlen2
);
1192 BOOL unic
=SVAL(inbuf
, smb_flg2
) & FLAGS2_UNICODE_STRINGS
;
1195 /* This was the previous fix. Not sure if it's still valid. JRA. */
1196 if ((ra_type
== RA_WINNT
) && (passlen2
== 0) && unic
&& passlen1
) {
1197 /* NT4.0 stuffs up plaintext unicode password lengths... */
1198 srvstr_pull(inbuf
, pass
, smb_buf(inbuf
) + 1,
1199 sizeof(pass
), passlen1
, STR_TERMINATE
);
1202 if (unic
&& (passlen2
== 0) && passlen1
) {
1203 /* Only a ascii plaintext password was sent. */
1204 srvstr_pull(inbuf
, pass
, smb_buf(inbuf
), sizeof(pass
),
1205 passlen1
, STR_TERMINATE
|STR_ASCII
);
1207 srvstr_pull(inbuf
, pass
, smb_buf(inbuf
),
1208 sizeof(pass
), unic
? passlen2
: passlen1
,
1211 plaintext_password
= data_blob(pass
, strlen(pass
)+1);
1214 p
+= passlen1
+ passlen2
;
1215 p
+= srvstr_pull_buf(inbuf
, user
, p
, sizeof(user
), STR_TERMINATE
);
1216 p
+= srvstr_pull_buf(inbuf
, domain
, p
, sizeof(domain
), STR_TERMINATE
);
1217 p
+= srvstr_pull_buf(inbuf
, native_os
, p
, sizeof(native_os
), STR_TERMINATE
);
1218 p
+= srvstr_pull_buf(inbuf
, native_lanman
, p
, sizeof(native_lanman
), STR_TERMINATE
);
1220 /* not documented or decoded by Ethereal but there is one more string
1221 in the extra bytes which is the same as the PrimaryDomain when using
1222 extended security. Windows NT 4 and 2003 use this string to store
1223 the native lanman string. Windows 9x does not include a string here
1224 at all so we have to check if we have any extra bytes left */
1226 byte_count
= SVAL(inbuf
, smb_vwv13
);
1227 if ( PTR_DIFF(p
, save_p
) < byte_count
)
1228 p
+= srvstr_pull_buf(inbuf
, primary_domain
, p
, sizeof(primary_domain
), STR_TERMINATE
);
1230 fstrcpy( primary_domain
, "null" );
1232 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1233 domain
, native_os
, native_lanman
, primary_domain
));
1235 if ( ra_type
== RA_WIN2K
) {
1236 if ( strlen(native_lanman
) == 0 )
1237 ra_lanman_string( primary_domain
);
1239 ra_lanman_string( native_lanman
);
1244 if (SVAL(inbuf
,smb_vwv4
) == 0) {
1245 setup_new_vc_session();
1248 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain
, user
, get_remote_machine_name()));
1251 if (global_spnego_negotiated
) {
1253 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
1255 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
1256 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1258 fstrcpy(sub_user
, user
);
1260 fstrcpy(sub_user
, lp_guestaccount());
1263 sub_set_smb_name(sub_user
);
1265 reload_services(True
);
1267 if (lp_security() == SEC_SHARE
) {
1268 /* in share level we should ignore any passwords */
1270 data_blob_free(&lm_resp
);
1271 data_blob_free(&nt_resp
);
1272 data_blob_clear_free(&plaintext_password
);
1274 map_username(sub_user
);
1275 add_session_user(sub_user
);
1276 add_session_workgroup(domain
);
1277 /* Then force it to null for the benfit of the code below */
1283 nt_status
= check_guest_password(&server_info
);
1285 } else if (doencrypt
) {
1286 if (!negprot_global_auth_context
) {
1287 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
1288 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1290 nt_status
= make_user_info_for_reply_enc(&user_info
, user
, domain
,
1292 if (NT_STATUS_IS_OK(nt_status
)) {
1293 nt_status
= negprot_global_auth_context
->check_ntlm_password(negprot_global_auth_context
,
1298 struct auth_context
*plaintext_auth_context
= NULL
;
1301 nt_status
= make_auth_context_subsystem(&plaintext_auth_context
);
1303 if (NT_STATUS_IS_OK(nt_status
)) {
1304 chal
= plaintext_auth_context
->get_ntlm_challenge(plaintext_auth_context
);
1306 if (!make_user_info_for_reply(&user_info
,
1308 plaintext_password
)) {
1309 nt_status
= NT_STATUS_NO_MEMORY
;
1312 if (NT_STATUS_IS_OK(nt_status
)) {
1313 nt_status
= plaintext_auth_context
->check_ntlm_password(plaintext_auth_context
,
1317 (plaintext_auth_context
->free
)(&plaintext_auth_context
);
1322 free_user_info(&user_info
);
1324 if (!NT_STATUS_IS_OK(nt_status
)) {
1325 nt_status
= do_map_to_guest(nt_status
, &server_info
, user
, domain
);
1328 if (!NT_STATUS_IS_OK(nt_status
)) {
1329 data_blob_free(&nt_resp
);
1330 data_blob_free(&lm_resp
);
1331 data_blob_clear_free(&plaintext_password
);
1332 return ERROR_NT(nt_status_squash(nt_status
));
1335 /* Ensure we can't possible take a code path leading to a null defref. */
1337 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1340 nt_status
= create_local_token(server_info
);
1341 if (!NT_STATUS_IS_OK(nt_status
)) {
1342 DEBUG(10, ("create_local_token failed: %s\n",
1343 nt_errstr(nt_status
)));
1344 data_blob_free(&nt_resp
);
1345 data_blob_free(&lm_resp
);
1346 data_blob_clear_free(&plaintext_password
);
1347 return ERROR_NT(nt_status_squash(nt_status
));
1350 if (server_info
->user_session_key
.data
) {
1351 session_key
= data_blob(server_info
->user_session_key
.data
, server_info
->user_session_key
.length
);
1353 session_key
= data_blob(NULL
, 0);
1356 data_blob_clear_free(&plaintext_password
);
1358 /* it's ok - setup a reply */
1359 set_message(outbuf
,3,0,True
);
1360 if (Protocol
>= PROTOCOL_NT1
) {
1361 char *p
= smb_buf( outbuf
);
1362 p
+= add_signature( outbuf
, p
);
1363 set_message_end( outbuf
, p
);
1364 /* perhaps grab OS version here?? */
1367 if (server_info
->guest
) {
1368 SSVAL(outbuf
,smb_vwv2
,1);
1371 /* register the name and uid as being validated, so further connections
1372 to a uid can get through without a password, on the same VC */
1374 if (lp_security() == SEC_SHARE
) {
1375 sess_vuid
= UID_FIELD_INVALID
;
1376 data_blob_free(&session_key
);
1377 TALLOC_FREE(server_info
);
1379 /* register_vuid keeps the server info */
1380 sess_vuid
= register_vuid(server_info
, session_key
,
1381 nt_resp
.data
? nt_resp
: lm_resp
,
1383 if (sess_vuid
== UID_FIELD_INVALID
) {
1384 data_blob_free(&nt_resp
);
1385 data_blob_free(&lm_resp
);
1386 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1389 /* current_user_info is changed on new vuid */
1390 reload_services( True
);
1392 sessionsetup_start_signing_engine(server_info
, inbuf
);
1395 data_blob_free(&nt_resp
);
1396 data_blob_free(&lm_resp
);
1398 SSVAL(outbuf
,smb_uid
,sess_vuid
);
1399 SSVAL(inbuf
,smb_uid
,sess_vuid
);
1401 if (!done_sesssetup
)
1402 max_send
= MIN(max_send
,smb_bufsize
);
1404 done_sesssetup
= True
;
1406 END_PROFILE(SMBsesssetupX
);
1407 return chain_reply(inbuf
,outbuf
,length
,bufsize
);