mount.cifs: check access of credential files before opening
[Samba.git] / source / libsmb / cliconnect.c
blob519d392e8ab78e4b41c4f4092b78b3eee46e215a
1 /*
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.
22 #include "includes.h"
24 extern pstring user_socket_options;
26 static const struct {
27 int prot;
28 const char *name;
29 } prots[] = {
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"},
40 {-1,NULL}
43 static const char *star_smbserver_name = "*SMBSERVER";
45 /**
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,
62 const char *user,
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);
68 fstring pword;
69 char *p;
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))
84 passlen = 0;
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);
143 return NT_STATUS_OK;
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));
161 return capabilities;
164 /****************************************************************************
165 Do a NT1 guest session setup.
166 ****************************************************************************/
168 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
170 char *p;
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, "");
216 return NT_STATUS_OK;
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);
228 char *p;
229 fstring lanman;
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)));
252 } else {
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;
291 return NT_STATUS_OK;
294 /****************************************************************************
295 do a NT1 NTLM/LM encrypted session setup - for when extended security
296 is not negotiated.
297 @param cli client state to create do session setup on
298 @param user username
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);
313 NTSTATUS result;
314 char *p;
316 if (passlen == 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
326 dodgy...
328 names_blob = NTLMv2_generate_names_blob(cli->called.name, workgroup);
330 if (!SMBNTLMv2encrypt(user, workgroup, pass, &server_chal,
331 &names_blob,
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);
340 } else {
341 uchar nt_hash[16];
342 E_md4hash(pass, nt_hash);
344 #ifdef LANMAN_ONLY
345 nt_response = data_blob(NULL, 0);
346 #else
347 nt_response = data_blob(NULL, 24);
348 SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
349 #endif
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);
359 } else {
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);
365 #ifdef LANMAN_ONLY
366 E_deshash(pass, session_key.data);
367 memset(&session_key.data[8], '\0', 8);
368 #else
369 SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
370 #endif
372 #ifdef LANMAN_ONLY
373 cli_simple_set_signing(cli, session_key, lm_response);
374 #else
375 cli_simple_set_signing(cli, session_key, nt_response);
376 #endif
377 } else {
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);
418 goto end;
421 /* show_msg(cli->inbuf); */
423 if (cli_is_error(cli)) {
424 result = cli_nt_error(cli);
425 goto end;
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;
448 end:
449 data_blob_free(&lm_response);
450 data_blob_free(&nt_response);
451 data_blob_free(&session_key);
452 return result;
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);
462 char *p;
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);
483 p += 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);
497 char *p;
498 size_t len;
500 if (!cli_receive_smb(cli))
501 return blob2;
503 show_msg(cli->inbuf);
505 if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli),
506 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
507 return blob2;
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));
517 p += blob2.length;
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);
524 return blob2;
527 #ifdef HAVE_KRB5
528 /****************************************************************************
529 Send a extended security session setup blob, returning a reply blob.
530 ****************************************************************************/
532 /* The following is calculated from :
533 * (smb_size-4) = 35
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
536 * end of packet.
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;
544 int32 cur = 0;
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);
555 return False;
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;
564 } else {
565 send_blob.length = remaining;
566 remaining = 0;
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"));
579 return False;
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)) ));
590 cli->vuid = 0;
591 return False;
595 return True;
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);
615 NTSTATUS nt_status;
616 BOOL res;
617 int rc;
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);
626 if (rc) {
627 DEBUG(1, ("cli_session_setup_kerberos: spnego_gen_negTokenTarg failed: %s\n",
628 error_message(rc)));
629 return ADS_ERROR_KRB5(rc);
632 #if 0
633 file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
634 #endif
636 if (!cli_session_setup_blob(cli, negTokenTarg)) {
637 nt_status = cli_nt_error(cli);
638 goto nt_error;
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;
646 goto nt_error;
649 cli_set_session_key(cli, session_key_krb5);
651 res = cli_simple_set_signing(cli, session_key_krb5, null_blob);
652 if (res) {
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;
659 goto nt_error;
663 data_blob_free(&negTokenTarg);
664 data_blob_free(&session_key_krb5);
666 return ADS_ERROR_NT(NT_STATUS_OK);
668 nt_error:
669 data_blob_free(&negTokenTarg);
670 data_blob_free(&session_key_krb5);
671 cli->vuid = 0;
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;
685 NTSTATUS nt_status;
686 int turn = 1;
687 DATA_BLOB msg1;
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))) {
695 return nt_status;
697 ntlmssp_want_feature(ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
699 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
700 return nt_status;
702 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
703 return nt_status;
705 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
706 return nt_status;
709 do {
710 nt_status = ntlmssp_update(ntlmssp_state,
711 blob_in, &blob_out);
712 data_blob_free(&blob_in);
713 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(nt_status)) {
714 if (turn == 1) {
715 /* and wrap it in a SPNEGO wrapper */
716 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
717 } else {
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;
726 } else {
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;
733 } else {
734 nt_status = NT_STATUS_UNSUCCESSFUL;
738 data_blob_free(&msg1);
741 if (!blob.length) {
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,
750 &tmp_blob)) {
751 DEBUG(3,("Failed to parse challenges\n"));
752 nt_status = NT_STATUS_INVALID_PARAMETER;
754 data_blob_free(&tmp_blob);
755 } else {
756 if (!spnego_parse_auth_response(blob, nt_status,
757 &blob_in)) {
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);
766 turn++;
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);
776 BOOL res;
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);
785 if (res) {
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)) {
803 cli->vuid = 0;
805 return 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];
821 int i;
822 BOOL got_kerberos_mechanism = False;
823 DATA_BLOB blob;
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"));
830 goto ntlmssp;
833 #if 0
834 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
835 #endif
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;
857 free(OIDs[i]);
860 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
862 fstrcpy(cli->user_name, user);
864 #ifdef HAVE_KRB5
865 /* If password is set we reauthenticate to kerberos server
866 * and do not store results */
868 if (got_kerberos_mechanism && cli->use_kerberos) {
869 ADS_STATUS rc;
871 if (pass && *pass) {
872 int ret;
874 use_in_memory_ccache();
875 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
877 if (ret){
878 SAFE_FREE(principal);
879 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
880 if (cli->fallback_after_kerberos)
881 goto ntlmssp;
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,
895 cli->desthost)) {
896 char *realm = NULL;
897 char *machine = NULL;
898 char *host = NULL;
899 DEBUG(3,("cli_session_setup_spnego: got a "
900 "bad server principal, trying to guess ...\n"));
902 host = strchr_m(cli->desthost, '.');
903 if (host) {
904 machine = SMB_STRNDUP(cli->desthost,
905 host - cli->desthost);
906 } else {
907 machine = SMB_STRDUP(cli->desthost);
909 if (machine == NULL) {
910 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
913 if (dest_realm) {
914 realm = SMB_STRDUP(dest_realm);
915 strupper_m(realm);
916 } else {
917 realm = kerberos_get_default_realm_from_ccache();
919 if (realm && *realm) {
920 if (asprintf(&principal, "%s$@%s",
921 machine, realm) < 0) {
922 SAFE_FREE(machine);
923 SAFE_FREE(realm);
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>"));
930 SAFE_FREE(machine);
931 SAFE_FREE(realm);
934 if (principal) {
935 rc = cli_session_setup_kerberos(cli, principal,
936 dest_realm);
937 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
938 SAFE_FREE(principal);
939 return rc;
943 #endif
945 SAFE_FREE(principal);
947 ntlmssp:
949 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, user, pass,
950 user_domain));
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,
960 const char *user,
961 const char *pass, int passlen,
962 const char *ntpass, int ntpasslen,
963 const char *workgroup)
965 char *p;
966 fstring user2;
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()))) {
972 *p = 0;
973 user = p+1;
974 workgroup = user2;
977 if (cli->protocol < PROTOCOL_LANMAN1) {
978 return NT_STATUS_OK;
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'"
990 " is disabled\n"));
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'"
997 " is disabled\n"));
998 return NT_STATUS_ACCESS_DENIED;
1001 return cli_session_setup_lanman2(cli, user, pass, passlen,
1002 workgroup);
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
1013 connect */
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'"
1024 " is disabled\n"));
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,
1034 workgroup, NULL);
1035 if (!ADS_ERR_OK(status)) {
1036 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1037 return ads_ntstatus(status);
1039 } else {
1040 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)));
1048 return status;
1052 if (strstr(cli->server_type, "Samba")) {
1053 cli->is_samba = True;
1056 return NT_STATUS_OK;
1059 /****************************************************************************
1060 Send a uloggoff.
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 */
1072 cli_send_smb(cli);
1073 if (!cli_receive_smb(cli))
1074 return False;
1076 if (cli_is_error(cli)) {
1077 return False;
1080 cli->cnum = -1;
1081 return True;
1084 /****************************************************************************
1085 Send a tconX.
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;
1092 char *p;
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) {
1100 passlen = 1;
1101 pass = "";
1102 } else if (!pass) {
1103 DEBUG(1, ("Server not using user level security and no password supplied.\n"));
1104 return False;
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'"
1111 " is disabled\n"));
1112 return False;
1116 * Non-encrypted passwords - convert to DOS codepage before encryption.
1118 passlen = 24;
1119 SMBencrypt(pass,cli->secblob.data,(uchar *)pword);
1120 } else {
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'"
1124 " is disabled\n"));
1125 return False;
1129 * Non-encrypted passwords - convert to DOS codepage before using.
1131 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
1133 } else {
1134 if (passlen) {
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);
1152 if (passlen) {
1153 memcpy(p,pword,passlen);
1155 p += 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);
1161 cli_send_smb(cli);
1162 if (!cli_receive_smb(cli))
1163 return False;
1165 if (cli_is_error(cli))
1166 return False;
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 */
1173 cli->win95 = True;
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);
1184 return True;
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);
1199 cli_send_smb(cli);
1200 if (!cli_receive_smb(cli))
1201 return False;
1203 if (cli_is_error(cli)) {
1204 return False;
1207 cli->cnum = -1;
1208 return True;
1211 /****************************************************************************
1212 Send a negprot command.
1213 ****************************************************************************/
1215 void cli_negprot_send(struct cli_state *cli)
1217 char *p;
1218 int numprots;
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);
1229 for (numprots=0;
1230 prots[numprots].name && prots[numprots].prot<=cli->protocol;
1231 numprots++) {
1232 *p++ = 2;
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);
1242 cli_send_smb(cli);
1245 /****************************************************************************
1246 Send a negprot command.
1247 ****************************************************************************/
1249 BOOL cli_negprot(struct cli_state *cli)
1251 char *p;
1252 int numprots;
1253 int plength;
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;
1263 numprots++)
1264 plength += strlen(prots[numprots].name)+2;
1266 set_message(cli->outbuf,0,plength,True);
1268 p = smb_buf(cli->outbuf);
1269 for (numprots=0;
1270 prots[numprots].name && prots[numprots].prot<=cli->protocol;
1271 numprots++) {
1272 *p++ = 2;
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);
1281 cli_send_smb(cli);
1282 if (!cli_receive_smb(cli))
1283 return False;
1285 show_msg(cli->inbuf);
1287 if (cli_is_error(cli) ||
1288 ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
1289 return(False);
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"));
1296 return False;
1299 if (cli->protocol >= PROTOCOL_NT1) {
1300 struct timespec ts;
1301 /* NT protocol */
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"));
1334 return False;
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"));
1342 return False;
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));
1371 } else {
1372 /* the old core protocol */
1373 cli->use_spnego = False;
1374 cli->sec_mode = 0;
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;
1384 return True;
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)
1394 char *p;
1395 int len = 4;
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);
1403 len += name_len(p);
1405 /* and my name */
1406 p = cli->outbuf+len;
1407 name_mangle(cli->calling.name, p, cli->calling.name_type);
1408 len += name_len(p);
1410 /* 445 doesn't have session request */
1411 if (cli->port == 445)
1412 return True;
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.
1420 * CRH.
1422 len -= 4;
1423 _smb_setlen(cli->outbuf,len);
1424 SCVAL(cli->outbuf,0,0x81);
1426 cli_send_smb(cli);
1427 DEBUG(5,("Sent session request\n"));
1429 if (!cli_receive_smb(cli))
1430 return False;
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{
1437 unsigned char type;
1438 unsigned char flags;
1439 int16 length;
1440 int32 ip_addr;
1441 int16 port;
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);
1449 if (cli->fd == -1)
1450 return False;
1452 DEBUG(3,("Retargeted\n"));
1454 set_socket_options(cli->fd,user_socket_options);
1456 /* Try again */
1458 static int depth;
1459 BOOL ret;
1460 if (depth > 4) {
1461 DEBUG(0,("Retarget recursion - failing\n"));
1462 return False;
1464 depth++;
1465 ret = cli_session_request(cli, calling, called);
1466 depth--;
1467 return ret;
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);
1474 return False;
1476 return(True);
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;
1486 char *p;
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);
1496 *p = 0;
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;
1504 } else {
1505 cli->dest_ip = *ip;
1508 if (getenv("LIBSMB_PROG")) {
1509 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
1510 } else {
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) {
1516 port = 139;
1517 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
1518 port, cli->timeout);
1520 if (cli->fd != -1)
1521 cli->port = port;
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,
1548 BOOL *retry)
1550 NTSTATUS nt_status;
1551 struct nmb_name calling;
1552 struct nmb_name called;
1553 struct cli_state *cli;
1554 struct in_addr ip;
1556 if (retry)
1557 *retry = False;
1559 if (!my_name)
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) {
1570 cli_shutdown(cli);
1571 return NT_STATUS_UNSUCCESSFUL;
1574 cli_set_timeout(cli, 10000); /* 10 seconds. */
1576 if (dest_ip)
1577 ip = *dest_ip;
1578 else
1579 ZERO_STRUCT(ip);
1581 again:
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) ));
1589 cli_shutdown(cli);
1590 return nt_status;
1593 if (retry)
1594 *retry = True;
1596 if (!cli_session_request(cli, &calling, &called)) {
1597 char *p;
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)) {
1601 *p = 0;
1602 goto again;
1604 if (strcmp(called.name, star_smbserver_name)) {
1605 make_nmb_name(&called , star_smbserver_name, 0x20);
1606 goto again;
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;
1624 cli_shutdown(cli);
1625 return nt_status;
1628 *output_cli = cli;
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,
1654 int signing_state,
1655 BOOL *retry)
1657 NTSTATUS nt_status;
1658 struct cli_state *cli = NULL;
1659 int pw_len = password ? strlen(password)+1 : 0;
1661 *output_cli = NULL;
1663 if (password == NULL) {
1664 password = "";
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)) {
1671 return nt_status;
1674 nt_status = cli_session_setup(cli, user, password, pw_len, password,
1675 pw_len, domain);
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)));
1681 cli_shutdown(cli);
1682 return 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)));
1689 cli_shutdown(cli);
1690 return nt_status;
1694 if (service) {
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)));
1698 cli_shutdown(cli);
1699 if (NT_STATUS_IS_OK(nt_status)) {
1700 nt_status = NT_STATUS_UNSUCCESSFUL;
1702 return nt_status;
1706 cli_init_creds(cli, user, domain, password);
1708 *output_cli = cli;
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);
1730 } else {
1731 make_nmb_name(&called, desthost, 0x20);
1734 if (!cli_session_request(*ppcli, &calling, &called)) {
1735 NTSTATUS status;
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) ));
1753 return False;
1756 /* Try again... */
1757 cli_shutdown(*ppcli);
1759 *ppcli = cli_initialise();
1760 if (!*ppcli) {
1761 /* Out of memory... */
1762 return False;
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) ));
1770 return False;
1774 return True;
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)
1788 char *p;
1790 if (!lp_client_plaintext_auth() && (*pass)) {
1791 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
1792 " is disabled\n"));
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);
1810 cli_send_smb(cli);
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;
1831 pstring myname;
1832 NTSTATUS nt_status;
1834 get_myname(myname);
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)) {
1841 return cli;
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);
1848 if (cli)
1849 return cli;
1852 return NULL;
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)));
1892 return NULL;
1895 if (!find_master_ip(name, &server_ip)) {
1896 DEBUG(99, ("Could not find master ip for %s\n", name));
1897 return NULL;
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);
1907 return cli;
1912 * Return the IP address and workgroup of a master browser on the network, and
1913 * connect to it.
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;
1920 int i, count;
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"));
1928 return False;
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);
1935 if (cli)
1936 return(cli);
1939 return NULL;