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.
24 extern pstring user_socket_options
;
30 {PROTOCOL_CORE
,"PC NETWORK PROGRAM 1.0"},
31 {PROTOCOL_COREPLUS
,"MICROSOFT NETWORKS 1.03"},
32 {PROTOCOL_LANMAN1
,"MICROSOFT NETWORKS 3.0"},
33 {PROTOCOL_LANMAN1
,"LANMAN1.0"},
34 {PROTOCOL_LANMAN2
,"LM1.2X002"},
35 {PROTOCOL_LANMAN2
,"DOS LANMAN2.1"},
36 {PROTOCOL_LANMAN2
,"LANMAN2.1"},
37 {PROTOCOL_LANMAN2
,"Samba"},
38 {PROTOCOL_NT1
,"NT LANMAN 1.0"},
39 {PROTOCOL_NT1
,"NT LM 0.12"},
43 static const char *star_smbserver_name
= "*SMBSERVER";
46 * Set the user session key for a connection
47 * @param cli The cli structure to add it too
48 * @param session_key The session key used. (A copy of this is taken for the cli struct)
52 static void cli_set_session_key (struct cli_state
*cli
, const DATA_BLOB session_key
)
54 cli
->user_session_key
= data_blob(session_key
.data
, session_key
.length
);
57 /****************************************************************************
58 Do an old lanman2 style session setup.
59 ****************************************************************************/
61 static NTSTATUS
cli_session_setup_lanman2(struct cli_state
*cli
,
63 const char *pass
, size_t passlen
,
64 const char *workgroup
)
66 DATA_BLOB session_key
= data_blob(NULL
, 0);
67 DATA_BLOB lm_response
= data_blob(NULL
, 0);
71 if (passlen
> sizeof(pword
)-1) {
72 return NT_STATUS_INVALID_PARAMETER
;
75 /* LANMAN servers predate NT status codes and Unicode and ignore those
76 smb flags so we must disable the corresponding default capabilities
77 that would otherwise cause the Unicode and NT Status flags to be
78 set (and even returned by the server) */
80 cli
->capabilities
&= ~(CAP_UNICODE
| CAP_STATUS32
);
82 /* if in share level security then don't send a password now */
83 if (!(cli
->sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
))
86 if (passlen
> 0 && (cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) && passlen
!= 24) {
87 /* Encrypted mode needed, and non encrypted password supplied. */
88 lm_response
= data_blob(NULL
, 24);
89 if (!SMBencrypt(pass
, cli
->secblob
.data
,(uchar
*)lm_response
.data
)) {
90 DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n"));
91 return NT_STATUS_ACCESS_DENIED
;
93 } else if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) && passlen
== 24) {
94 /* Encrypted mode needed, and encrypted password supplied. */
95 lm_response
= data_blob(pass
, passlen
);
96 } else if (passlen
> 0) {
97 /* Plaintext mode needed, assume plaintext supplied. */
98 passlen
= clistr_push(cli
, pword
, pass
, sizeof(pword
), STR_TERMINATE
);
99 lm_response
= data_blob(pass
, passlen
);
102 /* send a session setup command */
103 memset(cli
->outbuf
,'\0',smb_size
);
104 set_message(cli
->outbuf
,10, 0, True
);
105 SCVAL(cli
->outbuf
,smb_com
,SMBsesssetupX
);
106 cli_setup_packet(cli
);
108 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
109 SSVAL(cli
->outbuf
,smb_vwv2
,cli
->max_xmit
);
110 SSVAL(cli
->outbuf
,smb_vwv3
,2);
111 SSVAL(cli
->outbuf
,smb_vwv4
,1);
112 SIVAL(cli
->outbuf
,smb_vwv5
,cli
->sesskey
);
113 SSVAL(cli
->outbuf
,smb_vwv7
,lm_response
.length
);
115 p
= smb_buf(cli
->outbuf
);
116 memcpy(p
,lm_response
.data
,lm_response
.length
);
117 p
+= lm_response
.length
;
118 p
+= clistr_push(cli
, p
, user
, -1, STR_TERMINATE
|STR_UPPER
);
119 p
+= clistr_push(cli
, p
, workgroup
, -1, STR_TERMINATE
|STR_UPPER
);
120 p
+= clistr_push(cli
, p
, "Unix", -1, STR_TERMINATE
);
121 p
+= clistr_push(cli
, p
, "Samba", -1, STR_TERMINATE
);
122 cli_setup_bcc(cli
, p
);
124 if (!cli_send_smb(cli
) || !cli_receive_smb(cli
)) {
125 return cli_nt_error(cli
);
128 show_msg(cli
->inbuf
);
130 if (cli_is_error(cli
)) {
131 return cli_nt_error(cli
);
134 /* use the returned vuid from now on */
135 cli
->vuid
= SVAL(cli
->inbuf
,smb_uid
);
136 fstrcpy(cli
->user_name
, user
);
138 if (session_key
.data
) {
139 /* Have plaintext orginal */
140 cli_set_session_key(cli
, session_key
);
146 /****************************************************************************
147 Work out suitable capabilities to offer the server.
148 ****************************************************************************/
150 static uint32
cli_session_setup_capabilities(struct cli_state
*cli
)
152 uint32 capabilities
= CAP_NT_SMBS
;
154 if (!cli
->force_dos_errors
)
155 capabilities
|= CAP_STATUS32
;
157 if (cli
->use_level_II_oplocks
)
158 capabilities
|= CAP_LEVEL_II_OPLOCKS
;
160 capabilities
|= (cli
->capabilities
& (CAP_UNICODE
|CAP_LARGE_FILES
|CAP_LARGE_READX
|CAP_LARGE_WRITEX
|CAP_DFS
));
164 /****************************************************************************
165 Do a NT1 guest session setup.
166 ****************************************************************************/
168 static NTSTATUS
cli_session_setup_guest(struct cli_state
*cli
)
171 uint32 capabilities
= cli_session_setup_capabilities(cli
);
173 memset(cli
->outbuf
, '\0', smb_size
);
174 set_message(cli
->outbuf
,13,0,True
);
175 SCVAL(cli
->outbuf
,smb_com
,SMBsesssetupX
);
176 cli_setup_packet(cli
);
178 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
179 SSVAL(cli
->outbuf
,smb_vwv2
,CLI_BUFFER_SIZE
);
180 SSVAL(cli
->outbuf
,smb_vwv3
,2);
181 SSVAL(cli
->outbuf
,smb_vwv4
,cli
->pid
);
182 SIVAL(cli
->outbuf
,smb_vwv5
,cli
->sesskey
);
183 SSVAL(cli
->outbuf
,smb_vwv7
,0);
184 SSVAL(cli
->outbuf
,smb_vwv8
,0);
185 SIVAL(cli
->outbuf
,smb_vwv11
,capabilities
);
186 p
= smb_buf(cli
->outbuf
);
187 p
+= clistr_push(cli
, p
, "", -1, STR_TERMINATE
); /* username */
188 p
+= clistr_push(cli
, p
, "", -1, STR_TERMINATE
); /* workgroup */
189 p
+= clistr_push(cli
, p
, "Unix", -1, STR_TERMINATE
);
190 p
+= clistr_push(cli
, p
, "Samba", -1, STR_TERMINATE
);
191 cli_setup_bcc(cli
, p
);
193 if (!cli_send_smb(cli
) || !cli_receive_smb(cli
)) {
194 return cli_nt_error(cli
);
197 show_msg(cli
->inbuf
);
199 if (cli_is_error(cli
)) {
200 return cli_nt_error(cli
);
203 cli
->vuid
= SVAL(cli
->inbuf
,smb_uid
);
205 p
= smb_buf(cli
->inbuf
);
206 p
+= clistr_pull(cli
, cli
->server_os
, p
, sizeof(fstring
), -1, STR_TERMINATE
);
207 p
+= clistr_pull(cli
, cli
->server_type
, p
, sizeof(fstring
), -1, STR_TERMINATE
);
208 p
+= clistr_pull(cli
, cli
->server_domain
, p
, sizeof(fstring
), -1, STR_TERMINATE
);
210 if (strstr(cli
->server_type
, "Samba")) {
211 cli
->is_samba
= True
;
214 fstrcpy(cli
->user_name
, "");
219 /****************************************************************************
220 Do a NT1 plaintext session setup.
221 ****************************************************************************/
223 static NTSTATUS
cli_session_setup_plaintext(struct cli_state
*cli
,
224 const char *user
, const char *pass
,
225 const char *workgroup
)
227 uint32 capabilities
= cli_session_setup_capabilities(cli
);
231 fstr_sprintf( lanman
, "Samba %s", SAMBA_VERSION_STRING
);
233 memset(cli
->outbuf
, '\0', smb_size
);
234 set_message(cli
->outbuf
,13,0,True
);
235 SCVAL(cli
->outbuf
,smb_com
,SMBsesssetupX
);
236 cli_setup_packet(cli
);
238 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
239 SSVAL(cli
->outbuf
,smb_vwv2
,CLI_BUFFER_SIZE
);
240 SSVAL(cli
->outbuf
,smb_vwv3
,2);
241 SSVAL(cli
->outbuf
,smb_vwv4
,cli
->pid
);
242 SIVAL(cli
->outbuf
,smb_vwv5
,cli
->sesskey
);
243 SSVAL(cli
->outbuf
,smb_vwv8
,0);
244 SIVAL(cli
->outbuf
,smb_vwv11
,capabilities
);
245 p
= smb_buf(cli
->outbuf
);
247 /* check wether to send the ASCII or UNICODE version of the password */
249 if ( (capabilities
& CAP_UNICODE
) == 0 ) {
250 p
+= clistr_push(cli
, p
, pass
, -1, STR_TERMINATE
); /* password */
251 SSVAL(cli
->outbuf
,smb_vwv7
,PTR_DIFF(p
, smb_buf(cli
->outbuf
)));
253 /* For ucs2 passwords clistr_push calls ucs2_align, which causes
254 * the space taken by the unicode password to be one byte too
255 * long (as we're on an odd byte boundary here). Reduce the
256 * count by 1 to cope with this. Fixes smbclient against NetApp
257 * servers which can't cope. Fix from
258 * bryan.kolodziej@allenlund.com in bug #3840.
260 p
+= clistr_push(cli
, p
, pass
, -1, STR_UNICODE
|STR_TERMINATE
); /* unicode password */
261 SSVAL(cli
->outbuf
,smb_vwv8
,PTR_DIFF(p
, smb_buf(cli
->outbuf
))-1);
264 p
+= clistr_push(cli
, p
, user
, -1, STR_TERMINATE
); /* username */
265 p
+= clistr_push(cli
, p
, workgroup
, -1, STR_TERMINATE
); /* workgroup */
266 p
+= clistr_push(cli
, p
, "Unix", -1, STR_TERMINATE
);
267 p
+= clistr_push(cli
, p
, lanman
, -1, STR_TERMINATE
);
268 cli_setup_bcc(cli
, p
);
270 if (!cli_send_smb(cli
) || !cli_receive_smb(cli
)) {
271 return cli_nt_error(cli
);
274 show_msg(cli
->inbuf
);
276 if (cli_is_error(cli
)) {
277 return cli_nt_error(cli
);
280 cli
->vuid
= SVAL(cli
->inbuf
,smb_uid
);
281 p
= smb_buf(cli
->inbuf
);
282 p
+= clistr_pull(cli
, cli
->server_os
, p
, sizeof(fstring
), -1, STR_TERMINATE
);
283 p
+= clistr_pull(cli
, cli
->server_type
, p
, sizeof(fstring
), -1, STR_TERMINATE
);
284 p
+= clistr_pull(cli
, cli
->server_domain
, p
, sizeof(fstring
), -1, STR_TERMINATE
);
285 fstrcpy(cli
->user_name
, user
);
287 if (strstr(cli
->server_type
, "Samba")) {
288 cli
->is_samba
= True
;
294 /****************************************************************************
295 do a NT1 NTLM/LM encrypted session setup - for when extended security
297 @param cli client state to create do session setup on
299 @param pass *either* cleartext password (passlen !=24) or LM response.
300 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
301 @param workgroup The user's domain.
302 ****************************************************************************/
304 static NTSTATUS
cli_session_setup_nt1(struct cli_state
*cli
, const char *user
,
305 const char *pass
, size_t passlen
,
306 const char *ntpass
, size_t ntpasslen
,
307 const char *workgroup
)
309 uint32 capabilities
= cli_session_setup_capabilities(cli
);
310 DATA_BLOB lm_response
= data_blob(NULL
, 0);
311 DATA_BLOB nt_response
= data_blob(NULL
, 0);
312 DATA_BLOB session_key
= data_blob(NULL
, 0);
317 /* do nothing - guest login */
318 } else if (passlen
!= 24) {
319 if (lp_client_ntlmv2_auth()) {
320 DATA_BLOB server_chal
;
321 DATA_BLOB names_blob
;
322 server_chal
= data_blob(cli
->secblob
.data
, MIN(cli
->secblob
.length
, 8));
324 /* note that the 'workgroup' here is a best guess - we don't know
325 the server's domain at this point. The 'server name' is also
328 names_blob
= NTLMv2_generate_names_blob(cli
->called
.name
, workgroup
);
330 if (!SMBNTLMv2encrypt(user
, workgroup
, pass
, &server_chal
,
332 &lm_response
, &nt_response
, &session_key
)) {
333 data_blob_free(&names_blob
);
334 data_blob_free(&server_chal
);
335 return NT_STATUS_ACCESS_DENIED
;
337 data_blob_free(&names_blob
);
338 data_blob_free(&server_chal
);
342 E_md4hash(pass
, nt_hash
);
345 nt_response
= data_blob(NULL
, 0);
347 nt_response
= data_blob(NULL
, 24);
348 SMBNTencrypt(pass
,cli
->secblob
.data
,nt_response
.data
);
350 /* non encrypted password supplied. Ignore ntpass. */
351 if (lp_client_lanman_auth()) {
352 lm_response
= data_blob(NULL
, 24);
353 if (!SMBencrypt(pass
,cli
->secblob
.data
, lm_response
.data
)) {
354 /* Oops, the LM response is invalid, just put
355 the NT response there instead */
356 data_blob_free(&lm_response
);
357 lm_response
= data_blob(nt_response
.data
, nt_response
.length
);
360 /* LM disabled, place NT# in LM field instead */
361 lm_response
= data_blob(nt_response
.data
, nt_response
.length
);
364 session_key
= data_blob(NULL
, 16);
366 E_deshash(pass
, session_key
.data
);
367 memset(&session_key
.data
[8], '\0', 8);
369 SMBsesskeygen_ntv1(nt_hash
, NULL
, session_key
.data
);
373 cli_simple_set_signing(cli
, session_key
, lm_response
);
375 cli_simple_set_signing(cli
, session_key
, nt_response
);
378 /* pre-encrypted password supplied. Only used for
379 security=server, can't do
380 signing because we don't have original key */
382 lm_response
= data_blob(pass
, passlen
);
383 nt_response
= data_blob(ntpass
, ntpasslen
);
386 /* send a session setup command */
387 memset(cli
->outbuf
,'\0',smb_size
);
389 set_message(cli
->outbuf
,13,0,True
);
390 SCVAL(cli
->outbuf
,smb_com
,SMBsesssetupX
);
391 cli_setup_packet(cli
);
393 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
394 SSVAL(cli
->outbuf
,smb_vwv2
,CLI_BUFFER_SIZE
);
395 SSVAL(cli
->outbuf
,smb_vwv3
,2);
396 SSVAL(cli
->outbuf
,smb_vwv4
,cli
->pid
);
397 SIVAL(cli
->outbuf
,smb_vwv5
,cli
->sesskey
);
398 SSVAL(cli
->outbuf
,smb_vwv7
,lm_response
.length
);
399 SSVAL(cli
->outbuf
,smb_vwv8
,nt_response
.length
);
400 SIVAL(cli
->outbuf
,smb_vwv11
,capabilities
);
401 p
= smb_buf(cli
->outbuf
);
402 if (lm_response
.length
) {
403 memcpy(p
,lm_response
.data
, lm_response
.length
); p
+= lm_response
.length
;
405 if (nt_response
.length
) {
406 memcpy(p
,nt_response
.data
, nt_response
.length
); p
+= nt_response
.length
;
408 p
+= clistr_push(cli
, p
, user
, -1, STR_TERMINATE
);
410 /* Upper case here might help some NTLMv2 implementations */
411 p
+= clistr_push(cli
, p
, workgroup
, -1, STR_TERMINATE
|STR_UPPER
);
412 p
+= clistr_push(cli
, p
, "Unix", -1, STR_TERMINATE
);
413 p
+= clistr_push(cli
, p
, "Samba", -1, STR_TERMINATE
);
414 cli_setup_bcc(cli
, p
);
416 if (!cli_send_smb(cli
) || !cli_receive_smb(cli
)) {
417 result
= cli_nt_error(cli
);
421 /* show_msg(cli->inbuf); */
423 if (cli_is_error(cli
)) {
424 result
= cli_nt_error(cli
);
428 /* use the returned vuid from now on */
429 cli
->vuid
= SVAL(cli
->inbuf
,smb_uid
);
431 p
= smb_buf(cli
->inbuf
);
432 p
+= clistr_pull(cli
, cli
->server_os
, p
, sizeof(fstring
), -1, STR_TERMINATE
);
433 p
+= clistr_pull(cli
, cli
->server_type
, p
, sizeof(fstring
), -1, STR_TERMINATE
);
434 p
+= clistr_pull(cli
, cli
->server_domain
, p
, sizeof(fstring
), -1, STR_TERMINATE
);
436 if (strstr(cli
->server_type
, "Samba")) {
437 cli
->is_samba
= True
;
440 fstrcpy(cli
->user_name
, user
);
442 if (session_key
.data
) {
443 /* Have plaintext orginal */
444 cli_set_session_key(cli
, session_key
);
447 result
= NT_STATUS_OK
;
449 data_blob_free(&lm_response
);
450 data_blob_free(&nt_response
);
451 data_blob_free(&session_key
);
455 /****************************************************************************
456 Send a extended security session setup blob
457 ****************************************************************************/
459 static BOOL
cli_session_setup_blob_send(struct cli_state
*cli
, DATA_BLOB blob
)
461 uint32 capabilities
= cli_session_setup_capabilities(cli
);
464 capabilities
|= CAP_EXTENDED_SECURITY
;
466 /* send a session setup command */
467 memset(cli
->outbuf
,'\0',smb_size
);
469 set_message(cli
->outbuf
,12,0,True
);
470 SCVAL(cli
->outbuf
,smb_com
,SMBsesssetupX
);
472 cli_setup_packet(cli
);
474 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
475 SSVAL(cli
->outbuf
,smb_vwv2
,CLI_BUFFER_SIZE
);
476 SSVAL(cli
->outbuf
,smb_vwv3
,2);
477 SSVAL(cli
->outbuf
,smb_vwv4
,1);
478 SIVAL(cli
->outbuf
,smb_vwv5
,0);
479 SSVAL(cli
->outbuf
,smb_vwv7
,blob
.length
);
480 SIVAL(cli
->outbuf
,smb_vwv10
,capabilities
);
481 p
= smb_buf(cli
->outbuf
);
482 memcpy(p
, blob
.data
, blob
.length
);
484 p
+= clistr_push(cli
, p
, "Unix", -1, STR_TERMINATE
);
485 p
+= clistr_push(cli
, p
, "Samba", -1, STR_TERMINATE
);
486 cli_setup_bcc(cli
, p
);
487 return cli_send_smb(cli
);
490 /****************************************************************************
491 Send a extended security session setup blob, returning a reply blob.
492 ****************************************************************************/
494 static DATA_BLOB
cli_session_setup_blob_receive(struct cli_state
*cli
)
496 DATA_BLOB blob2
= data_blob(NULL
, 0);
500 if (!cli_receive_smb(cli
))
503 show_msg(cli
->inbuf
);
505 if (cli_is_error(cli
) && !NT_STATUS_EQUAL(cli_nt_error(cli
),
506 NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
510 /* use the returned vuid from now on */
511 cli
->vuid
= SVAL(cli
->inbuf
,smb_uid
);
513 p
= smb_buf(cli
->inbuf
);
515 blob2
= data_blob(p
, SVAL(cli
->inbuf
, smb_vwv3
));
518 p
+= clistr_pull(cli
, cli
->server_os
, p
, sizeof(fstring
), -1, STR_TERMINATE
);
520 /* w2k with kerberos doesn't properly null terminate this field */
521 len
= smb_buflen(cli
->inbuf
) - PTR_DIFF(p
, smb_buf(cli
->inbuf
));
522 p
+= clistr_pull(cli
, cli
->server_type
, p
, sizeof(fstring
), len
, 0);
528 /****************************************************************************
529 Send a extended security session setup blob, returning a reply blob.
530 ****************************************************************************/
532 /* The following is calculated from :
534 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
535 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
539 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
541 static BOOL
cli_session_setup_blob(struct cli_state
*cli
, DATA_BLOB blob
)
543 int32 remaining
= blob
.length
;
545 DATA_BLOB send_blob
= data_blob(NULL
, 0);
546 int32 max_blob_size
= 0;
547 DATA_BLOB receive_blob
= data_blob(NULL
, 0);
549 if (cli
->max_xmit
< BASE_SESSSETUP_BLOB_PACKET_SIZE
+ 1) {
550 DEBUG(0,("cli_session_setup_blob: cli->max_xmit too small "
551 "(was %u, need minimum %u)\n",
552 (unsigned int)cli
->max_xmit
,
553 BASE_SESSSETUP_BLOB_PACKET_SIZE
));
554 cli_set_nt_error(cli
, NT_STATUS_INVALID_PARAMETER
);
558 max_blob_size
= cli
->max_xmit
- BASE_SESSSETUP_BLOB_PACKET_SIZE
;
560 while ( remaining
> 0) {
561 if (remaining
>= max_blob_size
) {
562 send_blob
.length
= max_blob_size
;
563 remaining
-= max_blob_size
;
565 send_blob
.length
= remaining
;
569 send_blob
.data
= &blob
.data
[cur
];
570 cur
+= send_blob
.length
;
572 DEBUG(10, ("cli_session_setup_blob: Remaining (%u) sending (%u) current (%u)\n",
573 (unsigned int)remaining
,
574 (unsigned int)send_blob
.length
,
575 (unsigned int)cur
));
577 if (!cli_session_setup_blob_send(cli
, send_blob
)) {
578 DEBUG(0, ("cli_session_setup_blob: send failed\n"));
582 receive_blob
= cli_session_setup_blob_receive(cli
);
583 data_blob_free(&receive_blob
);
585 if (cli_is_error(cli
) &&
586 !NT_STATUS_EQUAL( cli_get_nt_error(cli
),
587 NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
588 DEBUG(0, ("cli_session_setup_blob: recieve failed (%s)\n",
589 nt_errstr(cli_get_nt_error(cli
)) ));
598 /****************************************************************************
599 Use in-memory credentials cache
600 ****************************************************************************/
602 static void use_in_memory_ccache(void) {
603 setenv(KRB5_ENV_CCNAME
, "MEMORY:cliconnect", 1);
606 /****************************************************************************
607 Do a spnego/kerberos encrypted session setup.
608 ****************************************************************************/
610 static ADS_STATUS
cli_session_setup_kerberos(struct cli_state
*cli
, const char *principal
, const char *workgroup
)
612 DATA_BLOB negTokenTarg
;
613 DATA_BLOB session_key_krb5
;
614 DATA_BLOB null_blob
= data_blob(NULL
, 0);
619 cli_temp_set_signing(cli
);
621 DEBUG(2,("Doing kerberos session setup\n"));
623 /* generate the encapsulated kerberos5 ticket */
624 rc
= spnego_gen_negTokenTarg(principal
, 0, &negTokenTarg
, &session_key_krb5
, 0, NULL
);
627 DEBUG(1, ("cli_session_setup_kerberos: spnego_gen_negTokenTarg failed: %s\n",
629 return ADS_ERROR_KRB5(rc
);
633 file_save("negTokenTarg.dat", negTokenTarg
.data
, negTokenTarg
.length
);
636 if (!cli_session_setup_blob(cli
, negTokenTarg
)) {
637 nt_status
= cli_nt_error(cli
);
641 if (cli_is_error(cli
)) {
642 nt_status
= cli_nt_error(cli
);
643 if (NT_STATUS_IS_OK(nt_status
)) {
644 nt_status
= NT_STATUS_UNSUCCESSFUL
;
649 cli_set_session_key(cli
, session_key_krb5
);
651 res
= cli_simple_set_signing(cli
, session_key_krb5
, null_blob
);
653 /* 'resign' the last message, so we get the right sequence numbers
654 for checking the first reply from the server */
655 cli_calculate_sign_mac(cli
);
657 if (!cli_check_sign_mac(cli
)) {
658 nt_status
= NT_STATUS_ACCESS_DENIED
;
663 data_blob_free(&negTokenTarg
);
664 data_blob_free(&session_key_krb5
);
666 return ADS_ERROR_NT(NT_STATUS_OK
);
669 data_blob_free(&negTokenTarg
);
670 data_blob_free(&session_key_krb5
);
672 return ADS_ERROR_NT(nt_status
);
674 #endif /* HAVE_KRB5 */
677 /****************************************************************************
678 Do a spnego/NTLMSSP encrypted session setup.
679 ****************************************************************************/
681 static NTSTATUS
cli_session_setup_ntlmssp(struct cli_state
*cli
, const char *user
,
682 const char *pass
, const char *domain
)
684 struct ntlmssp_state
*ntlmssp_state
;
688 DATA_BLOB blob
= data_blob(NULL
, 0);
689 DATA_BLOB blob_in
= data_blob(NULL
, 0);
690 DATA_BLOB blob_out
= data_blob(NULL
, 0);
692 cli_temp_set_signing(cli
);
694 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_client_start(&ntlmssp_state
))) {
697 ntlmssp_want_feature(ntlmssp_state
, NTLMSSP_FEATURE_SESSION_KEY
);
699 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_set_username(ntlmssp_state
, user
))) {
702 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_set_domain(ntlmssp_state
, domain
))) {
705 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_set_password(ntlmssp_state
, pass
))) {
710 nt_status
= ntlmssp_update(ntlmssp_state
,
712 data_blob_free(&blob_in
);
713 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) || NT_STATUS_IS_OK(nt_status
)) {
715 /* and wrap it in a SPNEGO wrapper */
716 msg1
= gen_negTokenInit(OID_NTLMSSP
, blob_out
);
718 /* wrap it in SPNEGO */
719 msg1
= spnego_gen_auth(blob_out
);
722 /* now send that blob on its way */
723 if (!cli_session_setup_blob_send(cli
, msg1
)) {
724 DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
725 nt_status
= NT_STATUS_UNSUCCESSFUL
;
727 blob
= cli_session_setup_blob_receive(cli
);
729 nt_status
= cli_nt_error(cli
);
730 if (cli_is_error(cli
) && NT_STATUS_IS_OK(nt_status
)) {
731 if (cli
->smb_rw_error
== READ_BAD_SIG
) {
732 nt_status
= NT_STATUS_ACCESS_DENIED
;
734 nt_status
= NT_STATUS_UNSUCCESSFUL
;
738 data_blob_free(&msg1
);
742 if (NT_STATUS_IS_OK(nt_status
)) {
743 nt_status
= NT_STATUS_UNSUCCESSFUL
;
745 } else if ((turn
== 1) &&
746 NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
747 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
748 /* the server might give us back two challenges */
749 if (!spnego_parse_challenge(blob
, &blob_in
,
751 DEBUG(3,("Failed to parse challenges\n"));
752 nt_status
= NT_STATUS_INVALID_PARAMETER
;
754 data_blob_free(&tmp_blob
);
756 if (!spnego_parse_auth_response(blob
, nt_status
,
758 DEBUG(3,("Failed to parse auth response\n"));
759 if (NT_STATUS_IS_OK(nt_status
)
760 || NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
))
761 nt_status
= NT_STATUS_INVALID_PARAMETER
;
764 data_blob_free(&blob
);
765 data_blob_free(&blob_out
);
767 } while (NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
));
769 data_blob_free(&blob_in
);
771 if (NT_STATUS_IS_OK(nt_status
)) {
773 DATA_BLOB key
= data_blob(ntlmssp_state
->session_key
.data
,
774 ntlmssp_state
->session_key
.length
);
775 DATA_BLOB null_blob
= data_blob(NULL
, 0);
778 fstrcpy(cli
->server_domain
, ntlmssp_state
->server_domain
);
779 cli_set_session_key(cli
, ntlmssp_state
->session_key
);
781 res
= cli_simple_set_signing(cli
, key
, null_blob
);
783 data_blob_free(&key
);
787 /* 'resign' the last message, so we get the right sequence numbers
788 for checking the first reply from the server */
789 cli_calculate_sign_mac(cli
);
791 if (!cli_check_sign_mac(cli
)) {
792 nt_status
= NT_STATUS_ACCESS_DENIED
;
797 /* we have a reference conter on ntlmssp_state, if we are signing
798 then the state will be kept by the signing engine */
800 ntlmssp_end(&ntlmssp_state
);
802 if (!NT_STATUS_IS_OK(nt_status
)) {
808 /****************************************************************************
809 Do a spnego encrypted session setup.
811 user_domain: The shortname of the domain the user/machine is a member of.
812 dest_realm: The realm we're connecting to, if NULL we use our default realm.
813 ****************************************************************************/
815 ADS_STATUS
cli_session_setup_spnego(struct cli_state
*cli
, const char *user
,
816 const char *pass
, const char *user_domain
,
817 const char * dest_realm
)
819 char *principal
= NULL
;
820 char *OIDs
[ASN1_MAX_OIDS
];
822 BOOL got_kerberos_mechanism
= False
;
825 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli
->secblob
.length
));
827 /* the server might not even do spnego */
828 if (cli
->secblob
.length
<= 16) {
829 DEBUG(3,("server didn't supply a full spnego negprot\n"));
834 file_save("negprot.dat", cli
->secblob
.data
, cli
->secblob
.length
);
837 /* there is 16 bytes of GUID before the real spnego packet starts */
838 blob
= data_blob(cli
->secblob
.data
+16, cli
->secblob
.length
-16);
840 /* The server sent us the first part of the SPNEGO exchange in the
841 * negprot reply. It is WRONG to depend on the principal sent in the
842 * negprot reply, but right now we do it. If we don't receive one,
843 * we try to best guess, then fall back to NTLM. */
844 if (!spnego_parse_negTokenInit(blob
, OIDs
, &principal
)) {
845 data_blob_free(&blob
);
846 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
848 data_blob_free(&blob
);
850 /* make sure the server understands kerberos */
851 for (i
=0;OIDs
[i
];i
++) {
852 DEBUG(3,("got OID=%s\n", OIDs
[i
]));
853 if (strcmp(OIDs
[i
], OID_KERBEROS5_OLD
) == 0 ||
854 strcmp(OIDs
[i
], OID_KERBEROS5
) == 0) {
855 got_kerberos_mechanism
= True
;
860 DEBUG(3,("got principal=%s\n", principal
? principal
: "<null>"));
862 fstrcpy(cli
->user_name
, user
);
865 /* If password is set we reauthenticate to kerberos server
866 * and do not store results */
868 if (got_kerberos_mechanism
&& cli
->use_kerberos
) {
874 use_in_memory_ccache();
875 ret
= kerberos_kinit_password(user
, pass
, 0 /* no time correction for now */, NULL
);
878 SAFE_FREE(principal
);
879 DEBUG(0, ("Kinit failed: %s\n", error_message(ret
)));
880 if (cli
->fallback_after_kerberos
)
882 return ADS_ERROR_KRB5(ret
);
886 /* If we get a bad principal, try to guess it if
887 we have a valid host NetBIOS name.
889 if (strequal(principal
, ADS_IGNORE_PRINCIPAL
)) {
890 SAFE_FREE(principal
);
892 if (principal
== NULL
&&
893 !is_ipaddress(cli
->desthost
) &&
894 !strequal(star_smbserver_name
,
897 char *machine
= NULL
;
899 DEBUG(3,("cli_session_setup_spnego: got a "
900 "bad server principal, trying to guess ...\n"));
902 host
= strchr_m(cli
->desthost
, '.');
904 machine
= SMB_STRNDUP(cli
->desthost
,
905 host
- cli
->desthost
);
907 machine
= SMB_STRDUP(cli
->desthost
);
909 if (machine
== NULL
) {
910 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
914 realm
= SMB_STRDUP(dest_realm
);
917 realm
= kerberos_get_default_realm_from_ccache();
919 if (realm
&& *realm
) {
920 if (asprintf(&principal
, "%s$@%s",
921 machine
, realm
) < 0) {
924 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
926 DEBUG(3,("cli_session_setup_spnego: guessed "
927 "server principal=%s\n",
928 principal
? principal
: "<null>"));
935 rc
= cli_session_setup_kerberos(cli
, principal
,
937 if (ADS_ERR_OK(rc
) || !cli
->fallback_after_kerberos
) {
938 SAFE_FREE(principal
);
945 SAFE_FREE(principal
);
949 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli
, user
, pass
,
953 /****************************************************************************
954 Send a session setup. The username and workgroup is in UNIX character
955 format and must be converted to DOS codepage format before sending. If the
956 password is in plaintext, the same should be done.
957 ****************************************************************************/
959 NTSTATUS
cli_session_setup(struct cli_state
*cli
,
961 const char *pass
, int passlen
,
962 const char *ntpass
, int ntpasslen
,
963 const char *workgroup
)
968 /* allow for workgroups as part of the username */
969 fstrcpy(user2
, user
);
970 if ((p
=strchr_m(user2
,'\\')) || (p
=strchr_m(user2
,'/')) ||
971 (p
=strchr_m(user2
,*lp_winbind_separator()))) {
977 if (cli
->protocol
< PROTOCOL_LANMAN1
) {
981 /* now work out what sort of session setup we are going to
982 do. I have split this into separate functions to make the
983 flow a bit easier to understand (tridge) */
985 /* if its an older server then we have to use the older request format */
987 if (cli
->protocol
< PROTOCOL_NT1
) {
988 if (!lp_client_lanman_auth() && passlen
!= 24 && (*pass
)) {
989 DEBUG(1, ("Server requested LM password but 'client lanman auth'"
991 return NT_STATUS_ACCESS_DENIED
;
994 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) == 0 &&
995 !lp_client_plaintext_auth() && (*pass
)) {
996 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
998 return NT_STATUS_ACCESS_DENIED
;
1001 return cli_session_setup_lanman2(cli
, user
, pass
, passlen
,
1005 /* if no user is supplied then we have to do an anonymous connection.
1006 passwords are ignored */
1008 if (!user
|| !*user
)
1009 return cli_session_setup_guest(cli
);
1011 /* if the server is share level then send a plaintext null
1012 password at this point. The password is sent in the tree
1015 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
) == 0)
1016 return cli_session_setup_plaintext(cli
, user
, "", workgroup
);
1018 /* if the server doesn't support encryption then we have to use
1019 plaintext. The second password is ignored */
1021 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) == 0) {
1022 if (!lp_client_plaintext_auth() && (*pass
)) {
1023 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
1025 return NT_STATUS_ACCESS_DENIED
;
1027 return cli_session_setup_plaintext(cli
, user
, pass
, workgroup
);
1030 /* if the server supports extended security then use SPNEGO */
1032 if (cli
->capabilities
& CAP_EXTENDED_SECURITY
) {
1033 ADS_STATUS status
= cli_session_setup_spnego(cli
, user
, pass
,
1035 if (!ADS_ERR_OK(status
)) {
1036 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status
)));
1037 return ads_ntstatus(status
);
1042 /* otherwise do a NT1 style session setup */
1043 status
= cli_session_setup_nt1(cli
, user
, pass
, passlen
,
1044 ntpass
, ntpasslen
, workgroup
);
1045 if (!NT_STATUS_IS_OK(status
)) {
1046 DEBUG(3,("cli_session_setup: NT1 session setup "
1047 "failed: %s\n", nt_errstr(status
)));
1052 if (strstr(cli
->server_type
, "Samba")) {
1053 cli
->is_samba
= True
;
1056 return NT_STATUS_OK
;
1059 /****************************************************************************
1061 *****************************************************************************/
1063 BOOL
cli_ulogoff(struct cli_state
*cli
)
1065 memset(cli
->outbuf
,'\0',smb_size
);
1066 set_message(cli
->outbuf
,2,0,True
);
1067 SCVAL(cli
->outbuf
,smb_com
,SMBulogoffX
);
1068 cli_setup_packet(cli
);
1069 SSVAL(cli
->outbuf
,smb_vwv0
,0xFF);
1070 SSVAL(cli
->outbuf
,smb_vwv2
,0); /* no additional info */
1073 if (!cli_receive_smb(cli
))
1076 if (cli_is_error(cli
)) {
1084 /****************************************************************************
1086 ****************************************************************************/
1088 BOOL
cli_send_tconX(struct cli_state
*cli
,
1089 const char *share
, const char *dev
, const char *pass
, int passlen
)
1091 fstring fullshare
, pword
;
1093 memset(cli
->outbuf
,'\0',smb_size
);
1094 memset(cli
->inbuf
,'\0',smb_size
);
1096 fstrcpy(cli
->share
, share
);
1098 /* in user level security don't send a password now */
1099 if (cli
->sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
) {
1103 DEBUG(1, ("Server not using user level security and no password supplied.\n"));
1107 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) &&
1108 *pass
&& passlen
!= 24) {
1109 if (!lp_client_lanman_auth()) {
1110 DEBUG(1, ("Server requested LANMAN password (share-level security) but 'client use lanman auth'"
1116 * Non-encrypted passwords - convert to DOS codepage before encryption.
1119 SMBencrypt(pass
,cli
->secblob
.data
,(uchar
*)pword
);
1121 if((cli
->sec_mode
& (NEGOTIATE_SECURITY_USER_LEVEL
|NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
)) == 0) {
1122 if (!lp_client_plaintext_auth() && (*pass
)) {
1123 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
1129 * Non-encrypted passwords - convert to DOS codepage before using.
1131 passlen
= clistr_push(cli
, pword
, pass
, sizeof(pword
), STR_TERMINATE
);
1135 memcpy(pword
, pass
, passlen
);
1140 slprintf(fullshare
, sizeof(fullshare
)-1,
1141 "\\\\%s\\%s", cli
->desthost
, share
);
1143 set_message(cli
->outbuf
,4, 0, True
);
1144 SCVAL(cli
->outbuf
,smb_com
,SMBtconX
);
1145 cli_setup_packet(cli
);
1147 SSVAL(cli
->outbuf
,smb_vwv0
,0xFF);
1148 SSVAL(cli
->outbuf
,smb_vwv2
,TCONX_FLAG_EXTENDED_RESPONSE
);
1149 SSVAL(cli
->outbuf
,smb_vwv3
,passlen
);
1151 p
= smb_buf(cli
->outbuf
);
1153 memcpy(p
,pword
,passlen
);
1156 p
+= clistr_push(cli
, p
, fullshare
, -1, STR_TERMINATE
|STR_UPPER
);
1157 p
+= clistr_push(cli
, p
, dev
, -1, STR_TERMINATE
|STR_UPPER
| STR_ASCII
);
1159 cli_setup_bcc(cli
, p
);
1162 if (!cli_receive_smb(cli
))
1165 if (cli_is_error(cli
))
1168 clistr_pull(cli
, cli
->dev
, smb_buf(cli
->inbuf
), sizeof(fstring
), -1, STR_TERMINATE
|STR_ASCII
);
1170 if (cli
->protocol
>= PROTOCOL_NT1
&&
1171 smb_buflen(cli
->inbuf
) == 3) {
1172 /* almost certainly win95 - enable bug fixes */
1176 /* Make sure that we have the optional support 16-bit field. WCT > 2 */
1177 /* Avoids issues when connecting to Win9x boxes sharing files */
1179 cli
->dfsroot
= False
;
1180 if ( (CVAL(cli
->inbuf
, smb_wct
))>2 && cli
->protocol
>= PROTOCOL_LANMAN2
)
1181 cli
->dfsroot
= (SVAL( cli
->inbuf
, smb_vwv2
) & SMB_SHARE_IN_DFS
) ? True
: False
;
1183 cli
->cnum
= SVAL(cli
->inbuf
,smb_tid
);
1187 /****************************************************************************
1188 Send a tree disconnect.
1189 ****************************************************************************/
1191 BOOL
cli_tdis(struct cli_state
*cli
)
1193 memset(cli
->outbuf
,'\0',smb_size
);
1194 set_message(cli
->outbuf
,0,0,True
);
1195 SCVAL(cli
->outbuf
,smb_com
,SMBtdis
);
1196 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
1197 cli_setup_packet(cli
);
1200 if (!cli_receive_smb(cli
))
1203 if (cli_is_error(cli
)) {
1211 /****************************************************************************
1212 Send a negprot command.
1213 ****************************************************************************/
1215 void cli_negprot_send(struct cli_state
*cli
)
1220 if (cli
->protocol
< PROTOCOL_NT1
)
1221 cli
->use_spnego
= False
;
1223 memset(cli
->outbuf
,'\0',smb_size
);
1225 /* setup the protocol strings */
1226 set_message(cli
->outbuf
,0,0,True
);
1228 p
= smb_buf(cli
->outbuf
);
1230 prots
[numprots
].name
&& prots
[numprots
].prot
<=cli
->protocol
;
1233 p
+= clistr_push(cli
, p
, prots
[numprots
].name
, -1, STR_TERMINATE
);
1236 SCVAL(cli
->outbuf
,smb_com
,SMBnegprot
);
1237 cli_setup_bcc(cli
, p
);
1238 cli_setup_packet(cli
);
1240 SCVAL(smb_buf(cli
->outbuf
),0,2);
1245 /****************************************************************************
1246 Send a negprot command.
1247 ****************************************************************************/
1249 BOOL
cli_negprot(struct cli_state
*cli
)
1255 if (cli
->protocol
< PROTOCOL_NT1
)
1256 cli
->use_spnego
= False
;
1258 memset(cli
->outbuf
,'\0',smb_size
);
1260 /* setup the protocol strings */
1261 for (plength
=0,numprots
=0;
1262 prots
[numprots
].name
&& prots
[numprots
].prot
<=cli
->protocol
;
1264 plength
+= strlen(prots
[numprots
].name
)+2;
1266 set_message(cli
->outbuf
,0,plength
,True
);
1268 p
= smb_buf(cli
->outbuf
);
1270 prots
[numprots
].name
&& prots
[numprots
].prot
<=cli
->protocol
;
1273 p
+= clistr_push(cli
, p
, prots
[numprots
].name
, -1, STR_TERMINATE
);
1276 SCVAL(cli
->outbuf
,smb_com
,SMBnegprot
);
1277 cli_setup_packet(cli
);
1279 SCVAL(smb_buf(cli
->outbuf
),0,2);
1282 if (!cli_receive_smb(cli
))
1285 show_msg(cli
->inbuf
);
1287 if (cli_is_error(cli
) ||
1288 ((int)SVAL(cli
->inbuf
,smb_vwv0
) >= numprots
)) {
1292 cli
->protocol
= prots
[SVAL(cli
->inbuf
,smb_vwv0
)].prot
;
1294 if ((cli
->protocol
< PROTOCOL_NT1
) && cli
->sign_info
.mandatory_signing
) {
1295 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1299 if (cli
->protocol
>= PROTOCOL_NT1
) {
1302 cli
->sec_mode
= CVAL(cli
->inbuf
,smb_vwv1
);
1303 cli
->max_mux
= SVAL(cli
->inbuf
, smb_vwv1
+1);
1304 cli
->max_xmit
= IVAL(cli
->inbuf
,smb_vwv3
+1);
1305 cli
->sesskey
= IVAL(cli
->inbuf
,smb_vwv7
+1);
1306 cli
->serverzone
= SVALS(cli
->inbuf
,smb_vwv15
+1);
1307 cli
->serverzone
*= 60;
1308 /* this time arrives in real GMT */
1309 ts
= interpret_long_date(cli
->inbuf
+smb_vwv11
+1);
1310 cli
->servertime
= ts
.tv_sec
;
1311 cli
->secblob
= data_blob(smb_buf(cli
->inbuf
),smb_buflen(cli
->inbuf
));
1312 cli
->capabilities
= IVAL(cli
->inbuf
,smb_vwv9
+1);
1313 if (cli
->capabilities
& CAP_RAW_MODE
) {
1314 cli
->readbraw_supported
= True
;
1315 cli
->writebraw_supported
= True
;
1317 /* work out if they sent us a workgroup */
1318 if (!(cli
->capabilities
& CAP_EXTENDED_SECURITY
) &&
1319 smb_buflen(cli
->inbuf
) > 8) {
1320 clistr_pull(cli
, cli
->server_domain
,
1321 smb_buf(cli
->inbuf
)+8, sizeof(cli
->server_domain
),
1322 smb_buflen(cli
->inbuf
)-8, STR_UNICODE
|STR_NOALIGN
);
1326 * As signing is slow we only turn it on if either the client or
1327 * the server require it. JRA.
1330 if (cli
->sec_mode
& NEGOTIATE_SECURITY_SIGNATURES_REQUIRED
) {
1331 /* Fail if server says signing is mandatory and we don't want to support it. */
1332 if (!cli
->sign_info
.allow_smb_signing
) {
1333 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1336 cli
->sign_info
.negotiated_smb_signing
= True
;
1337 cli
->sign_info
.mandatory_signing
= True
;
1338 } else if (cli
->sign_info
.mandatory_signing
&& cli
->sign_info
.allow_smb_signing
) {
1339 /* Fail if client says signing is mandatory and the server doesn't support it. */
1340 if (!(cli
->sec_mode
& NEGOTIATE_SECURITY_SIGNATURES_ENABLED
)) {
1341 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1344 cli
->sign_info
.negotiated_smb_signing
= True
;
1345 cli
->sign_info
.mandatory_signing
= True
;
1346 } else if (cli
->sec_mode
& NEGOTIATE_SECURITY_SIGNATURES_ENABLED
) {
1347 cli
->sign_info
.negotiated_smb_signing
= True
;
1350 if (cli
->capabilities
& (CAP_LARGE_READX
|CAP_LARGE_WRITEX
)) {
1351 SAFE_FREE(cli
->outbuf
);
1352 SAFE_FREE(cli
->inbuf
);
1353 cli
->outbuf
= (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE
+LARGE_WRITEX_HDR_SIZE
+SAFETY_MARGIN
);
1354 cli
->inbuf
= (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE
+LARGE_WRITEX_HDR_SIZE
+SAFETY_MARGIN
);
1355 cli
->bufsize
= CLI_SAMBA_MAX_LARGE_READX_SIZE
+ LARGE_WRITEX_HDR_SIZE
;
1358 } else if (cli
->protocol
>= PROTOCOL_LANMAN1
) {
1359 cli
->use_spnego
= False
;
1360 cli
->sec_mode
= SVAL(cli
->inbuf
,smb_vwv1
);
1361 cli
->max_xmit
= SVAL(cli
->inbuf
,smb_vwv2
);
1362 cli
->max_mux
= SVAL(cli
->inbuf
, smb_vwv3
);
1363 cli
->sesskey
= IVAL(cli
->inbuf
,smb_vwv6
);
1364 cli
->serverzone
= SVALS(cli
->inbuf
,smb_vwv10
);
1365 cli
->serverzone
*= 60;
1366 /* this time is converted to GMT by make_unix_date */
1367 cli
->servertime
= cli_make_unix_date(cli
,cli
->inbuf
+smb_vwv8
);
1368 cli
->readbraw_supported
= ((SVAL(cli
->inbuf
,smb_vwv5
) & 0x1) != 0);
1369 cli
->writebraw_supported
= ((SVAL(cli
->inbuf
,smb_vwv5
) & 0x2) != 0);
1370 cli
->secblob
= data_blob(smb_buf(cli
->inbuf
),smb_buflen(cli
->inbuf
));
1372 /* the old core protocol */
1373 cli
->use_spnego
= False
;
1375 cli
->serverzone
= get_time_zone(time(NULL
));
1378 cli
->max_xmit
= MIN(cli
->max_xmit
, CLI_BUFFER_SIZE
);
1380 /* a way to force ascii SMB */
1381 if (getenv("CLI_FORCE_ASCII"))
1382 cli
->capabilities
&= ~CAP_UNICODE
;
1387 /****************************************************************************
1388 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1389 ****************************************************************************/
1391 BOOL
cli_session_request(struct cli_state
*cli
,
1392 struct nmb_name
*calling
, struct nmb_name
*called
)
1397 memcpy(&(cli
->calling
), calling
, sizeof(*calling
));
1398 memcpy(&(cli
->called
), called
, sizeof(*called
));
1400 /* put in the destination name */
1401 p
= cli
->outbuf
+len
;
1402 name_mangle(cli
->called
.name
, p
, cli
->called
.name_type
);
1406 p
= cli
->outbuf
+len
;
1407 name_mangle(cli
->calling
.name
, p
, cli
->calling
.name_type
);
1410 /* 445 doesn't have session request */
1411 if (cli
->port
== 445)
1414 /* send a session request (RFC 1002) */
1415 /* setup the packet length
1416 * Remove four bytes from the length count, since the length
1417 * field in the NBT Session Service header counts the number
1418 * of bytes which follow. The cli_send_smb() function knows
1419 * about this and accounts for those four bytes.
1423 _smb_setlen(cli
->outbuf
,len
);
1424 SCVAL(cli
->outbuf
,0,0x81);
1427 DEBUG(5,("Sent session request\n"));
1429 if (!cli_receive_smb(cli
))
1432 if (CVAL(cli
->inbuf
,0) == 0x84) {
1433 /* C. Hoch 9/14/95 Start */
1434 /* For information, here is the response structure.
1435 * We do the byte-twiddling to for portability.
1436 struct RetargetResponse{
1438 unsigned char flags;
1444 int port
= (CVAL(cli
->inbuf
,8)<<8)+CVAL(cli
->inbuf
,9);
1445 /* SESSION RETARGET */
1446 putip((char *)&cli
->dest_ip
,cli
->inbuf
+4);
1448 cli
->fd
= open_socket_out(SOCK_STREAM
, &cli
->dest_ip
, port
, LONG_CONNECT_TIMEOUT
);
1452 DEBUG(3,("Retargeted\n"));
1454 set_socket_options(cli
->fd
,user_socket_options
);
1461 DEBUG(0,("Retarget recursion - failing\n"));
1465 ret
= cli_session_request(cli
, calling
, called
);
1469 } /* C. Hoch 9/14/95 End */
1471 if (CVAL(cli
->inbuf
,0) != 0x82) {
1472 /* This is the wrong place to put the error... JRA. */
1473 cli
->rap_error
= CVAL(cli
->inbuf
,4);
1479 /****************************************************************************
1480 Open the client sockets.
1481 ****************************************************************************/
1483 NTSTATUS
cli_connect(struct cli_state
*cli
, const char *host
, struct in_addr
*ip
)
1485 int name_type
= 0x20;
1488 /* reasonable default hostname */
1489 if (!host
) host
= star_smbserver_name
;
1491 fstrcpy(cli
->desthost
, host
);
1493 /* allow hostnames of the form NAME#xx and do a netbios lookup */
1494 if ((p
= strchr(cli
->desthost
, '#'))) {
1495 name_type
= strtol(p
+1, NULL
, 16);
1499 if (!ip
|| is_zero_ip(*ip
)) {
1500 if (!resolve_name(cli
->desthost
, &cli
->dest_ip
, name_type
)) {
1501 return NT_STATUS_BAD_NETWORK_NAME
;
1503 if (ip
) *ip
= cli
->dest_ip
;
1508 if (getenv("LIBSMB_PROG")) {
1509 cli
->fd
= sock_exec(getenv("LIBSMB_PROG"));
1511 /* try 445 first, then 139 */
1512 int port
= cli
->port
?cli
->port
:445;
1513 cli
->fd
= open_socket_out(SOCK_STREAM
, &cli
->dest_ip
,
1514 port
, cli
->timeout
);
1515 if (cli
->fd
== -1 && cli
->port
== 0) {
1517 cli
->fd
= open_socket_out(SOCK_STREAM
, &cli
->dest_ip
,
1518 port
, cli
->timeout
);
1523 if (cli
->fd
== -1) {
1524 DEBUG(1,("Error connecting to %s (%s)\n",
1525 ip
?inet_ntoa(*ip
):host
,strerror(errno
)));
1526 return map_nt_error_from_unix(errno
);
1529 set_socket_options(cli
->fd
,user_socket_options
);
1531 return NT_STATUS_OK
;
1535 establishes a connection to after the negprot.
1536 @param output_cli A fully initialised cli structure, non-null only on success
1537 @param dest_host The netbios name of the remote host
1538 @param dest_ip (optional) The the destination IP, NULL for name based lookup
1539 @param port (optional) The destination port (0 for default)
1540 @param retry BOOL. Did this connection fail with a retryable error ?
1543 NTSTATUS
cli_start_connection(struct cli_state
**output_cli
,
1544 const char *my_name
,
1545 const char *dest_host
,
1546 struct in_addr
*dest_ip
, int port
,
1547 int signing_state
, int flags
,
1551 struct nmb_name calling
;
1552 struct nmb_name called
;
1553 struct cli_state
*cli
;
1560 my_name
= global_myname();
1562 if (!(cli
= cli_initialise())) {
1563 return NT_STATUS_NO_MEMORY
;
1566 make_nmb_name(&calling
, my_name
, 0x0);
1567 make_nmb_name(&called
, dest_host
, 0x20);
1569 if (cli_set_port(cli
, port
) != port
) {
1571 return NT_STATUS_UNSUCCESSFUL
;
1574 cli_set_timeout(cli
, 10000); /* 10 seconds. */
1583 DEBUG(3,("Connecting to host=%s\n", dest_host
));
1585 nt_status
= cli_connect(cli
, dest_host
, &ip
);
1586 if (!NT_STATUS_IS_OK(nt_status
)) {
1587 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
1588 nmb_namestr(&called
), inet_ntoa(ip
), nt_errstr(nt_status
) ));
1596 if (!cli_session_request(cli
, &calling
, &called
)) {
1598 DEBUG(1,("session request to %s failed (%s)\n",
1599 called
.name
, cli_errstr(cli
)));
1600 if ((p
=strchr(called
.name
, '.')) && !is_ipaddress(called
.name
)) {
1604 if (strcmp(called
.name
, star_smbserver_name
)) {
1605 make_nmb_name(&called
, star_smbserver_name
, 0x20);
1608 return NT_STATUS_BAD_NETWORK_NAME
;
1611 cli_setup_signing_state(cli
, signing_state
);
1613 if (flags
& CLI_FULL_CONNECTION_DONT_SPNEGO
)
1614 cli
->use_spnego
= False
;
1615 else if (flags
& CLI_FULL_CONNECTION_USE_KERBEROS
)
1616 cli
->use_kerberos
= True
;
1618 if (!cli_negprot(cli
)) {
1619 DEBUG(1,("failed negprot\n"));
1620 nt_status
= cli_nt_error(cli
);
1621 if (NT_STATUS_IS_OK(nt_status
)) {
1622 nt_status
= NT_STATUS_UNSUCCESSFUL
;
1629 return NT_STATUS_OK
;
1634 establishes a connection right up to doing tconX, password specified.
1635 @param output_cli A fully initialised cli structure, non-null only on success
1636 @param dest_host The netbios name of the remote host
1637 @param dest_ip (optional) The the destination IP, NULL for name based lookup
1638 @param port (optional) The destination port (0 for default)
1639 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
1640 @param service_type The 'type' of serivice.
1641 @param user Username, unix string
1642 @param domain User's domain
1643 @param password User's password, unencrypted unix string.
1644 @param retry BOOL. Did this connection fail with a retryable error ?
1647 NTSTATUS
cli_full_connection(struct cli_state
**output_cli
,
1648 const char *my_name
,
1649 const char *dest_host
,
1650 struct in_addr
*dest_ip
, int port
,
1651 const char *service
, const char *service_type
,
1652 const char *user
, const char *domain
,
1653 const char *password
, int flags
,
1658 struct cli_state
*cli
= NULL
;
1659 int pw_len
= password
? strlen(password
)+1 : 0;
1663 if (password
== NULL
) {
1667 nt_status
= cli_start_connection(&cli
, my_name
, dest_host
,
1668 dest_ip
, port
, signing_state
, flags
, retry
);
1670 if (!NT_STATUS_IS_OK(nt_status
)) {
1674 nt_status
= cli_session_setup(cli
, user
, password
, pw_len
, password
,
1676 if (!NT_STATUS_IS_OK(nt_status
)) {
1678 if (!(flags
& CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK
)) {
1679 DEBUG(1,("failed session setup with %s\n",
1680 nt_errstr(nt_status
)));
1685 nt_status
= cli_session_setup(cli
, "", "", 0, "", 0, domain
);
1686 if (!NT_STATUS_IS_OK(nt_status
)) {
1687 DEBUG(1,("anonymous failed session setup with %s\n",
1688 nt_errstr(nt_status
)));
1695 if (!cli_send_tconX(cli
, service
, service_type
, password
, pw_len
)) {
1696 nt_status
= cli_nt_error(cli
);
1697 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status
)));
1699 if (NT_STATUS_IS_OK(nt_status
)) {
1700 nt_status
= NT_STATUS_UNSUCCESSFUL
;
1706 cli_init_creds(cli
, user
, domain
, password
);
1709 return NT_STATUS_OK
;
1712 /****************************************************************************
1713 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
1714 ****************************************************************************/
1716 BOOL
attempt_netbios_session_request(struct cli_state
**ppcli
, const char *srchost
, const char *desthost
,
1717 struct in_addr
*pdest_ip
)
1719 struct nmb_name calling
, called
;
1721 make_nmb_name(&calling
, srchost
, 0x0);
1724 * If the called name is an IP address
1725 * then use *SMBSERVER immediately.
1728 if(is_ipaddress(desthost
)) {
1729 make_nmb_name(&called
, star_smbserver_name
, 0x20);
1731 make_nmb_name(&called
, desthost
, 0x20);
1734 if (!cli_session_request(*ppcli
, &calling
, &called
)) {
1736 struct nmb_name smbservername
;
1738 make_nmb_name(&smbservername
, star_smbserver_name
, 0x20);
1741 * If the name wasn't *SMBSERVER then
1742 * try with *SMBSERVER if the first name fails.
1745 if (nmb_name_equal(&called
, &smbservername
)) {
1748 * The name used was *SMBSERVER, don't bother with another name.
1751 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
1752 with error %s.\n", desthost
, cli_errstr(*ppcli
) ));
1757 cli_shutdown(*ppcli
);
1759 *ppcli
= cli_initialise();
1761 /* Out of memory... */
1765 status
= cli_connect(*ppcli
, desthost
, pdest_ip
);
1766 if (!NT_STATUS_IS_OK(status
) ||
1767 !cli_session_request(*ppcli
, &calling
, &smbservername
)) {
1768 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
1769 name *SMBSERVER with error %s\n", desthost
, cli_errstr(*ppcli
) ));
1781 /****************************************************************************
1782 Send an old style tcon.
1783 ****************************************************************************/
1784 NTSTATUS
cli_raw_tcon(struct cli_state
*cli
,
1785 const char *service
, const char *pass
, const char *dev
,
1786 uint16
*max_xmit
, uint16
*tid
)
1790 if (!lp_client_plaintext_auth() && (*pass
)) {
1791 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
1793 return NT_STATUS_ACCESS_DENIED
;
1796 memset(cli
->outbuf
,'\0',smb_size
);
1797 memset(cli
->inbuf
,'\0',smb_size
);
1799 set_message(cli
->outbuf
, 0, 0, True
);
1800 SCVAL(cli
->outbuf
,smb_com
,SMBtcon
);
1801 cli_setup_packet(cli
);
1803 p
= smb_buf(cli
->outbuf
);
1804 *p
++ = 4; p
+= clistr_push(cli
, p
, service
, -1, STR_TERMINATE
| STR_NOALIGN
);
1805 *p
++ = 4; p
+= clistr_push(cli
, p
, pass
, -1, STR_TERMINATE
| STR_NOALIGN
);
1806 *p
++ = 4; p
+= clistr_push(cli
, p
, dev
, -1, STR_TERMINATE
| STR_NOALIGN
);
1808 cli_setup_bcc(cli
, p
);
1811 if (!cli_receive_smb(cli
)) {
1812 return NT_STATUS_UNEXPECTED_NETWORK_ERROR
;
1815 if (cli_is_error(cli
)) {
1816 return cli_nt_error(cli
);
1819 *max_xmit
= SVAL(cli
->inbuf
, smb_vwv0
);
1820 *tid
= SVAL(cli
->inbuf
, smb_vwv1
);
1822 return NT_STATUS_OK
;
1825 /* Return a cli_state pointing at the IPC$ share for the given server */
1827 struct cli_state
*get_ipc_connect(char *server
, struct in_addr
*server_ip
,
1828 struct user_auth_info
*user_info
)
1830 struct cli_state
*cli
;
1836 nt_status
= cli_full_connection(&cli
, myname
, server
, server_ip
, 0, "IPC$", "IPC",
1837 user_info
->username
, lp_workgroup(), user_info
->password
,
1838 CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK
, Undefined
, NULL
);
1840 if (NT_STATUS_IS_OK(nt_status
)) {
1842 } else if (is_ipaddress(server
)) {
1843 /* windows 9* needs a correct NMB name for connections */
1844 fstring remote_name
;
1846 if (name_status_find("*", 0, 0, *server_ip
, remote_name
)) {
1847 cli
= get_ipc_connect(remote_name
, server_ip
, user_info
);
1856 * Given the IP address of a master browser on the network, return its
1857 * workgroup and connect to it.
1859 * This function is provided to allow additional processing beyond what
1860 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
1861 * browsers and obtain each master browsers' list of domains (in case the
1862 * first master browser is recently on the network and has not yet
1863 * synchronized with other master browsers and therefore does not yet have the
1864 * entire network browse list)
1867 struct cli_state
*get_ipc_connect_master_ip(struct ip_service
* mb_ip
, pstring workgroup
, struct user_auth_info
*user_info
)
1869 static fstring name
;
1870 struct cli_state
*cli
;
1871 struct in_addr server_ip
;
1873 DEBUG(99, ("Looking up name of master browser %s\n",
1874 inet_ntoa(mb_ip
->ip
)));
1877 * Do a name status query to find out the name of the master browser.
1878 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
1879 * master browser will not respond to a wildcard query (or, at least,
1880 * an NT4 server acting as the domain master browser will not).
1882 * We might be able to use ONLY the query on MSBROWSE, but that's not
1883 * yet been tested with all Windows versions, so until it is, leave
1884 * the original wildcard query as the first choice and fall back to
1885 * MSBROWSE if the wildcard query fails.
1887 if (!name_status_find("*", 0, 0x1d, mb_ip
->ip
, name
) &&
1888 !name_status_find(MSBROWSE
, 1, 0x1d, mb_ip
->ip
, name
)) {
1890 DEBUG(99, ("Could not retrieve name status for %s\n",
1891 inet_ntoa(mb_ip
->ip
)));
1895 if (!find_master_ip(name
, &server_ip
)) {
1896 DEBUG(99, ("Could not find master ip for %s\n", name
));
1900 pstrcpy(workgroup
, name
);
1902 DEBUG(4, ("found master browser %s, %s\n",
1903 name
, inet_ntoa(mb_ip
->ip
)));
1905 cli
= get_ipc_connect(inet_ntoa(server_ip
), &server_ip
, user_info
);
1912 * Return the IP address and workgroup of a master browser on the network, and
1916 struct cli_state
*get_ipc_connect_master_ip_bcast(pstring workgroup
, struct user_auth_info
*user_info
)
1918 struct ip_service
*ip_list
;
1919 struct cli_state
*cli
;
1922 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
1924 /* Go looking for workgroups by broadcasting on the local network */
1926 if (!name_resolve_bcast(MSBROWSE
, 1, &ip_list
, &count
)) {
1927 DEBUG(99, ("No master browsers responded\n"));
1931 for (i
= 0; i
< count
; i
++) {
1932 DEBUG(99, ("Found master browser %s\n", inet_ntoa(ip_list
[i
].ip
)));
1934 cli
= get_ipc_connect_master_ip(&ip_list
[i
], workgroup
, user_info
);