2 Unix SMB/CIFS implementation.
3 client connect/disconnect routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Andrew Bartlett 2001-2003
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 {PROTOCOL_CORE
,"PC NETWORK PROGRAM 1.0"},
32 {PROTOCOL_COREPLUS
,"MICROSOFT NETWORKS 1.03"},
33 {PROTOCOL_LANMAN1
,"MICROSOFT NETWORKS 3.0"},
34 {PROTOCOL_LANMAN1
,"LANMAN1.0"},
35 {PROTOCOL_LANMAN2
,"LM1.2X002"},
36 {PROTOCOL_LANMAN2
,"DOS LANMAN2.1"},
37 {PROTOCOL_LANMAN2
,"Samba"},
38 {PROTOCOL_NT1
,"NT LANMAN 1.0"},
39 {PROTOCOL_NT1
,"NT LM 0.12"},
43 /****************************************************************************
44 Do an old lanman2 style session setup.
45 ****************************************************************************/
47 static BOOL
cli_session_setup_lanman2(struct cli_state
*cli
, const char *user
,
48 const char *pass
, size_t passlen
, const char *workgroup
)
53 if (passlen
> sizeof(pword
)-1)
56 /* LANMAN servers predate NT status codes and Unicode and ignore those
57 smb flags so we must disable the corresponding default capabilities
58 that would otherwise cause the Unicode and NT Status flags to be
59 set (and even returned by the server) */
61 cli
->capabilities
&= ~(CAP_UNICODE
| CAP_STATUS32
);
63 /* if in share level security then don't send a password now */
64 if (!(cli
->sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
))
67 if (passlen
> 0 && (cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) && passlen
!= 24) {
68 /* Encrypted mode needed, and non encrypted password supplied. */
70 SMBencrypt(pass
,cli
->secblob
.data
,(uchar
*)pword
);
71 } else if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) && passlen
== 24) {
72 /* Encrypted mode needed, and encrypted password supplied. */
73 memcpy(pword
, pass
, passlen
);
74 } else if (passlen
> 0) {
75 /* Plaintext mode needed, assume plaintext supplied. */
76 passlen
= clistr_push(cli
, pword
, pass
, sizeof(pword
), STR_TERMINATE
);
79 /* send a session setup command */
80 memset(cli
->outbuf
,'\0',smb_size
);
81 set_message(cli
->outbuf
,10, 0, True
);
82 SCVAL(cli
->outbuf
,smb_com
,SMBsesssetupX
);
83 cli_setup_packet(cli
);
85 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
86 SSVAL(cli
->outbuf
,smb_vwv2
,cli
->max_xmit
);
87 SSVAL(cli
->outbuf
,smb_vwv3
,2);
88 SSVAL(cli
->outbuf
,smb_vwv4
,1);
89 SIVAL(cli
->outbuf
,smb_vwv5
,cli
->sesskey
);
90 SSVAL(cli
->outbuf
,smb_vwv7
,passlen
);
92 p
= smb_buf(cli
->outbuf
);
93 memcpy(p
,pword
,passlen
);
95 p
+= clistr_push(cli
, p
, user
, -1, STR_TERMINATE
|STR_UPPER
);
96 p
+= clistr_push(cli
, p
, workgroup
, -1, STR_TERMINATE
|STR_UPPER
);
97 p
+= clistr_push(cli
, p
, "Unix", -1, STR_TERMINATE
);
98 p
+= clistr_push(cli
, p
, "Samba", -1, STR_TERMINATE
);
99 cli_setup_bcc(cli
, p
);
102 if (!cli_receive_smb(cli
))
105 show_msg(cli
->inbuf
);
107 if (cli_is_error(cli
))
110 /* use the returned vuid from now on */
111 cli
->vuid
= SVAL(cli
->inbuf
,smb_uid
);
112 fstrcpy(cli
->user_name
, user
);
117 /****************************************************************************
118 Work out suitable capabilities to offer the server.
119 ****************************************************************************/
121 static uint32
cli_session_setup_capabilities(struct cli_state
*cli
)
123 uint32 capabilities
= CAP_NT_SMBS
;
125 if (!cli
->force_dos_errors
)
126 capabilities
|= CAP_STATUS32
;
128 if (cli
->use_level_II_oplocks
)
129 capabilities
|= CAP_LEVEL_II_OPLOCKS
;
131 if (cli
->capabilities
& CAP_UNICODE
)
132 capabilities
|= CAP_UNICODE
;
134 if (cli
->capabilities
& CAP_LARGE_FILES
)
135 capabilities
|= CAP_LARGE_FILES
;
140 /****************************************************************************
141 Do a NT1 guest session setup.
142 ****************************************************************************/
144 static BOOL
cli_session_setup_guest(struct cli_state
*cli
)
147 uint32 capabilities
= cli_session_setup_capabilities(cli
);
149 set_message(cli
->outbuf
,13,0,True
);
150 SCVAL(cli
->outbuf
,smb_com
,SMBsesssetupX
);
151 cli_setup_packet(cli
);
153 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
154 SSVAL(cli
->outbuf
,smb_vwv2
,CLI_BUFFER_SIZE
);
155 SSVAL(cli
->outbuf
,smb_vwv3
,2);
156 SSVAL(cli
->outbuf
,smb_vwv4
,cli
->pid
);
157 SIVAL(cli
->outbuf
,smb_vwv5
,cli
->sesskey
);
158 SSVAL(cli
->outbuf
,smb_vwv7
,0);
159 SSVAL(cli
->outbuf
,smb_vwv8
,0);
160 SIVAL(cli
->outbuf
,smb_vwv11
,capabilities
);
161 p
= smb_buf(cli
->outbuf
);
162 p
+= clistr_push(cli
, p
, "", -1, STR_TERMINATE
); /* username */
163 p
+= clistr_push(cli
, p
, "", -1, STR_TERMINATE
); /* workgroup */
164 p
+= clistr_push(cli
, p
, "Unix", -1, STR_TERMINATE
);
165 p
+= clistr_push(cli
, p
, "Samba", -1, STR_TERMINATE
);
166 cli_setup_bcc(cli
, p
);
169 if (!cli_receive_smb(cli
))
172 show_msg(cli
->inbuf
);
174 if (cli_is_error(cli
))
177 cli
->vuid
= SVAL(cli
->inbuf
,smb_uid
);
179 p
= smb_buf(cli
->inbuf
);
180 p
+= clistr_pull(cli
, cli
->server_os
, p
, sizeof(fstring
), -1, STR_TERMINATE
);
181 p
+= clistr_pull(cli
, cli
->server_type
, p
, sizeof(fstring
), -1, STR_TERMINATE
);
182 p
+= clistr_pull(cli
, cli
->server_domain
, p
, sizeof(fstring
), -1, STR_TERMINATE
);
184 fstrcpy(cli
->user_name
, "");
189 /****************************************************************************
190 Do a NT1 plaintext session setup.
191 ****************************************************************************/
193 static BOOL
cli_session_setup_plaintext(struct cli_state
*cli
, const char *user
,
194 const char *pass
, const char *workgroup
)
196 uint32 capabilities
= cli_session_setup_capabilities(cli
);
200 fstr_sprintf( lanman
, "Samba %s", SAMBA_VERSION_STRING
);
202 set_message(cli
->outbuf
,13,0,True
);
203 SCVAL(cli
->outbuf
,smb_com
,SMBsesssetupX
);
204 cli_setup_packet(cli
);
206 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
207 SSVAL(cli
->outbuf
,smb_vwv2
,CLI_BUFFER_SIZE
);
208 SSVAL(cli
->outbuf
,smb_vwv3
,2);
209 SSVAL(cli
->outbuf
,smb_vwv4
,cli
->pid
);
210 SIVAL(cli
->outbuf
,smb_vwv5
,cli
->sesskey
);
211 SSVAL(cli
->outbuf
,smb_vwv8
,0);
212 SIVAL(cli
->outbuf
,smb_vwv11
,capabilities
);
213 p
= smb_buf(cli
->outbuf
);
215 /* check wether to send the ASCII or UNICODE version of the password */
217 if ( (capabilities
& CAP_UNICODE
) == 0 ) {
218 p
+= clistr_push(cli
, p
, pass
, -1, STR_TERMINATE
); /* password */
219 SSVAL(cli
->outbuf
,smb_vwv7
,PTR_DIFF(p
, smb_buf(cli
->outbuf
)));
222 p
+= clistr_push(cli
, p
, pass
, -1, STR_UNICODE
|STR_TERMINATE
); /* unicode password */
223 SSVAL(cli
->outbuf
,smb_vwv8
,PTR_DIFF(p
, smb_buf(cli
->outbuf
)));
226 p
+= clistr_push(cli
, p
, user
, -1, STR_TERMINATE
); /* username */
227 p
+= clistr_push(cli
, p
, workgroup
, -1, STR_TERMINATE
); /* workgroup */
228 p
+= clistr_push(cli
, p
, "Unix", -1, STR_TERMINATE
);
229 p
+= clistr_push(cli
, p
, lanman
, -1, STR_TERMINATE
);
230 cli_setup_bcc(cli
, p
);
233 if (!cli_receive_smb(cli
))
236 show_msg(cli
->inbuf
);
238 if (cli_is_error(cli
))
241 cli
->vuid
= SVAL(cli
->inbuf
,smb_uid
);
242 p
= smb_buf(cli
->inbuf
);
243 p
+= clistr_pull(cli
, cli
->server_os
, p
, sizeof(fstring
), -1, STR_TERMINATE
);
244 p
+= clistr_pull(cli
, cli
->server_type
, p
, sizeof(fstring
), -1, STR_TERMINATE
);
245 p
+= clistr_pull(cli
, cli
->server_domain
, p
, sizeof(fstring
), -1, STR_TERMINATE
);
246 fstrcpy(cli
->user_name
, user
);
252 * Set the user session key for a connection
253 * @param cli The cli structure to add it too
254 * @param session_key The session key used. (A copy of this is taken for the cli struct)
258 static void cli_set_session_key (struct cli_state
*cli
, const DATA_BLOB session_key
)
260 cli
->user_session_key
= data_blob(session_key
.data
, session_key
.length
);
263 /****************************************************************************
264 do a NT1 NTLM/LM encrypted session setup - for when extended security
266 @param cli client state to create do session setup on
268 @param pass *either* cleartext password (passlen !=24) or LM response.
269 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
270 @param workgroup The user's domain.
271 ****************************************************************************/
273 static BOOL
cli_session_setup_nt1(struct cli_state
*cli
, const char *user
,
274 const char *pass
, size_t passlen
,
275 const char *ntpass
, size_t ntpasslen
,
276 const char *workgroup
)
278 uint32 capabilities
= cli_session_setup_capabilities(cli
);
279 DATA_BLOB lm_response
= data_blob(NULL
, 0);
280 DATA_BLOB nt_response
= data_blob(NULL
, 0);
281 DATA_BLOB session_key
= data_blob(NULL
, 0);
286 /* do nothing - guest login */
287 } else if (passlen
!= 24) {
288 if (lp_client_ntlmv2_auth()) {
289 DATA_BLOB server_chal
;
290 DATA_BLOB names_blob
;
291 server_chal
= data_blob(cli
->secblob
.data
, MIN(cli
->secblob
.length
, 8));
293 /* note that the 'workgroup' here is a best guess - we don't know
294 the server's domain at this point. The 'server name' is also
297 names_blob
= NTLMv2_generate_names_blob(cli
->called
.name
, workgroup
);
299 if (!SMBNTLMv2encrypt(user
, workgroup
, pass
, &server_chal
,
301 &lm_response
, &nt_response
, &session_key
)) {
302 data_blob_free(&names_blob
);
303 data_blob_free(&server_chal
);
306 data_blob_free(&names_blob
);
307 data_blob_free(&server_chal
);
311 E_md4hash(pass
, nt_hash
);
313 nt_response
= data_blob(NULL
, 24);
314 SMBNTencrypt(pass
,cli
->secblob
.data
,nt_response
.data
);
316 /* non encrypted password supplied. Ignore ntpass. */
317 if (lp_client_lanman_auth()) {
318 lm_response
= data_blob(NULL
, 24);
319 SMBencrypt(pass
,cli
->secblob
.data
, lm_response
.data
);
321 /* LM disabled, place NT# in LM field instead */
322 lm_response
= data_blob(nt_response
.data
, nt_response
.length
);
325 session_key
= data_blob(NULL
, 16);
326 SMBsesskeygen_ntv1(nt_hash
, NULL
, session_key
.data
);
328 cli_simple_set_signing(cli
, session_key
, nt_response
);
330 /* pre-encrypted password supplied. Only used for
331 security=server, can't do
332 signing because we don't have original key */
334 lm_response
= data_blob(pass
, passlen
);
335 nt_response
= data_blob(ntpass
, ntpasslen
);
338 /* send a session setup command */
339 memset(cli
->outbuf
,'\0',smb_size
);
341 set_message(cli
->outbuf
,13,0,True
);
342 SCVAL(cli
->outbuf
,smb_com
,SMBsesssetupX
);
343 cli_setup_packet(cli
);
345 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
346 SSVAL(cli
->outbuf
,smb_vwv2
,CLI_BUFFER_SIZE
);
347 SSVAL(cli
->outbuf
,smb_vwv3
,2);
348 SSVAL(cli
->outbuf
,smb_vwv4
,cli
->pid
);
349 SIVAL(cli
->outbuf
,smb_vwv5
,cli
->sesskey
);
350 SSVAL(cli
->outbuf
,smb_vwv7
,lm_response
.length
);
351 SSVAL(cli
->outbuf
,smb_vwv8
,nt_response
.length
);
352 SIVAL(cli
->outbuf
,smb_vwv11
,capabilities
);
353 p
= smb_buf(cli
->outbuf
);
354 if (lm_response
.length
) {
355 memcpy(p
,lm_response
.data
, lm_response
.length
); p
+= lm_response
.length
;
357 if (nt_response
.length
) {
358 memcpy(p
,nt_response
.data
, nt_response
.length
); p
+= nt_response
.length
;
360 p
+= clistr_push(cli
, p
, user
, -1, STR_TERMINATE
);
362 /* Upper case here might help some NTLMv2 implementations */
363 p
+= clistr_push(cli
, p
, workgroup
, -1, STR_TERMINATE
|STR_UPPER
);
364 p
+= clistr_push(cli
, p
, "Unix", -1, STR_TERMINATE
);
365 p
+= clistr_push(cli
, p
, "Samba", -1, STR_TERMINATE
);
366 cli_setup_bcc(cli
, p
);
368 if (!cli_send_smb(cli
) || !cli_receive_smb(cli
)) {
373 /* show_msg(cli->inbuf); */
375 if (cli_is_error(cli
)) {
380 /* use the returned vuid from now on */
381 cli
->vuid
= SVAL(cli
->inbuf
,smb_uid
);
383 p
= smb_buf(cli
->inbuf
);
384 p
+= clistr_pull(cli
, cli
->server_os
, p
, sizeof(fstring
), -1, STR_TERMINATE
);
385 p
+= clistr_pull(cli
, cli
->server_type
, p
, sizeof(fstring
), -1, STR_TERMINATE
);
386 p
+= clistr_pull(cli
, cli
->server_domain
, p
, sizeof(fstring
), -1, STR_TERMINATE
);
388 fstrcpy(cli
->user_name
, user
);
390 if (session_key
.data
) {
391 /* Have plaintext orginal */
392 cli_set_session_key(cli
, session_key
);
397 data_blob_free(&lm_response
);
398 data_blob_free(&nt_response
);
401 data_blob_free(&session_key
);
405 /****************************************************************************
406 Send a extended security session setup blob
407 ****************************************************************************/
409 static BOOL
cli_session_setup_blob_send(struct cli_state
*cli
, DATA_BLOB blob
)
411 uint32 capabilities
= cli_session_setup_capabilities(cli
);
414 capabilities
|= CAP_EXTENDED_SECURITY
;
416 /* send a session setup command */
417 memset(cli
->outbuf
,'\0',smb_size
);
419 set_message(cli
->outbuf
,12,0,True
);
420 SCVAL(cli
->outbuf
,smb_com
,SMBsesssetupX
);
422 cli_setup_packet(cli
);
424 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
425 SSVAL(cli
->outbuf
,smb_vwv2
,CLI_BUFFER_SIZE
);
426 SSVAL(cli
->outbuf
,smb_vwv3
,2);
427 SSVAL(cli
->outbuf
,smb_vwv4
,1);
428 SIVAL(cli
->outbuf
,smb_vwv5
,0);
429 SSVAL(cli
->outbuf
,smb_vwv7
,blob
.length
);
430 SIVAL(cli
->outbuf
,smb_vwv10
,capabilities
);
431 p
= smb_buf(cli
->outbuf
);
432 memcpy(p
, blob
.data
, blob
.length
);
434 p
+= clistr_push(cli
, p
, "Unix", -1, STR_TERMINATE
);
435 p
+= clistr_push(cli
, p
, "Samba", -1, STR_TERMINATE
);
436 cli_setup_bcc(cli
, p
);
437 return cli_send_smb(cli
);
440 /****************************************************************************
441 Send a extended security session setup blob, returning a reply blob.
442 ****************************************************************************/
444 static DATA_BLOB
cli_session_setup_blob_receive(struct cli_state
*cli
)
446 DATA_BLOB blob2
= data_blob(NULL
, 0);
450 if (!cli_receive_smb(cli
))
453 show_msg(cli
->inbuf
);
455 if (cli_is_error(cli
) && !NT_STATUS_EQUAL(cli_nt_error(cli
),
456 NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
460 /* use the returned vuid from now on */
461 cli
->vuid
= SVAL(cli
->inbuf
,smb_uid
);
463 p
= smb_buf(cli
->inbuf
);
465 blob2
= data_blob(p
, SVAL(cli
->inbuf
, smb_vwv3
));
468 p
+= clistr_pull(cli
, cli
->server_os
, p
, sizeof(fstring
), -1, STR_TERMINATE
);
470 /* w2k with kerberos doesn't properly null terminate this field */
471 len
= smb_buflen(cli
->inbuf
) - PTR_DIFF(p
, smb_buf(cli
->inbuf
));
472 p
+= clistr_pull(cli
, cli
->server_type
, p
, sizeof(fstring
), len
, 0);
479 /****************************************************************************
480 Send a extended security session setup blob, returning a reply blob.
481 ****************************************************************************/
483 static DATA_BLOB
cli_session_setup_blob(struct cli_state
*cli
, DATA_BLOB blob
)
485 DATA_BLOB blob2
= data_blob(NULL
, 0);
486 if (!cli_session_setup_blob_send(cli
, blob
)) {
490 return cli_session_setup_blob_receive(cli
);
493 /****************************************************************************
494 Use in-memory credentials cache
495 ****************************************************************************/
497 static void use_in_memory_ccache(void) {
498 setenv(KRB5_ENV_CCNAME
, "MEMORY:cliconnect", 1);
501 /****************************************************************************
502 Do a spnego/kerberos encrypted session setup.
503 ****************************************************************************/
505 static ADS_STATUS
cli_session_setup_kerberos(struct cli_state
*cli
, const char *principal
, const char *workgroup
)
507 DATA_BLOB blob2
, negTokenTarg
;
508 DATA_BLOB session_key_krb5
;
509 DATA_BLOB null_blob
= data_blob(NULL
, 0);
512 DEBUG(2,("Doing kerberos session setup\n"));
514 /* generate the encapsulated kerberos5 ticket */
515 rc
= spnego_gen_negTokenTarg(principal
, 0, &negTokenTarg
, &session_key_krb5
);
518 DEBUG(1, ("spnego_gen_negTokenTarg failed: %s\n", error_message(rc
)));
519 return ADS_ERROR_KRB5(rc
);
523 file_save("negTokenTarg.dat", negTokenTarg
.data
, negTokenTarg
.length
);
526 cli_simple_set_signing(cli
, session_key_krb5
, null_blob
);
528 blob2
= cli_session_setup_blob(cli
, negTokenTarg
);
530 /* we don't need this blob for kerberos */
531 data_blob_free(&blob2
);
533 cli_set_session_key(cli
, session_key_krb5
);
535 data_blob_free(&negTokenTarg
);
537 if (cli_is_error(cli
)) {
538 if (NT_STATUS_IS_OK(cli_nt_error(cli
))) {
539 return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL
);
542 return ADS_ERROR_NT(cli_nt_error(cli
));
544 #endif /* HAVE_KRB5 */
547 /****************************************************************************
548 Do a spnego/NTLMSSP encrypted session setup.
549 ****************************************************************************/
551 static NTSTATUS
cli_session_setup_ntlmssp(struct cli_state
*cli
, const char *user
,
552 const char *pass
, const char *domain
)
554 struct ntlmssp_state
*ntlmssp_state
;
559 DATA_BLOB blob_in
= data_blob(NULL
, 0);
562 cli_temp_set_signing(cli
);
564 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_client_start(&ntlmssp_state
))) {
568 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_set_username(ntlmssp_state
, user
))) {
571 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_set_domain(ntlmssp_state
, domain
))) {
574 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_set_password(ntlmssp_state
, pass
))) {
579 nt_status
= ntlmssp_update(ntlmssp_state
,
581 data_blob_free(&blob_in
);
582 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
584 /* and wrap it in a SPNEGO wrapper */
585 msg1
= gen_negTokenInit(OID_NTLMSSP
, blob_out
);
587 /* wrap it in SPNEGO */
588 msg1
= spnego_gen_auth(blob_out
);
591 /* now send that blob on its way */
592 if (!cli_session_setup_blob_send(cli
, msg1
)) {
593 DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
594 nt_status
= NT_STATUS_UNSUCCESSFUL
;
596 data_blob_free(&msg1
);
598 blob
= cli_session_setup_blob_receive(cli
);
600 nt_status
= cli_nt_error(cli
);
601 if (cli_is_error(cli
) && NT_STATUS_IS_OK(nt_status
)) {
602 if (cli
->smb_rw_error
== READ_BAD_SIG
) {
603 nt_status
= NT_STATUS_ACCESS_DENIED
;
605 nt_status
= NT_STATUS_UNSUCCESSFUL
;
612 if (NT_STATUS_IS_OK(nt_status
)) {
613 nt_status
= NT_STATUS_UNSUCCESSFUL
;
615 } else if ((turn
== 1) &&
616 NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
617 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
618 /* the server might give us back two challenges */
619 if (!spnego_parse_challenge(blob
, &blob_in
,
621 DEBUG(3,("Failed to parse challenges\n"));
622 nt_status
= NT_STATUS_INVALID_PARAMETER
;
624 data_blob_free(&tmp_blob
);
626 if (!spnego_parse_auth_response(blob
, nt_status
,
628 DEBUG(3,("Failed to parse auth response\n"));
629 if (NT_STATUS_IS_OK(nt_status
)
630 || NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
))
631 nt_status
= NT_STATUS_INVALID_PARAMETER
;
634 data_blob_free(&blob
);
635 data_blob_free(&blob_out
);
637 } while (NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
));
639 if (NT_STATUS_IS_OK(nt_status
)) {
641 DATA_BLOB key
= data_blob(ntlmssp_state
->session_key
.data
,
642 ntlmssp_state
->session_key
.length
);
643 DATA_BLOB null_blob
= data_blob(NULL
, 0);
645 fstrcpy(cli
->server_domain
, ntlmssp_state
->server_domain
);
646 cli_set_session_key(cli
, ntlmssp_state
->session_key
);
648 if (cli_simple_set_signing(cli
, key
, null_blob
)) {
650 /* 'resign' the last message, so we get the right sequence numbers
651 for checking the first reply from the server */
652 cli_calculate_sign_mac(cli
);
654 if (!cli_check_sign_mac(cli
, True
)) {
655 nt_status
= NT_STATUS_ACCESS_DENIED
;
660 /* we have a reference conter on ntlmssp_state, if we are signing
661 then the state will be kept by the signing engine */
663 ntlmssp_end(&ntlmssp_state
);
668 /****************************************************************************
669 Do a spnego encrypted session setup.
670 ****************************************************************************/
672 ADS_STATUS
cli_session_setup_spnego(struct cli_state
*cli
, const char *user
,
673 const char *pass
, const char *domain
)
676 char *OIDs
[ASN1_MAX_OIDS
];
678 BOOL got_kerberos_mechanism
= False
;
681 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli
->secblob
.length
));
683 /* the server might not even do spnego */
684 if (cli
->secblob
.length
<= 16) {
685 DEBUG(3,("server didn't supply a full spnego negprot\n"));
690 file_save("negprot.dat", cli
->secblob
.data
, cli
->secblob
.length
);
693 /* there is 16 bytes of GUID before the real spnego packet starts */
694 blob
= data_blob(cli
->secblob
.data
+16, cli
->secblob
.length
-16);
696 /* the server sent us the first part of the SPNEGO exchange in the negprot
698 if (!spnego_parse_negTokenInit(blob
, OIDs
, &principal
)) {
699 data_blob_free(&blob
);
700 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
702 data_blob_free(&blob
);
704 /* make sure the server understands kerberos */
705 for (i
=0;OIDs
[i
];i
++) {
706 DEBUG(3,("got OID=%s\n", OIDs
[i
]));
707 if (strcmp(OIDs
[i
], OID_KERBEROS5_OLD
) == 0 ||
708 strcmp(OIDs
[i
], OID_KERBEROS5
) == 0) {
709 got_kerberos_mechanism
= True
;
713 DEBUG(3,("got principal=%s\n", principal
));
715 fstrcpy(cli
->user_name
, user
);
718 /* If password is set we reauthenticate to kerberos server
719 * and do not store results */
721 if (got_kerberos_mechanism
&& cli
->use_kerberos
) {
725 use_in_memory_ccache();
726 ret
= kerberos_kinit_password(user
, pass
, 0 /* no time correction for now */, NULL
);
729 DEBUG(0, ("Kinit failed: %s\n", error_message(ret
)));
730 return ADS_ERROR_KRB5(ret
);
734 return cli_session_setup_kerberos(cli
, principal
, domain
);
742 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli
, user
, pass
, domain
));
745 /****************************************************************************
746 Send a session setup. The username and workgroup is in UNIX character
747 format and must be converted to DOS codepage format before sending. If the
748 password is in plaintext, the same should be done.
749 ****************************************************************************/
751 BOOL
cli_session_setup(struct cli_state
*cli
,
753 const char *pass
, int passlen
,
754 const char *ntpass
, int ntpasslen
,
755 const char *workgroup
)
760 /* allow for workgroups as part of the username */
761 fstrcpy(user2
, user
);
762 if ((p
=strchr_m(user2
,'\\')) || (p
=strchr_m(user2
,'/')) ||
763 (p
=strchr_m(user2
,*lp_winbind_separator()))) {
769 if (cli
->protocol
< PROTOCOL_LANMAN1
)
772 /* now work out what sort of session setup we are going to
773 do. I have split this into separate functions to make the
774 flow a bit easier to understand (tridge) */
776 /* if its an older server then we have to use the older request format */
778 if (cli
->protocol
< PROTOCOL_NT1
) {
779 if (!lp_client_lanman_auth() && passlen
!= 24 && (*pass
)) {
780 DEBUG(1, ("Server requested LM password but 'client lanman auth'"
785 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) == 0 &&
786 !lp_client_plaintext_auth() && (*pass
)) {
787 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
792 return cli_session_setup_lanman2(cli
, user
, pass
, passlen
, workgroup
);
795 /* if no user is supplied then we have to do an anonymous connection.
796 passwords are ignored */
799 return cli_session_setup_guest(cli
);
801 /* if the server is share level then send a plaintext null
802 password at this point. The password is sent in the tree
805 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
) == 0)
806 return cli_session_setup_plaintext(cli
, user
, "", workgroup
);
808 /* if the server doesn't support encryption then we have to use
809 plaintext. The second password is ignored */
811 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) == 0) {
812 if (!lp_client_plaintext_auth() && (*pass
)) {
813 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
817 return cli_session_setup_plaintext(cli
, user
, pass
, workgroup
);
820 /* if the server supports extended security then use SPNEGO */
822 if (cli
->capabilities
& CAP_EXTENDED_SECURITY
) {
823 ADS_STATUS status
= cli_session_setup_spnego(cli
, user
, pass
, workgroup
);
824 if (!ADS_ERR_OK(status
)) {
825 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status
)));
831 /* otherwise do a NT1 style session setup */
833 return cli_session_setup_nt1(cli
, user
,
834 pass
, passlen
, ntpass
, ntpasslen
,
838 /****************************************************************************
840 *****************************************************************************/
842 BOOL
cli_ulogoff(struct cli_state
*cli
)
844 memset(cli
->outbuf
,'\0',smb_size
);
845 set_message(cli
->outbuf
,2,0,True
);
846 SCVAL(cli
->outbuf
,smb_com
,SMBulogoffX
);
847 cli_setup_packet(cli
);
848 SSVAL(cli
->outbuf
,smb_vwv0
,0xFF);
849 SSVAL(cli
->outbuf
,smb_vwv2
,0); /* no additional info */
852 if (!cli_receive_smb(cli
))
855 return !cli_is_error(cli
);
858 /****************************************************************************
860 ****************************************************************************/
861 BOOL
cli_send_tconX(struct cli_state
*cli
,
862 const char *share
, const char *dev
, const char *pass
, int passlen
)
864 fstring fullshare
, pword
;
866 memset(cli
->outbuf
,'\0',smb_size
);
867 memset(cli
->inbuf
,'\0',smb_size
);
869 fstrcpy(cli
->share
, share
);
871 /* in user level security don't send a password now */
872 if (cli
->sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
) {
877 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) && *pass
&& passlen
!= 24) {
878 if (!lp_client_lanman_auth()) {
879 DEBUG(1, ("Server requested LANMAN password (share-level security) but 'client use lanman auth'"
885 * Non-encrypted passwords - convert to DOS codepage before encryption.
888 SMBencrypt(pass
,cli
->secblob
.data
,(uchar
*)pword
);
890 if((cli
->sec_mode
& (NEGOTIATE_SECURITY_USER_LEVEL
|NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
)) == 0) {
891 if (!lp_client_plaintext_auth() && (*pass
)) {
892 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
898 * Non-encrypted passwords - convert to DOS codepage before using.
900 passlen
= clistr_push(cli
, pword
, pass
, sizeof(pword
), STR_TERMINATE
);
903 memcpy(pword
, pass
, passlen
);
907 slprintf(fullshare
, sizeof(fullshare
)-1,
908 "\\\\%s\\%s", cli
->desthost
, share
);
910 set_message(cli
->outbuf
,4, 0, True
);
911 SCVAL(cli
->outbuf
,smb_com
,SMBtconX
);
912 cli_setup_packet(cli
);
914 SSVAL(cli
->outbuf
,smb_vwv0
,0xFF);
915 SSVAL(cli
->outbuf
,smb_vwv3
,passlen
);
917 p
= smb_buf(cli
->outbuf
);
918 memcpy(p
,pword
,passlen
);
920 p
+= clistr_push(cli
, p
, fullshare
, -1, STR_TERMINATE
|STR_UPPER
);
921 p
+= clistr_push(cli
, p
, dev
, -1, STR_TERMINATE
|STR_UPPER
| STR_ASCII
);
923 cli_setup_bcc(cli
, p
);
926 if (!cli_receive_smb(cli
))
929 if (cli_is_error(cli
))
932 clistr_pull(cli
, cli
->dev
, smb_buf(cli
->inbuf
), sizeof(fstring
), -1, STR_TERMINATE
|STR_ASCII
);
934 if (cli
->protocol
>= PROTOCOL_NT1
&&
935 smb_buflen(cli
->inbuf
) == 3) {
936 /* almost certainly win95 - enable bug fixes */
940 cli
->cnum
= SVAL(cli
->inbuf
,smb_tid
);
944 /****************************************************************************
945 Send a tree disconnect.
946 ****************************************************************************/
948 BOOL
cli_tdis(struct cli_state
*cli
)
950 memset(cli
->outbuf
,'\0',smb_size
);
951 set_message(cli
->outbuf
,0,0,True
);
952 SCVAL(cli
->outbuf
,smb_com
,SMBtdis
);
953 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
954 cli_setup_packet(cli
);
957 if (!cli_receive_smb(cli
))
960 return !cli_is_error(cli
);
963 /****************************************************************************
964 Send a negprot command.
965 ****************************************************************************/
967 void cli_negprot_send(struct cli_state
*cli
)
972 if (cli
->protocol
< PROTOCOL_NT1
)
973 cli
->use_spnego
= False
;
975 memset(cli
->outbuf
,'\0',smb_size
);
977 /* setup the protocol strings */
978 set_message(cli
->outbuf
,0,0,True
);
980 p
= smb_buf(cli
->outbuf
);
982 prots
[numprots
].name
&& prots
[numprots
].prot
<=cli
->protocol
;
985 p
+= clistr_push(cli
, p
, prots
[numprots
].name
, -1, STR_TERMINATE
);
988 SCVAL(cli
->outbuf
,smb_com
,SMBnegprot
);
989 cli_setup_bcc(cli
, p
);
990 cli_setup_packet(cli
);
992 SCVAL(smb_buf(cli
->outbuf
),0,2);
997 /****************************************************************************
998 Send a negprot command.
999 ****************************************************************************/
1001 BOOL
cli_negprot(struct cli_state
*cli
)
1007 if (cli
->protocol
< PROTOCOL_NT1
)
1008 cli
->use_spnego
= False
;
1010 memset(cli
->outbuf
,'\0',smb_size
);
1012 /* setup the protocol strings */
1013 for (plength
=0,numprots
=0;
1014 prots
[numprots
].name
&& prots
[numprots
].prot
<=cli
->protocol
;
1016 plength
+= strlen(prots
[numprots
].name
)+2;
1018 set_message(cli
->outbuf
,0,plength
,True
);
1020 p
= smb_buf(cli
->outbuf
);
1022 prots
[numprots
].name
&& prots
[numprots
].prot
<=cli
->protocol
;
1025 p
+= clistr_push(cli
, p
, prots
[numprots
].name
, -1, STR_TERMINATE
);
1028 SCVAL(cli
->outbuf
,smb_com
,SMBnegprot
);
1029 cli_setup_packet(cli
);
1031 SCVAL(smb_buf(cli
->outbuf
),0,2);
1034 if (!cli_receive_smb(cli
))
1037 show_msg(cli
->inbuf
);
1039 if (cli_is_error(cli
) ||
1040 ((int)SVAL(cli
->inbuf
,smb_vwv0
) >= numprots
)) {
1044 cli
->protocol
= prots
[SVAL(cli
->inbuf
,smb_vwv0
)].prot
;
1046 if ((cli
->protocol
< PROTOCOL_NT1
) && cli
->sign_info
.mandatory_signing
) {
1047 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1051 if (cli
->protocol
>= PROTOCOL_NT1
) {
1053 cli
->sec_mode
= CVAL(cli
->inbuf
,smb_vwv1
);
1054 cli
->max_mux
= SVAL(cli
->inbuf
, smb_vwv1
+1);
1055 cli
->max_xmit
= IVAL(cli
->inbuf
,smb_vwv3
+1);
1056 cli
->sesskey
= IVAL(cli
->inbuf
,smb_vwv7
+1);
1057 cli
->serverzone
= SVALS(cli
->inbuf
,smb_vwv15
+1);
1058 cli
->serverzone
*= 60;
1059 /* this time arrives in real GMT */
1060 cli
->servertime
= interpret_long_date(cli
->inbuf
+smb_vwv11
+1);
1061 cli
->secblob
= data_blob(smb_buf(cli
->inbuf
),smb_buflen(cli
->inbuf
));
1062 cli
->capabilities
= IVAL(cli
->inbuf
,smb_vwv9
+1);
1063 if (cli
->capabilities
& CAP_RAW_MODE
) {
1064 cli
->readbraw_supported
= True
;
1065 cli
->writebraw_supported
= True
;
1067 /* work out if they sent us a workgroup */
1068 if (!(cli
->capabilities
& CAP_EXTENDED_SECURITY
) &&
1069 smb_buflen(cli
->inbuf
) > 8) {
1070 clistr_pull(cli
, cli
->server_domain
,
1071 smb_buf(cli
->inbuf
)+8, sizeof(cli
->server_domain
),
1072 smb_buflen(cli
->inbuf
)-8, STR_UNICODE
|STR_NOALIGN
);
1076 * As signing is slow we only turn it on if either the client or
1077 * the server require it. JRA.
1080 if (cli
->sec_mode
& NEGOTIATE_SECURITY_SIGNATURES_REQUIRED
) {
1081 /* Fail if server says signing is mandatory and we don't want to support it. */
1082 if (!cli
->sign_info
.allow_smb_signing
) {
1083 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1086 cli
->sign_info
.negotiated_smb_signing
= True
;
1087 cli
->sign_info
.mandatory_signing
= True
;
1088 } else if (cli
->sign_info
.mandatory_signing
&& cli
->sign_info
.allow_smb_signing
) {
1089 /* Fail if client says signing is mandatory and the server doesn't support it. */
1090 if (!(cli
->sec_mode
& NEGOTIATE_SECURITY_SIGNATURES_ENABLED
)) {
1091 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1094 cli
->sign_info
.negotiated_smb_signing
= True
;
1095 cli
->sign_info
.mandatory_signing
= True
;
1096 } else if (cli
->sec_mode
& NEGOTIATE_SECURITY_SIGNATURES_ENABLED
) {
1097 cli
->sign_info
.negotiated_smb_signing
= True
;
1100 } else if (cli
->protocol
>= PROTOCOL_LANMAN1
) {
1101 cli
->use_spnego
= False
;
1102 cli
->sec_mode
= SVAL(cli
->inbuf
,smb_vwv1
);
1103 cli
->max_xmit
= SVAL(cli
->inbuf
,smb_vwv2
);
1104 cli
->sesskey
= IVAL(cli
->inbuf
,smb_vwv6
);
1105 cli
->serverzone
= SVALS(cli
->inbuf
,smb_vwv10
);
1106 cli
->serverzone
*= 60;
1107 /* this time is converted to GMT by make_unix_date */
1108 cli
->servertime
= make_unix_date(cli
->inbuf
+smb_vwv8
);
1109 cli
->readbraw_supported
= ((SVAL(cli
->inbuf
,smb_vwv5
) & 0x1) != 0);
1110 cli
->writebraw_supported
= ((SVAL(cli
->inbuf
,smb_vwv5
) & 0x2) != 0);
1111 cli
->secblob
= data_blob(smb_buf(cli
->inbuf
),smb_buflen(cli
->inbuf
));
1113 /* the old core protocol */
1114 cli
->use_spnego
= False
;
1116 cli
->serverzone
= TimeDiff(time(NULL
));
1119 cli
->max_xmit
= MIN(cli
->max_xmit
, CLI_BUFFER_SIZE
);
1121 /* a way to force ascii SMB */
1122 if (getenv("CLI_FORCE_ASCII"))
1123 cli
->capabilities
&= ~CAP_UNICODE
;
1128 /****************************************************************************
1129 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1130 ****************************************************************************/
1132 BOOL
cli_session_request(struct cli_state
*cli
,
1133 struct nmb_name
*calling
, struct nmb_name
*called
)
1137 extern pstring user_socket_options
;
1139 memcpy(&(cli
->calling
), calling
, sizeof(*calling
));
1140 memcpy(&(cli
->called
), called
, sizeof(*called
));
1142 /* put in the destination name */
1143 p
= cli
->outbuf
+len
;
1144 name_mangle(cli
->called
.name
, p
, cli
->called
.name_type
);
1148 p
= cli
->outbuf
+len
;
1149 name_mangle(cli
->calling
.name
, p
, cli
->calling
.name_type
);
1152 /* 445 doesn't have session request */
1153 if (cli
->port
== 445)
1156 /* send a session request (RFC 1002) */
1157 /* setup the packet length
1158 * Remove four bytes from the length count, since the length
1159 * field in the NBT Session Service header counts the number
1160 * of bytes which follow. The cli_send_smb() function knows
1161 * about this and accounts for those four bytes.
1165 _smb_setlen(cli
->outbuf
,len
);
1166 SCVAL(cli
->outbuf
,0,0x81);
1169 DEBUG(5,("Sent session request\n"));
1171 if (!cli_receive_smb(cli
))
1174 if (CVAL(cli
->inbuf
,0) == 0x84) {
1175 /* C. Hoch 9/14/95 Start */
1176 /* For information, here is the response structure.
1177 * We do the byte-twiddling to for portability.
1178 struct RetargetResponse{
1180 unsigned char flags;
1186 int port
= (CVAL(cli
->inbuf
,8)<<8)+CVAL(cli
->inbuf
,9);
1187 /* SESSION RETARGET */
1188 putip((char *)&cli
->dest_ip
,cli
->inbuf
+4);
1190 cli
->fd
= open_socket_out(SOCK_STREAM
, &cli
->dest_ip
, port
, LONG_CONNECT_TIMEOUT
);
1194 DEBUG(3,("Retargeted\n"));
1196 set_socket_options(cli
->fd
,user_socket_options
);
1203 DEBUG(0,("Retarget recursion - failing\n"));
1207 ret
= cli_session_request(cli
, calling
, called
);
1211 } /* C. Hoch 9/14/95 End */
1213 if (CVAL(cli
->inbuf
,0) != 0x82) {
1214 /* This is the wrong place to put the error... JRA. */
1215 cli
->rap_error
= CVAL(cli
->inbuf
,4);
1221 /****************************************************************************
1222 Open the client sockets.
1223 ****************************************************************************/
1225 BOOL
cli_connect(struct cli_state
*cli
, const char *host
, struct in_addr
*ip
)
1227 extern pstring user_socket_options
;
1228 int name_type
= 0x20;
1231 /* reasonable default hostname */
1232 if (!host
) host
= "*SMBSERVER";
1234 fstrcpy(cli
->desthost
, host
);
1236 /* allow hostnames of the form NAME#xx and do a netbios lookup */
1237 if ((p
= strchr(cli
->desthost
, '#'))) {
1238 name_type
= strtol(p
+1, NULL
, 16);
1242 if (!ip
|| is_zero_ip(*ip
)) {
1243 if (!resolve_name(cli
->desthost
, &cli
->dest_ip
, name_type
)) {
1246 if (ip
) *ip
= cli
->dest_ip
;
1251 if (getenv("LIBSMB_PROG")) {
1252 cli
->fd
= sock_exec(getenv("LIBSMB_PROG"));
1254 /* try 445 first, then 139 */
1255 int port
= cli
->port
?cli
->port
:445;
1256 cli
->fd
= open_socket_out(SOCK_STREAM
, &cli
->dest_ip
,
1257 port
, cli
->timeout
);
1258 if (cli
->fd
== -1 && cli
->port
== 0) {
1260 cli
->fd
= open_socket_out(SOCK_STREAM
, &cli
->dest_ip
,
1261 port
, cli
->timeout
);
1266 if (cli
->fd
== -1) {
1267 DEBUG(1,("Error connecting to %s (%s)\n",
1268 ip
?inet_ntoa(*ip
):host
,strerror(errno
)));
1272 set_socket_options(cli
->fd
,user_socket_options
);
1277 /****************************************************************************
1278 Initialise client credentials for authenticated pipe access.
1279 ****************************************************************************/
1281 void init_creds(struct ntuser_creds
*creds
, const char* username
,
1282 const char* domain
, const char* password
)
1284 ZERO_STRUCTP(creds
);
1286 pwd_set_cleartext(&creds
->pwd
, password
);
1288 fstrcpy(creds
->user_name
, username
);
1289 fstrcpy(creds
->domain
, domain
);
1292 creds
->pwd
.null_pwd
= True
;
1297 establishes a connection to after the negprot.
1298 @param output_cli A fully initialised cli structure, non-null only on success
1299 @param dest_host The netbios name of the remote host
1300 @param dest_ip (optional) The the destination IP, NULL for name based lookup
1301 @param port (optional) The destination port (0 for default)
1302 @param retry BOOL. Did this connection fail with a retryable error ?
1305 NTSTATUS
cli_start_connection(struct cli_state
**output_cli
,
1306 const char *my_name
,
1307 const char *dest_host
,
1308 struct in_addr
*dest_ip
, int port
,
1309 int signing_state
, int flags
,
1313 struct nmb_name calling
;
1314 struct nmb_name called
;
1315 struct cli_state
*cli
;
1322 my_name
= global_myname();
1324 if (!(cli
= cli_initialise(NULL
)))
1325 return NT_STATUS_NO_MEMORY
;
1327 make_nmb_name(&calling
, my_name
, 0x0);
1328 make_nmb_name(&called
, dest_host
, 0x20);
1330 if (cli_set_port(cli
, port
) != port
) {
1332 return NT_STATUS_UNSUCCESSFUL
;
1335 cli_set_timeout(cli
, 10000); /* 10 seconds. */
1344 DEBUG(3,("Connecting to host=%s\n", dest_host
));
1346 if (!cli_connect(cli
, dest_host
, &ip
)) {
1347 DEBUG(1,("cli_full_connection: failed to connect to %s (%s)\n",
1348 nmb_namestr(&called
), inet_ntoa(ip
)));
1350 return NT_STATUS_UNSUCCESSFUL
;
1356 if (!cli_session_request(cli
, &calling
, &called
)) {
1358 DEBUG(1,("session request to %s failed (%s)\n",
1359 called
.name
, cli_errstr(cli
)));
1360 if ((p
=strchr(called
.name
, '.')) && !is_ipaddress(called
.name
)) {
1364 if (strcmp(called
.name
, "*SMBSERVER")) {
1365 make_nmb_name(&called
, "*SMBSERVER", 0x20);
1368 return NT_STATUS_UNSUCCESSFUL
;
1371 cli_setup_signing_state(cli
, signing_state
);
1373 if (flags
& CLI_FULL_CONNECTION_DONT_SPNEGO
)
1374 cli
->use_spnego
= False
;
1375 else if (flags
& CLI_FULL_CONNECTION_USE_KERBEROS
)
1376 cli
->use_kerberos
= True
;
1378 if (!cli_negprot(cli
)) {
1379 DEBUG(1,("failed negprot\n"));
1380 nt_status
= NT_STATUS_UNSUCCESSFUL
;
1386 return NT_STATUS_OK
;
1391 establishes a connection right up to doing tconX, password specified.
1392 @param output_cli A fully initialised cli structure, non-null only on success
1393 @param dest_host The netbios name of the remote host
1394 @param dest_ip (optional) The the destination IP, NULL for name based lookup
1395 @param port (optional) The destination port (0 for default)
1396 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
1397 @param service_type The 'type' of serivice.
1398 @param user Username, unix string
1399 @param domain User's domain
1400 @param password User's password, unencrypted unix string.
1401 @param retry BOOL. Did this connection fail with a retryable error ?
1404 NTSTATUS
cli_full_connection(struct cli_state
**output_cli
,
1405 const char *my_name
,
1406 const char *dest_host
,
1407 struct in_addr
*dest_ip
, int port
,
1408 const char *service
, const char *service_type
,
1409 const char *user
, const char *domain
,
1410 const char *password
, int flags
,
1414 struct ntuser_creds creds
;
1416 struct cli_state
*cli
= NULL
;
1418 nt_status
= cli_start_connection(&cli
, my_name
, dest_host
,
1419 dest_ip
, port
, signing_state
, flags
, retry
);
1421 if (!NT_STATUS_IS_OK(nt_status
)) {
1425 if (!cli_session_setup(cli
, user
, password
, strlen(password
)+1,
1426 password
, strlen(password
)+1,
1428 if ((flags
& CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK
)
1429 && cli_session_setup(cli
, "", "", 0, "", 0, domain
)) {
1431 nt_status
= cli_nt_error(cli
);
1432 DEBUG(1,("failed session setup with %s\n", nt_errstr(nt_status
)));
1434 if (NT_STATUS_IS_OK(nt_status
))
1435 nt_status
= NT_STATUS_UNSUCCESSFUL
;
1441 if (!cli_send_tconX(cli
, service
, service_type
,
1442 password
, strlen(password
)+1)) {
1443 nt_status
= cli_nt_error(cli
);
1444 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status
)));
1446 if (NT_STATUS_IS_OK(nt_status
)) {
1447 nt_status
= NT_STATUS_UNSUCCESSFUL
;
1453 init_creds(&creds
, user
, domain
, password
);
1454 cli_init_creds(cli
, &creds
);
1457 return NT_STATUS_OK
;
1460 /****************************************************************************
1461 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
1462 ****************************************************************************/
1464 BOOL
attempt_netbios_session_request(struct cli_state
*cli
, const char *srchost
, const char *desthost
,
1465 struct in_addr
*pdest_ip
)
1467 struct nmb_name calling
, called
;
1469 make_nmb_name(&calling
, srchost
, 0x0);
1472 * If the called name is an IP address
1473 * then use *SMBSERVER immediately.
1476 if(is_ipaddress(desthost
))
1477 make_nmb_name(&called
, "*SMBSERVER", 0x20);
1479 make_nmb_name(&called
, desthost
, 0x20);
1481 if (!cli_session_request(cli
, &calling
, &called
)) {
1482 struct nmb_name smbservername
;
1484 make_nmb_name(&smbservername
, "*SMBSERVER", 0x20);
1487 * If the name wasn't *SMBSERVER then
1488 * try with *SMBSERVER if the first name fails.
1491 if (nmb_name_equal(&called
, &smbservername
)) {
1494 * The name used was *SMBSERVER, don't bother with another name.
1497 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
1498 with error %s.\n", desthost
, cli_errstr(cli
) ));
1503 * We need to close the connection here but can't call cli_shutdown as
1504 * will free an allocated cli struct. cli_close_connection was invented
1505 * for this purpose. JRA. Based on work by "Kim R. Pedersen" <krp@filanet.dk>.
1508 cli_close_connection(cli
);
1510 if (!cli_initialise(cli
) ||
1511 !cli_connect(cli
, desthost
, pdest_ip
) ||
1512 !cli_session_request(cli
, &calling
, &smbservername
)) {
1513 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
1514 name *SMBSERVER with error %s\n", desthost
, cli_errstr(cli
) ));
1526 /****************************************************************************
1527 Send an old style tcon.
1528 ****************************************************************************/
1529 NTSTATUS
cli_raw_tcon(struct cli_state
*cli
,
1530 const char *service
, const char *pass
, const char *dev
,
1531 uint16
*max_xmit
, uint16
*tid
)
1535 if (!lp_client_plaintext_auth() && (*pass
)) {
1536 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
1538 return NT_STATUS_ACCESS_DENIED
;
1541 memset(cli
->outbuf
,'\0',smb_size
);
1542 memset(cli
->inbuf
,'\0',smb_size
);
1544 set_message(cli
->outbuf
, 0, 0, True
);
1545 SCVAL(cli
->outbuf
,smb_com
,SMBtcon
);
1546 cli_setup_packet(cli
);
1548 p
= smb_buf(cli
->outbuf
);
1549 *p
++ = 4; p
+= clistr_push(cli
, p
, service
, -1, STR_TERMINATE
| STR_NOALIGN
);
1550 *p
++ = 4; p
+= clistr_push(cli
, p
, pass
, -1, STR_TERMINATE
| STR_NOALIGN
);
1551 *p
++ = 4; p
+= clistr_push(cli
, p
, dev
, -1, STR_TERMINATE
| STR_NOALIGN
);
1553 cli_setup_bcc(cli
, p
);
1556 if (!cli_receive_smb(cli
)) {
1557 return NT_STATUS_UNEXPECTED_NETWORK_ERROR
;
1560 if (cli_is_error(cli
)) {
1561 return cli_nt_error(cli
);
1564 *max_xmit
= SVAL(cli
->inbuf
, smb_vwv0
);
1565 *tid
= SVAL(cli
->inbuf
, smb_vwv1
);
1567 return NT_STATUS_OK
;
1570 /* Return a cli_state pointing at the IPC$ share for the given server */
1572 struct cli_state
*get_ipc_connect(char *server
, struct in_addr
*server_ip
,
1573 struct user_auth_info
*user_info
)
1575 struct cli_state
*cli
;
1581 nt_status
= cli_full_connection(&cli
, myname
, server
, server_ip
, 0, "IPC$", "IPC",
1582 user_info
->username
, lp_workgroup(), user_info
->password
,
1583 CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK
, Undefined
, NULL
);
1585 if (NT_STATUS_IS_OK(nt_status
)) {
1587 } else if (is_ipaddress(server
)) {
1588 /* windows 9* needs a correct NMB name for connections */
1589 fstring remote_name
;
1591 if (name_status_find("*", 0, 0, *server_ip
, remote_name
)) {
1592 cli
= get_ipc_connect(remote_name
, server_ip
, user_info
);
1601 * Given the IP address of a master browser on the network, return its
1602 * workgroup and connect to it.
1604 * This function is provided to allow additional processing beyond what
1605 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
1606 * browsers and obtain each master browsers' list of domains (in case the
1607 * first master browser is recently on the network and has not yet
1608 * synchronized with other master browsers and therefore does not yet have the
1609 * entire network browse list)
1612 struct cli_state
*get_ipc_connect_master_ip(struct ip_service
* mb_ip
, pstring workgroup
, struct user_auth_info
*user_info
)
1614 static fstring name
;
1615 struct cli_state
*cli
;
1616 struct in_addr server_ip
;
1618 DEBUG(99, ("Looking up name of master browser %s\n",
1619 inet_ntoa(mb_ip
->ip
)));
1622 * Do a name status query to find out the name of the master browser.
1623 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
1624 * master browser will not respond to a wildcard query (or, at least,
1625 * an NT4 server acting as the domain master browser will not).
1627 * We might be able to use ONLY the query on MSBROWSE, but that's not
1628 * yet been tested with all Windows versions, so until it is, leave
1629 * the original wildcard query as the first choice and fall back to
1630 * MSBROWSE if the wildcard query fails.
1632 if (!name_status_find("*", 0, 0x1d, mb_ip
->ip
, name
) &&
1633 !name_status_find(MSBROWSE
, 1, 0x1d, mb_ip
->ip
, name
)) {
1635 DEBUG(99, ("Could not retrieve name status for %s\n",
1636 inet_ntoa(mb_ip
->ip
)));
1640 if (!find_master_ip(name
, &server_ip
)) {
1641 DEBUG(99, ("Could not find master ip for %s\n", name
));
1645 pstrcpy(workgroup
, name
);
1647 DEBUG(4, ("found master browser %s, %s\n",
1648 name
, inet_ntoa(mb_ip
->ip
)));
1650 cli
= get_ipc_connect(inet_ntoa(server_ip
), &server_ip
, user_info
);
1657 * Return the IP address and workgroup of a master browser on the network, and
1661 struct cli_state
*get_ipc_connect_master_ip_bcast(pstring workgroup
, struct user_auth_info
*user_info
)
1663 struct ip_service
*ip_list
;
1664 struct cli_state
*cli
;
1667 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
1669 /* Go looking for workgroups by broadcasting on the local network */
1671 if (!name_resolve_bcast(MSBROWSE
, 1, &ip_list
, &count
)) {
1672 DEBUG(99, ("No master browsers responded\n"));
1676 for (i
= 0; i
< count
; i
++) {
1677 DEBUG(99, ("Found master browser %s\n", inet_ntoa(ip_list
[i
].ip
)));
1679 cli
= get_ipc_connect_master_ip(&ip_list
[i
], workgroup
, user_info
);