Fix bug #Bug 6090 renaming or deleting a "not matching/resolving" symlink is failing.
[Samba.git] / source3 / libsmb / cliconnect.c
bloba39e035d2acd810877df64cad06b165bb3a28a49
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 3 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, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
23 static const struct {
24 int prot;
25 const char name[24];
26 } prots[10] = {
27 {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
28 {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
29 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
30 {PROTOCOL_LANMAN1, "LANMAN1.0"},
31 {PROTOCOL_LANMAN2, "LM1.2X002"},
32 {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
33 {PROTOCOL_LANMAN2, "LANMAN2.1"},
34 {PROTOCOL_LANMAN2, "Samba"},
35 {PROTOCOL_NT1, "NT LANMAN 1.0"},
36 {PROTOCOL_NT1, "NT LM 0.12"},
39 #define STAR_SMBSERVER "*SMBSERVER"
41 /**
42 * Set the user session key for a connection
43 * @param cli The cli structure to add it too
44 * @param session_key The session key used. (A copy of this is taken for the cli struct)
48 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
50 cli->user_session_key = data_blob(session_key.data, session_key.length);
53 /****************************************************************************
54 Do an old lanman2 style session setup.
55 ****************************************************************************/
57 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
58 const char *user,
59 const char *pass, size_t passlen,
60 const char *workgroup)
62 DATA_BLOB session_key = data_blob_null;
63 DATA_BLOB lm_response = data_blob_null;
64 fstring pword;
65 char *p;
67 if (passlen > sizeof(pword)-1) {
68 return NT_STATUS_INVALID_PARAMETER;
71 /* LANMAN servers predate NT status codes and Unicode and ignore those
72 smb flags so we must disable the corresponding default capabilities
73 that would otherwise cause the Unicode and NT Status flags to be
74 set (and even returned by the server) */
76 cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
78 /* if in share level security then don't send a password now */
79 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
80 passlen = 0;
82 if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
83 /* Encrypted mode needed, and non encrypted password supplied. */
84 lm_response = data_blob(NULL, 24);
85 if (!SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data)) {
86 DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n"));
87 return NT_STATUS_ACCESS_DENIED;
89 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
90 /* Encrypted mode needed, and encrypted password supplied. */
91 lm_response = data_blob(pass, passlen);
92 } else if (passlen > 0) {
93 /* Plaintext mode needed, assume plaintext supplied. */
94 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
95 lm_response = data_blob(pass, passlen);
98 /* send a session setup command */
99 memset(cli->outbuf,'\0',smb_size);
100 cli_set_message(cli->outbuf,10, 0, True);
101 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
102 cli_setup_packet(cli);
104 SCVAL(cli->outbuf,smb_vwv0,0xFF);
105 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
106 SSVAL(cli->outbuf,smb_vwv3,2);
107 SSVAL(cli->outbuf,smb_vwv4,1);
108 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
109 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
111 p = smb_buf(cli->outbuf);
112 memcpy(p,lm_response.data,lm_response.length);
113 p += lm_response.length;
114 p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
115 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
116 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
117 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
118 cli_setup_bcc(cli, p);
120 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
121 return cli_nt_error(cli);
124 show_msg(cli->inbuf);
126 if (cli_is_error(cli)) {
127 return cli_nt_error(cli);
130 /* use the returned vuid from now on */
131 cli->vuid = SVAL(cli->inbuf,smb_uid);
132 fstrcpy(cli->user_name, user);
134 if (session_key.data) {
135 /* Have plaintext orginal */
136 cli_set_session_key(cli, session_key);
139 return NT_STATUS_OK;
142 /****************************************************************************
143 Work out suitable capabilities to offer the server.
144 ****************************************************************************/
146 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
148 uint32 capabilities = CAP_NT_SMBS;
150 if (!cli->force_dos_errors)
151 capabilities |= CAP_STATUS32;
153 if (cli->use_level_II_oplocks)
154 capabilities |= CAP_LEVEL_II_OPLOCKS;
156 capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
157 return capabilities;
160 /****************************************************************************
161 Do a NT1 guest session setup.
162 ****************************************************************************/
164 struct async_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
165 struct event_context *ev,
166 struct cli_state *cli)
168 struct async_req *result;
169 uint16_t vwv[13];
170 uint8_t *bytes;
172 SCVAL(vwv+0, 0, 0xFF);
173 SCVAL(vwv+0, 1, 0);
174 SSVAL(vwv+1, 0, 0);
175 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
176 SSVAL(vwv+3, 0, 2);
177 SSVAL(vwv+4, 0, cli->pid);
178 SIVAL(vwv+5, 0, cli->sesskey);
179 SSVAL(vwv+7, 0, 0);
180 SSVAL(vwv+8, 0, 0);
181 SSVAL(vwv+9, 0, 0);
182 SSVAL(vwv+10, 0, 0);
183 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
185 bytes = talloc_array(talloc_tos(), uint8_t, 0);
187 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
188 NULL);
189 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
190 NULL);
191 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix",
192 strlen("Unix")+1, NULL);
193 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba",
194 strlen("Samba")+1, NULL);
196 if (bytes == NULL) {
197 return NULL;
200 result = cli_request_send(mem_ctx, ev, cli, SMBsesssetupX, 0,
201 13, vwv, 0, talloc_get_size(bytes), bytes);
202 TALLOC_FREE(bytes);
203 return result;
206 NTSTATUS cli_session_setup_guest_recv(struct async_req *req)
208 struct cli_request *cli_req = talloc_get_type_abort(
209 req->private_data, struct cli_request);
210 struct cli_state *cli = cli_req->cli;
211 uint8_t wct;
212 uint16_t *vwv;
213 uint16_t num_bytes;
214 uint8_t *bytes;
215 uint8_t *p;
216 NTSTATUS status;
218 if (async_req_is_nterror(req, &status)) {
219 return status;
222 status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
223 if (!NT_STATUS_IS_OK(status)) {
224 return status;
227 p = bytes;
229 cli->vuid = SVAL(cli_req->inbuf, smb_uid);
231 p += clistr_pull(cli_req->inbuf, cli->server_os, (char *)p,
232 sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE);
233 p += clistr_pull(cli_req->inbuf, cli->server_type, (char *)p,
234 sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE);
235 p += clistr_pull(cli_req->inbuf, cli->server_domain, (char *)p,
236 sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE);
238 if (strstr(cli->server_type, "Samba")) {
239 cli->is_samba = True;
242 fstrcpy(cli->user_name, "");
244 return NT_STATUS_OK;
247 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
249 TALLOC_CTX *frame = talloc_stackframe();
250 struct event_context *ev;
251 struct async_req *req;
252 NTSTATUS status;
254 if (cli->fd_event != NULL) {
256 * Can't use sync call while an async call is in flight
258 status = NT_STATUS_INVALID_PARAMETER;
259 goto fail;
262 ev = event_context_init(frame);
263 if (ev == NULL) {
264 status = NT_STATUS_NO_MEMORY;
265 goto fail;
268 req = cli_session_setup_guest_send(frame, ev, cli);
269 if (req == NULL) {
270 status = NT_STATUS_NO_MEMORY;
271 goto fail;
274 while (req->state < ASYNC_REQ_DONE) {
275 event_loop_once(ev);
278 status = cli_session_setup_guest_recv(req);
279 fail:
280 TALLOC_FREE(frame);
281 return status;
284 /****************************************************************************
285 Do a NT1 plaintext session setup.
286 ****************************************************************************/
288 static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
289 const char *user, const char *pass,
290 const char *workgroup)
292 uint32 capabilities = cli_session_setup_capabilities(cli);
293 char *p;
294 fstring lanman;
296 fstr_sprintf( lanman, "Samba %s", samba_version_string());
298 memset(cli->outbuf, '\0', smb_size);
299 cli_set_message(cli->outbuf,13,0,True);
300 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
301 cli_setup_packet(cli);
303 SCVAL(cli->outbuf,smb_vwv0,0xFF);
304 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
305 SSVAL(cli->outbuf,smb_vwv3,2);
306 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
307 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
308 SSVAL(cli->outbuf,smb_vwv8,0);
309 SIVAL(cli->outbuf,smb_vwv11,capabilities);
310 p = smb_buf(cli->outbuf);
312 /* check wether to send the ASCII or UNICODE version of the password */
314 if ( (capabilities & CAP_UNICODE) == 0 ) {
315 p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
316 SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
318 else {
319 /* For ucs2 passwords clistr_push calls ucs2_align, which causes
320 * the space taken by the unicode password to be one byte too
321 * long (as we're on an odd byte boundary here). Reduce the
322 * count by 1 to cope with this. Fixes smbclient against NetApp
323 * servers which can't cope. Fix from
324 * bryan.kolodziej@allenlund.com in bug #3840.
326 p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
327 SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))-1);
330 p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
331 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
332 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
333 p += clistr_push(cli, p, lanman, -1, STR_TERMINATE);
334 cli_setup_bcc(cli, p);
336 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
337 return cli_nt_error(cli);
340 show_msg(cli->inbuf);
342 if (cli_is_error(cli)) {
343 return cli_nt_error(cli);
346 cli->vuid = SVAL(cli->inbuf,smb_uid);
347 p = smb_buf(cli->inbuf);
348 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
349 -1, STR_TERMINATE);
350 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
351 -1, STR_TERMINATE);
352 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
353 -1, STR_TERMINATE);
354 fstrcpy(cli->user_name, user);
356 if (strstr(cli->server_type, "Samba")) {
357 cli->is_samba = True;
360 return NT_STATUS_OK;
363 /****************************************************************************
364 do a NT1 NTLM/LM encrypted session setup - for when extended security
365 is not negotiated.
366 @param cli client state to create do session setup on
367 @param user username
368 @param pass *either* cleartext password (passlen !=24) or LM response.
369 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
370 @param workgroup The user's domain.
371 ****************************************************************************/
373 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
374 const char *pass, size_t passlen,
375 const char *ntpass, size_t ntpasslen,
376 const char *workgroup)
378 uint32 capabilities = cli_session_setup_capabilities(cli);
379 DATA_BLOB lm_response = data_blob_null;
380 DATA_BLOB nt_response = data_blob_null;
381 DATA_BLOB session_key = data_blob_null;
382 NTSTATUS result;
383 char *p;
385 if (passlen == 0) {
386 /* do nothing - guest login */
387 } else if (passlen != 24) {
388 if (lp_client_ntlmv2_auth()) {
389 DATA_BLOB server_chal;
390 DATA_BLOB names_blob;
391 server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8));
393 /* note that the 'workgroup' here is a best guess - we don't know
394 the server's domain at this point. The 'server name' is also
395 dodgy...
397 names_blob = NTLMv2_generate_names_blob(cli->called.name, workgroup);
399 if (!SMBNTLMv2encrypt(user, workgroup, pass, &server_chal,
400 &names_blob,
401 &lm_response, &nt_response, &session_key)) {
402 data_blob_free(&names_blob);
403 data_blob_free(&server_chal);
404 return NT_STATUS_ACCESS_DENIED;
406 data_blob_free(&names_blob);
407 data_blob_free(&server_chal);
409 } else {
410 uchar nt_hash[16];
411 E_md4hash(pass, nt_hash);
413 #ifdef LANMAN_ONLY
414 nt_response = data_blob_null;
415 #else
416 nt_response = data_blob(NULL, 24);
417 SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
418 #endif
419 /* non encrypted password supplied. Ignore ntpass. */
420 if (lp_client_lanman_auth()) {
421 lm_response = data_blob(NULL, 24);
422 if (!SMBencrypt(pass,cli->secblob.data, lm_response.data)) {
423 /* Oops, the LM response is invalid, just put
424 the NT response there instead */
425 data_blob_free(&lm_response);
426 lm_response = data_blob(nt_response.data, nt_response.length);
428 } else {
429 /* LM disabled, place NT# in LM field instead */
430 lm_response = data_blob(nt_response.data, nt_response.length);
433 session_key = data_blob(NULL, 16);
434 #ifdef LANMAN_ONLY
435 E_deshash(pass, session_key.data);
436 memset(&session_key.data[8], '\0', 8);
437 #else
438 SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
439 #endif
441 #ifdef LANMAN_ONLY
442 cli_simple_set_signing(cli, session_key, lm_response);
443 #else
444 cli_simple_set_signing(cli, session_key, nt_response);
445 #endif
446 } else {
447 /* pre-encrypted password supplied. Only used for
448 security=server, can't do
449 signing because we don't have original key */
451 lm_response = data_blob(pass, passlen);
452 nt_response = data_blob(ntpass, ntpasslen);
455 /* send a session setup command */
456 memset(cli->outbuf,'\0',smb_size);
458 cli_set_message(cli->outbuf,13,0,True);
459 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
460 cli_setup_packet(cli);
462 SCVAL(cli->outbuf,smb_vwv0,0xFF);
463 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
464 SSVAL(cli->outbuf,smb_vwv3,2);
465 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
466 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
467 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
468 SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
469 SIVAL(cli->outbuf,smb_vwv11,capabilities);
470 p = smb_buf(cli->outbuf);
471 if (lm_response.length) {
472 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
474 if (nt_response.length) {
475 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
477 p += clistr_push(cli, p, user, -1, STR_TERMINATE);
479 /* Upper case here might help some NTLMv2 implementations */
480 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
481 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
482 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
483 cli_setup_bcc(cli, p);
485 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
486 result = cli_nt_error(cli);
487 goto end;
490 /* show_msg(cli->inbuf); */
492 if (cli_is_error(cli)) {
493 result = cli_nt_error(cli);
494 goto end;
497 /* use the returned vuid from now on */
498 cli->vuid = SVAL(cli->inbuf,smb_uid);
500 p = smb_buf(cli->inbuf);
501 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
502 -1, STR_TERMINATE);
503 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
504 -1, STR_TERMINATE);
505 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
506 -1, STR_TERMINATE);
508 if (strstr(cli->server_type, "Samba")) {
509 cli->is_samba = True;
512 fstrcpy(cli->user_name, user);
514 if (session_key.data) {
515 /* Have plaintext orginal */
516 cli_set_session_key(cli, session_key);
519 result = NT_STATUS_OK;
520 end:
521 data_blob_free(&lm_response);
522 data_blob_free(&nt_response);
523 data_blob_free(&session_key);
524 return result;
527 /****************************************************************************
528 Send a extended security session setup blob
529 ****************************************************************************/
531 static bool cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob)
533 uint32 capabilities = cli_session_setup_capabilities(cli);
534 char *p;
536 capabilities |= CAP_EXTENDED_SECURITY;
538 /* send a session setup command */
539 memset(cli->outbuf,'\0',smb_size);
541 cli_set_message(cli->outbuf,12,0,True);
542 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
544 cli_setup_packet(cli);
546 SCVAL(cli->outbuf,smb_vwv0,0xFF);
547 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
548 SSVAL(cli->outbuf,smb_vwv3,2);
549 SSVAL(cli->outbuf,smb_vwv4,1);
550 SIVAL(cli->outbuf,smb_vwv5,0);
551 SSVAL(cli->outbuf,smb_vwv7,blob.length);
552 SIVAL(cli->outbuf,smb_vwv10,capabilities);
553 p = smb_buf(cli->outbuf);
554 memcpy(p, blob.data, blob.length);
555 p += blob.length;
556 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
557 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
558 cli_setup_bcc(cli, p);
559 return cli_send_smb(cli);
562 /****************************************************************************
563 Send a extended security session setup blob, returning a reply blob.
564 ****************************************************************************/
566 static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli)
568 DATA_BLOB blob2 = data_blob_null;
569 char *p;
570 size_t len;
572 if (!cli_receive_smb(cli))
573 return blob2;
575 show_msg(cli->inbuf);
577 if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli),
578 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
579 return blob2;
582 /* use the returned vuid from now on */
583 cli->vuid = SVAL(cli->inbuf,smb_uid);
585 p = smb_buf(cli->inbuf);
587 blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3));
589 p += blob2.length;
590 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
591 -1, STR_TERMINATE);
593 /* w2k with kerberos doesn't properly null terminate this field */
594 len = smb_bufrem(cli->inbuf, p);
595 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
596 len, 0);
598 return blob2;
601 #ifdef HAVE_KRB5
602 /****************************************************************************
603 Send a extended security session setup blob, returning a reply blob.
604 ****************************************************************************/
606 /* The following is calculated from :
607 * (smb_size-4) = 35
608 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
609 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
610 * end of packet.
613 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
615 static bool cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
617 int32 remaining = blob.length;
618 int32 cur = 0;
619 DATA_BLOB send_blob = data_blob_null;
620 int32 max_blob_size = 0;
621 DATA_BLOB receive_blob = data_blob_null;
623 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
624 DEBUG(0,("cli_session_setup_blob: cli->max_xmit too small "
625 "(was %u, need minimum %u)\n",
626 (unsigned int)cli->max_xmit,
627 BASE_SESSSETUP_BLOB_PACKET_SIZE));
628 cli_set_nt_error(cli, NT_STATUS_INVALID_PARAMETER);
629 return False;
632 max_blob_size = cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE;
634 while ( remaining > 0) {
635 if (remaining >= max_blob_size) {
636 send_blob.length = max_blob_size;
637 remaining -= max_blob_size;
638 } else {
639 send_blob.length = remaining;
640 remaining = 0;
643 send_blob.data = &blob.data[cur];
644 cur += send_blob.length;
646 DEBUG(10, ("cli_session_setup_blob: Remaining (%u) sending (%u) current (%u)\n",
647 (unsigned int)remaining,
648 (unsigned int)send_blob.length,
649 (unsigned int)cur ));
651 if (!cli_session_setup_blob_send(cli, send_blob)) {
652 DEBUG(0, ("cli_session_setup_blob: send failed\n"));
653 return False;
656 receive_blob = cli_session_setup_blob_receive(cli);
657 data_blob_free(&receive_blob);
659 if (cli_is_error(cli) &&
660 !NT_STATUS_EQUAL( cli_get_nt_error(cli),
661 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
662 DEBUG(0, ("cli_session_setup_blob: receive failed "
663 "(%s)\n", nt_errstr(cli_get_nt_error(cli))));
664 cli->vuid = 0;
665 return False;
669 return True;
672 /****************************************************************************
673 Use in-memory credentials cache
674 ****************************************************************************/
676 static void use_in_memory_ccache(void) {
677 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
680 /****************************************************************************
681 Do a spnego/kerberos encrypted session setup.
682 ****************************************************************************/
684 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
686 DATA_BLOB negTokenTarg;
687 DATA_BLOB session_key_krb5;
688 NTSTATUS nt_status;
689 int rc;
691 cli_temp_set_signing(cli);
693 DEBUG(2,("Doing kerberos session setup\n"));
695 /* generate the encapsulated kerberos5 ticket */
696 rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5, 0, NULL);
698 if (rc) {
699 DEBUG(1, ("cli_session_setup_kerberos: spnego_gen_negTokenTarg failed: %s\n",
700 error_message(rc)));
701 return ADS_ERROR_KRB5(rc);
704 #if 0
705 file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
706 #endif
708 if (!cli_session_setup_blob(cli, negTokenTarg)) {
709 nt_status = cli_nt_error(cli);
710 goto nt_error;
713 if (cli_is_error(cli)) {
714 nt_status = cli_nt_error(cli);
715 if (NT_STATUS_IS_OK(nt_status)) {
716 nt_status = NT_STATUS_UNSUCCESSFUL;
718 goto nt_error;
721 cli_set_session_key(cli, session_key_krb5);
723 if (cli_simple_set_signing(
724 cli, session_key_krb5, data_blob_null)) {
726 /* 'resign' the last message, so we get the right sequence numbers
727 for checking the first reply from the server */
728 cli_calculate_sign_mac(cli, cli->outbuf);
730 if (!cli_check_sign_mac(cli, cli->inbuf)) {
731 nt_status = NT_STATUS_ACCESS_DENIED;
732 goto nt_error;
736 data_blob_free(&negTokenTarg);
737 data_blob_free(&session_key_krb5);
739 return ADS_ERROR_NT(NT_STATUS_OK);
741 nt_error:
742 data_blob_free(&negTokenTarg);
743 data_blob_free(&session_key_krb5);
744 cli->vuid = 0;
745 return ADS_ERROR_NT(nt_status);
747 #endif /* HAVE_KRB5 */
750 /****************************************************************************
751 Do a spnego/NTLMSSP encrypted session setup.
752 ****************************************************************************/
754 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
755 const char *pass, const char *domain)
757 struct ntlmssp_state *ntlmssp_state;
758 NTSTATUS nt_status;
759 int turn = 1;
760 DATA_BLOB msg1;
761 DATA_BLOB blob = data_blob_null;
762 DATA_BLOB blob_in = data_blob_null;
763 DATA_BLOB blob_out = data_blob_null;
765 cli_temp_set_signing(cli);
767 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
768 return nt_status;
770 ntlmssp_want_feature(ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
772 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
773 return nt_status;
775 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
776 return nt_status;
778 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
779 return nt_status;
782 do {
783 nt_status = ntlmssp_update(ntlmssp_state,
784 blob_in, &blob_out);
785 data_blob_free(&blob_in);
786 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(nt_status)) {
787 if (turn == 1) {
788 /* and wrap it in a SPNEGO wrapper */
789 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
790 } else {
791 /* wrap it in SPNEGO */
792 msg1 = spnego_gen_auth(blob_out);
795 /* now send that blob on its way */
796 if (!cli_session_setup_blob_send(cli, msg1)) {
797 DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
798 nt_status = NT_STATUS_UNSUCCESSFUL;
799 } else {
800 blob = cli_session_setup_blob_receive(cli);
802 nt_status = cli_nt_error(cli);
803 if (cli_is_error(cli) && NT_STATUS_IS_OK(nt_status)) {
804 if (cli->smb_rw_error == SMB_READ_BAD_SIG) {
805 nt_status = NT_STATUS_ACCESS_DENIED;
806 } else {
807 nt_status = NT_STATUS_UNSUCCESSFUL;
811 data_blob_free(&msg1);
814 if (!blob.length) {
815 if (NT_STATUS_IS_OK(nt_status)) {
816 nt_status = NT_STATUS_UNSUCCESSFUL;
818 } else if ((turn == 1) &&
819 NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
820 DATA_BLOB tmp_blob = data_blob_null;
821 /* the server might give us back two challenges */
822 if (!spnego_parse_challenge(blob, &blob_in,
823 &tmp_blob)) {
824 DEBUG(3,("Failed to parse challenges\n"));
825 nt_status = NT_STATUS_INVALID_PARAMETER;
827 data_blob_free(&tmp_blob);
828 } else {
829 if (!spnego_parse_auth_response(blob, nt_status, OID_NTLMSSP,
830 &blob_in)) {
831 DEBUG(3,("Failed to parse auth response\n"));
832 if (NT_STATUS_IS_OK(nt_status)
833 || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED))
834 nt_status = NT_STATUS_INVALID_PARAMETER;
837 data_blob_free(&blob);
838 data_blob_free(&blob_out);
839 turn++;
840 } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
842 data_blob_free(&blob_in);
844 if (NT_STATUS_IS_OK(nt_status)) {
846 fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
847 cli_set_session_key(cli, ntlmssp_state->session_key);
849 if (cli_simple_set_signing(
850 cli, ntlmssp_state->session_key, data_blob_null)) {
852 /* 'resign' the last message, so we get the right sequence numbers
853 for checking the first reply from the server */
854 cli_calculate_sign_mac(cli, cli->outbuf);
856 if (!cli_check_sign_mac(cli, cli->inbuf)) {
857 nt_status = NT_STATUS_ACCESS_DENIED;
862 /* we have a reference conter on ntlmssp_state, if we are signing
863 then the state will be kept by the signing engine */
865 ntlmssp_end(&ntlmssp_state);
867 if (!NT_STATUS_IS_OK(nt_status)) {
868 cli->vuid = 0;
870 return nt_status;
873 /****************************************************************************
874 Do a spnego encrypted session setup.
876 user_domain: The shortname of the domain the user/machine is a member of.
877 dest_realm: The realm we're connecting to, if NULL we use our default realm.
878 ****************************************************************************/
880 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
881 const char *pass, const char *user_domain,
882 const char * dest_realm)
884 char *principal = NULL;
885 char *OIDs[ASN1_MAX_OIDS];
886 int i;
887 DATA_BLOB blob;
888 const char *p = NULL;
889 char *account = NULL;
891 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
893 /* the server might not even do spnego */
894 if (cli->secblob.length <= 16) {
895 DEBUG(3,("server didn't supply a full spnego negprot\n"));
896 goto ntlmssp;
899 #if 0
900 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
901 #endif
903 /* there is 16 bytes of GUID before the real spnego packet starts */
904 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
906 /* The server sent us the first part of the SPNEGO exchange in the
907 * negprot reply. It is WRONG to depend on the principal sent in the
908 * negprot reply, but right now we do it. If we don't receive one,
909 * we try to best guess, then fall back to NTLM. */
910 if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
911 data_blob_free(&blob);
912 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
914 data_blob_free(&blob);
916 /* make sure the server understands kerberos */
917 for (i=0;OIDs[i];i++) {
918 DEBUG(3,("got OID=%s\n", OIDs[i]));
919 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
920 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
921 cli->got_kerberos_mechanism = True;
923 talloc_free(OIDs[i]);
926 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
928 fstrcpy(cli->user_name, user);
930 #ifdef HAVE_KRB5
931 /* If password is set we reauthenticate to kerberos server
932 * and do not store results */
934 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
935 ADS_STATUS rc;
937 if (pass && *pass) {
938 int ret;
940 use_in_memory_ccache();
941 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
943 if (ret){
944 TALLOC_FREE(principal);
945 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
946 if (cli->fallback_after_kerberos)
947 goto ntlmssp;
948 return ADS_ERROR_KRB5(ret);
952 /* If we get a bad principal, try to guess it if
953 we have a valid host NetBIOS name.
955 if (strequal(principal, ADS_IGNORE_PRINCIPAL)) {
956 TALLOC_FREE(principal);
959 if (principal == NULL &&
960 !is_ipaddress(cli->desthost) &&
961 !strequal(STAR_SMBSERVER,
962 cli->desthost)) {
963 char *realm = NULL;
964 char *machine = NULL;
965 char *host = NULL;
966 DEBUG(3,("cli_session_setup_spnego: got a "
967 "bad server principal, trying to guess ...\n"));
969 host = strchr_m(cli->desthost, '.');
970 if (host) {
971 machine = SMB_STRNDUP(cli->desthost,
972 host - cli->desthost);
973 } else {
974 machine = SMB_STRDUP(cli->desthost);
976 if (machine == NULL) {
977 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
980 if (dest_realm) {
981 realm = SMB_STRDUP(dest_realm);
982 strupper_m(realm);
983 } else {
984 realm = kerberos_get_default_realm_from_ccache();
986 if (realm && *realm) {
987 principal = talloc_asprintf(NULL, "%s$@%s",
988 machine, realm);
989 if (!principal) {
990 SAFE_FREE(machine);
991 SAFE_FREE(realm);
992 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
994 DEBUG(3,("cli_session_setup_spnego: guessed "
995 "server principal=%s\n",
996 principal ? principal : "<null>"));
998 SAFE_FREE(machine);
999 SAFE_FREE(realm);
1002 if (principal) {
1003 rc = cli_session_setup_kerberos(cli, principal,
1004 dest_realm);
1005 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1006 TALLOC_FREE(principal);
1007 return rc;
1011 #endif
1013 TALLOC_FREE(principal);
1015 ntlmssp:
1017 account = talloc_strdup(talloc_tos(), user);
1018 if (!account) {
1019 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1022 /* when falling back to ntlmssp while authenticating with a machine
1023 * account strip off the realm - gd */
1025 if ((p = strchr_m(user, '@')) != NULL) {
1026 account[PTR_DIFF(p,user)] = '\0';
1029 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1032 /****************************************************************************
1033 Send a session setup. The username and workgroup is in UNIX character
1034 format and must be converted to DOS codepage format before sending. If the
1035 password is in plaintext, the same should be done.
1036 ****************************************************************************/
1038 NTSTATUS cli_session_setup(struct cli_state *cli,
1039 const char *user,
1040 const char *pass, int passlen,
1041 const char *ntpass, int ntpasslen,
1042 const char *workgroup)
1044 char *p;
1045 fstring user2;
1047 if (user) {
1048 fstrcpy(user2, user);
1049 } else {
1050 user2[0] ='\0';
1053 if (!workgroup) {
1054 workgroup = "";
1057 /* allow for workgroups as part of the username */
1058 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1059 (p=strchr_m(user2,*lp_winbind_separator()))) {
1060 *p = 0;
1061 user = p+1;
1062 workgroup = user2;
1065 if (cli->protocol < PROTOCOL_LANMAN1) {
1066 return NT_STATUS_OK;
1069 /* now work out what sort of session setup we are going to
1070 do. I have split this into separate functions to make the
1071 flow a bit easier to understand (tridge) */
1073 /* if its an older server then we have to use the older request format */
1075 if (cli->protocol < PROTOCOL_NT1) {
1076 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1077 DEBUG(1, ("Server requested LM password but 'client lanman auth'"
1078 " is disabled\n"));
1079 return NT_STATUS_ACCESS_DENIED;
1082 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1083 !lp_client_plaintext_auth() && (*pass)) {
1084 DEBUG(1, ("Server requested plaintext password but "
1085 "'client plaintext auth' is disabled\n"));
1086 return NT_STATUS_ACCESS_DENIED;
1089 return cli_session_setup_lanman2(cli, user, pass, passlen,
1090 workgroup);
1093 /* if no user is supplied then we have to do an anonymous connection.
1094 passwords are ignored */
1096 if (!user || !*user)
1097 return cli_session_setup_guest(cli);
1099 /* if the server is share level then send a plaintext null
1100 password at this point. The password is sent in the tree
1101 connect */
1103 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
1104 return cli_session_setup_plaintext(cli, user, "", workgroup);
1106 /* if the server doesn't support encryption then we have to use
1107 plaintext. The second password is ignored */
1109 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1110 if (!lp_client_plaintext_auth() && (*pass)) {
1111 DEBUG(1, ("Server requested plaintext password but "
1112 "'client plaintext auth' is disabled\n"));
1113 return NT_STATUS_ACCESS_DENIED;
1115 return cli_session_setup_plaintext(cli, user, pass, workgroup);
1118 /* if the server supports extended security then use SPNEGO */
1120 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
1121 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
1122 workgroup, NULL);
1123 if (!ADS_ERR_OK(status)) {
1124 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1125 return ads_ntstatus(status);
1127 } else {
1128 NTSTATUS status;
1130 /* otherwise do a NT1 style session setup */
1131 status = cli_session_setup_nt1(cli, user, pass, passlen,
1132 ntpass, ntpasslen, workgroup);
1133 if (!NT_STATUS_IS_OK(status)) {
1134 DEBUG(3,("cli_session_setup: NT1 session setup "
1135 "failed: %s\n", nt_errstr(status)));
1136 return status;
1140 if (strstr(cli->server_type, "Samba")) {
1141 cli->is_samba = True;
1144 return NT_STATUS_OK;
1147 /****************************************************************************
1148 Send a uloggoff.
1149 *****************************************************************************/
1151 bool cli_ulogoff(struct cli_state *cli)
1153 memset(cli->outbuf,'\0',smb_size);
1154 cli_set_message(cli->outbuf,2,0,True);
1155 SCVAL(cli->outbuf,smb_com,SMBulogoffX);
1156 cli_setup_packet(cli);
1157 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1158 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1160 cli_send_smb(cli);
1161 if (!cli_receive_smb(cli))
1162 return False;
1164 if (cli_is_error(cli)) {
1165 return False;
1168 cli->cnum = -1;
1169 return True;
1172 /****************************************************************************
1173 Send a tconX.
1174 ****************************************************************************/
1176 struct async_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
1177 struct event_context *ev,
1178 struct cli_state *cli,
1179 const char *share, const char *dev,
1180 const char *pass, int passlen)
1182 fstring pword;
1183 char *tmp = NULL;
1184 struct async_req *result;
1185 uint16_t vwv[4];
1186 uint8_t *bytes;
1188 fstrcpy(cli->share, share);
1190 /* in user level security don't send a password now */
1191 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1192 passlen = 1;
1193 pass = "";
1194 } else if (pass == NULL) {
1195 DEBUG(1, ("Server not using user level security and no "
1196 "password supplied.\n"));
1197 goto access_denied;
1200 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1201 *pass && passlen != 24) {
1202 if (!lp_client_lanman_auth()) {
1203 DEBUG(1, ("Server requested LANMAN password "
1204 "(share-level security) but "
1205 "'client lanman auth' is disabled\n"));
1206 goto access_denied;
1210 * Non-encrypted passwords - convert to DOS codepage before
1211 * encryption.
1213 passlen = 24;
1214 SMBencrypt(pass, cli->secblob.data, (uchar *)pword);
1215 } else {
1216 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1217 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1218 == 0) {
1219 if (!lp_client_plaintext_auth() && (*pass)) {
1220 DEBUG(1, ("Server requested plaintext "
1221 "password but 'client plaintext "
1222 "auth' is disabled\n"));
1223 goto access_denied;
1227 * Non-encrypted passwords - convert to DOS codepage
1228 * before using.
1230 passlen = clistr_push(cli, pword, pass, sizeof(pword),
1231 STR_TERMINATE);
1232 if (passlen == -1) {
1233 DEBUG(1, ("clistr_push(pword) failed\n"));
1234 goto access_denied;
1236 } else {
1237 if (passlen) {
1238 memcpy(pword, pass, passlen);
1243 SCVAL(vwv+0, 0, 0xFF);
1244 SCVAL(vwv+0, 1, 0);
1245 SSVAL(vwv+1, 0, 0);
1246 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
1247 SSVAL(vwv+3, 0, passlen);
1249 if (passlen) {
1250 bytes = (uint8_t *)talloc_memdup(talloc_tos(), pword, passlen);
1251 } else {
1252 bytes = talloc_array(talloc_tos(), uint8_t, 0);
1256 * Add the sharename
1258 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1259 cli->desthost, share);
1260 if (tmp == NULL) {
1261 TALLOC_FREE(bytes);
1262 return NULL;
1264 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
1265 NULL);
1266 TALLOC_FREE(tmp);
1269 * Add the devicetype
1271 tmp = talloc_strdup_upper(talloc_tos(), dev);
1272 if (tmp == NULL) {
1273 TALLOC_FREE(bytes);
1274 return NULL;
1276 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
1277 TALLOC_FREE(tmp);
1279 if (bytes == NULL) {
1280 return NULL;
1283 result = cli_request_send(mem_ctx, ev, cli, SMBtconX, 0,
1284 4, vwv, 0, talloc_get_size(bytes), bytes);
1285 TALLOC_FREE(bytes);
1286 return result;
1288 access_denied:
1289 result = async_req_new(mem_ctx);
1290 if (async_post_ntstatus(result, ev, NT_STATUS_ACCESS_DENIED)) {
1291 return result;
1293 TALLOC_FREE(result);
1294 return NULL;
1297 NTSTATUS cli_tcon_andx_recv(struct async_req *req)
1299 struct cli_request *cli_req = talloc_get_type_abort(
1300 req->private_data, struct cli_request);
1301 struct cli_state *cli = cli_req->cli;
1302 uint8_t wct;
1303 uint16_t *vwv;
1304 uint16_t num_bytes;
1305 uint8_t *bytes;
1306 NTSTATUS status;
1308 if (async_req_is_nterror(req, &status)) {
1309 return status;
1312 status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
1313 if (!NT_STATUS_IS_OK(status)) {
1314 return status;
1317 clistr_pull(cli_req->inbuf, cli->dev, bytes, sizeof(fstring),
1318 num_bytes, STR_TERMINATE|STR_ASCII);
1320 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
1321 /* almost certainly win95 - enable bug fixes */
1322 cli->win95 = True;
1326 * Make sure that we have the optional support 16-bit field. WCT > 2.
1327 * Avoids issues when connecting to Win9x boxes sharing files
1330 cli->dfsroot = false;
1332 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
1333 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
1336 cli->cnum = SVAL(cli_req->inbuf,smb_tid);
1337 return NT_STATUS_OK;
1340 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
1341 const char *dev, const char *pass, int passlen)
1343 TALLOC_CTX *frame = talloc_stackframe();
1344 struct event_context *ev;
1345 struct async_req *req;
1346 NTSTATUS status;
1348 if (cli->fd_event != NULL) {
1350 * Can't use sync call while an async call is in flight
1352 status = NT_STATUS_INVALID_PARAMETER;
1353 goto fail;
1356 ev = event_context_init(frame);
1357 if (ev == NULL) {
1358 status = NT_STATUS_NO_MEMORY;
1359 goto fail;
1362 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
1363 if (req == NULL) {
1364 status = NT_STATUS_NO_MEMORY;
1365 goto fail;
1368 while (req->state < ASYNC_REQ_DONE) {
1369 event_loop_once(ev);
1372 status = cli_tcon_andx_recv(req);
1373 fail:
1374 TALLOC_FREE(frame);
1375 return status;
1378 /****************************************************************************
1379 Send a tree disconnect.
1380 ****************************************************************************/
1382 bool cli_tdis(struct cli_state *cli)
1384 memset(cli->outbuf,'\0',smb_size);
1385 cli_set_message(cli->outbuf,0,0,True);
1386 SCVAL(cli->outbuf,smb_com,SMBtdis);
1387 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1388 cli_setup_packet(cli);
1390 cli_send_smb(cli);
1391 if (!cli_receive_smb(cli))
1392 return False;
1394 if (cli_is_error(cli)) {
1395 return False;
1398 cli->cnum = -1;
1399 return True;
1402 /****************************************************************************
1403 Send a negprot command.
1404 ****************************************************************************/
1406 void cli_negprot_sendsync(struct cli_state *cli)
1408 char *p;
1409 int numprots;
1411 if (cli->protocol < PROTOCOL_NT1)
1412 cli->use_spnego = False;
1414 memset(cli->outbuf,'\0',smb_size);
1416 /* setup the protocol strings */
1417 cli_set_message(cli->outbuf,0,0,True);
1419 p = smb_buf(cli->outbuf);
1420 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1421 if (prots[numprots].prot > cli->protocol) {
1422 break;
1424 *p++ = 2;
1425 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1428 SCVAL(cli->outbuf,smb_com,SMBnegprot);
1429 cli_setup_bcc(cli, p);
1430 cli_setup_packet(cli);
1432 SCVAL(smb_buf(cli->outbuf),0,2);
1434 cli_send_smb(cli);
1437 /****************************************************************************
1438 Send a negprot command.
1439 ****************************************************************************/
1441 struct async_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
1442 struct event_context *ev,
1443 struct cli_state *cli)
1445 struct async_req *result;
1446 uint8_t *bytes = NULL;
1447 int numprots;
1449 if (cli->protocol < PROTOCOL_NT1)
1450 cli->use_spnego = False;
1452 /* setup the protocol strings */
1453 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1454 uint8_t c = 2;
1455 if (prots[numprots].prot > cli->protocol) {
1456 break;
1458 bytes = (uint8_t *)talloc_append_blob(
1459 talloc_tos(), bytes, data_blob_const(&c, sizeof(c)));
1460 if (bytes == NULL) {
1461 return NULL;
1463 bytes = smb_bytes_push_str(bytes, false,
1464 prots[numprots].name,
1465 strlen(prots[numprots].name)+1,
1466 NULL);
1467 if (bytes == NULL) {
1468 return NULL;
1472 result = cli_request_send(mem_ctx, ev, cli, SMBnegprot, 0, 0, NULL, 0,
1473 talloc_get_size(bytes), bytes);
1474 TALLOC_FREE(bytes);
1475 return result;
1478 NTSTATUS cli_negprot_recv(struct async_req *req)
1480 struct cli_request *cli_req = talloc_get_type_abort(
1481 req->private_data, struct cli_request);
1482 struct cli_state *cli = cli_req->cli;
1483 uint8_t wct;
1484 uint16_t *vwv;
1485 uint16_t num_bytes;
1486 uint8_t *bytes;
1487 NTSTATUS status;
1488 uint16_t protnum;
1490 if (async_req_is_nterror(req, &status)) {
1491 return status;
1494 status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
1495 if (!NT_STATUS_IS_OK(status)) {
1496 return status;
1499 protnum = SVAL(vwv, 0);
1501 if ((protnum >= ARRAY_SIZE(prots))
1502 || (prots[protnum].prot > cli_req->cli->protocol)) {
1503 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1506 cli->protocol = prots[protnum].prot;
1508 if ((cli->protocol < PROTOCOL_NT1) && cli->sign_info.mandatory_signing) {
1509 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1510 return NT_STATUS_ACCESS_DENIED;
1513 if (cli->protocol >= PROTOCOL_NT1) {
1514 struct timespec ts;
1515 /* NT protocol */
1516 cli->sec_mode = CVAL(vwv + 1, 0);
1517 cli->max_mux = SVAL(vwv + 1, 1);
1518 cli->max_xmit = IVAL(vwv + 3, 1);
1519 cli->sesskey = IVAL(vwv + 7, 1);
1520 cli->serverzone = SVALS(vwv + 15, 1);
1521 cli->serverzone *= 60;
1522 /* this time arrives in real GMT */
1523 ts = interpret_long_date(((char *)(vwv+11))+1);
1524 cli->servertime = ts.tv_sec;
1525 cli->secblob = data_blob(bytes, num_bytes);
1526 cli->capabilities = IVAL(vwv + 9, 1);
1527 if (cli->capabilities & CAP_RAW_MODE) {
1528 cli->readbraw_supported = True;
1529 cli->writebraw_supported = True;
1531 /* work out if they sent us a workgroup */
1532 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1533 smb_buflen(cli->inbuf) > 8) {
1534 clistr_pull(cli->inbuf, cli->server_domain,
1535 bytes+8, sizeof(cli->server_domain),
1536 num_bytes-8,
1537 STR_UNICODE|STR_NOALIGN);
1541 * As signing is slow we only turn it on if either the client or
1542 * the server require it. JRA.
1545 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
1546 /* Fail if server says signing is mandatory and we don't want to support it. */
1547 if (!cli->sign_info.allow_smb_signing) {
1548 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1549 return NT_STATUS_ACCESS_DENIED;
1551 cli->sign_info.negotiated_smb_signing = True;
1552 cli->sign_info.mandatory_signing = True;
1553 } else if (cli->sign_info.mandatory_signing && cli->sign_info.allow_smb_signing) {
1554 /* Fail if client says signing is mandatory and the server doesn't support it. */
1555 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
1556 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1557 return NT_STATUS_ACCESS_DENIED;
1559 cli->sign_info.negotiated_smb_signing = True;
1560 cli->sign_info.mandatory_signing = True;
1561 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
1562 cli->sign_info.negotiated_smb_signing = True;
1565 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
1566 SAFE_FREE(cli->outbuf);
1567 SAFE_FREE(cli->inbuf);
1568 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1569 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1570 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
1573 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1574 cli->use_spnego = False;
1575 cli->sec_mode = SVAL(vwv + 1, 0);
1576 cli->max_xmit = SVAL(vwv + 2, 0);
1577 cli->max_mux = SVAL(vwv + 3, 0);
1578 cli->sesskey = IVAL(vwv + 6, 0);
1579 cli->serverzone = SVALS(vwv + 10, 0);
1580 cli->serverzone *= 60;
1581 /* this time is converted to GMT by make_unix_date */
1582 cli->servertime = cli_make_unix_date(
1583 cli, (char *)(vwv + 8));
1584 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
1585 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
1586 cli->secblob = data_blob(bytes, num_bytes);
1587 } else {
1588 /* the old core protocol */
1589 cli->use_spnego = False;
1590 cli->sec_mode = 0;
1591 cli->serverzone = get_time_zone(time(NULL));
1594 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1596 /* a way to force ascii SMB */
1597 if (getenv("CLI_FORCE_ASCII"))
1598 cli->capabilities &= ~CAP_UNICODE;
1600 return NT_STATUS_OK;
1603 NTSTATUS cli_negprot(struct cli_state *cli)
1605 TALLOC_CTX *frame = talloc_stackframe();
1606 struct event_context *ev;
1607 struct async_req *req;
1608 NTSTATUS status = NT_STATUS_NO_MEMORY;
1610 if (cli->fd_event != NULL) {
1612 * Can't use sync call while an async call is in flight
1614 cli_set_error(cli, NT_STATUS_INVALID_PARAMETER);
1615 goto fail;
1618 ev = event_context_init(frame);
1619 if (ev == NULL) {
1620 goto fail;
1623 req = cli_negprot_send(frame, ev, cli);
1624 if (req == NULL) {
1625 goto fail;
1628 while (req->state < ASYNC_REQ_DONE) {
1629 event_loop_once(ev);
1632 status = cli_negprot_recv(req);
1633 fail:
1634 TALLOC_FREE(frame);
1635 return status;
1638 /****************************************************************************
1639 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1640 ****************************************************************************/
1642 bool cli_session_request(struct cli_state *cli,
1643 struct nmb_name *calling, struct nmb_name *called)
1645 char *p;
1646 int len = 4;
1648 /* 445 doesn't have session request */
1649 if (cli->port == 445)
1650 return True;
1652 memcpy(&(cli->calling), calling, sizeof(*calling));
1653 memcpy(&(cli->called ), called , sizeof(*called ));
1655 /* put in the destination name */
1656 p = cli->outbuf+len;
1657 name_mangle(cli->called .name, p, cli->called .name_type);
1658 len += name_len(p);
1660 /* and my name */
1661 p = cli->outbuf+len;
1662 name_mangle(cli->calling.name, p, cli->calling.name_type);
1663 len += name_len(p);
1665 /* send a session request (RFC 1002) */
1666 /* setup the packet length
1667 * Remove four bytes from the length count, since the length
1668 * field in the NBT Session Service header counts the number
1669 * of bytes which follow. The cli_send_smb() function knows
1670 * about this and accounts for those four bytes.
1671 * CRH.
1673 len -= 4;
1674 _smb_setlen(cli->outbuf,len);
1675 SCVAL(cli->outbuf,0,0x81);
1677 cli_send_smb(cli);
1678 DEBUG(5,("Sent session request\n"));
1680 if (!cli_receive_smb(cli))
1681 return False;
1683 if (CVAL(cli->inbuf,0) == 0x84) {
1684 /* C. Hoch 9/14/95 Start */
1685 /* For information, here is the response structure.
1686 * We do the byte-twiddling to for portability.
1687 struct RetargetResponse{
1688 unsigned char type;
1689 unsigned char flags;
1690 int16 length;
1691 int32 ip_addr;
1692 int16 port;
1695 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1696 struct in_addr dest_ip;
1697 NTSTATUS status;
1699 /* SESSION RETARGET */
1700 putip((char *)&dest_ip,cli->inbuf+4);
1701 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
1703 status = open_socket_out(&cli->dest_ss, port,
1704 LONG_CONNECT_TIMEOUT, &cli->fd);
1705 if (!NT_STATUS_IS_OK(status)) {
1706 return False;
1709 DEBUG(3,("Retargeted\n"));
1711 set_socket_options(cli->fd, lp_socket_options());
1713 /* Try again */
1715 static int depth;
1716 bool ret;
1717 if (depth > 4) {
1718 DEBUG(0,("Retarget recursion - failing\n"));
1719 return False;
1721 depth++;
1722 ret = cli_session_request(cli, calling, called);
1723 depth--;
1724 return ret;
1726 } /* C. Hoch 9/14/95 End */
1728 if (CVAL(cli->inbuf,0) != 0x82) {
1729 /* This is the wrong place to put the error... JRA. */
1730 cli->rap_error = CVAL(cli->inbuf,4);
1731 return False;
1733 return(True);
1736 static void smb_sock_connected(struct async_req *req)
1738 int *pfd = (int *)req->async.priv;
1739 int fd;
1740 NTSTATUS status;
1742 status = open_socket_out_defer_recv(req, &fd);
1743 if (NT_STATUS_IS_OK(status)) {
1744 *pfd = fd;
1748 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
1749 uint16_t *port, int timeout, int *pfd)
1751 struct event_context *ev;
1752 struct async_req *r139, *r445;
1753 int fd139 = -1;
1754 int fd445 = -1;
1755 NTSTATUS status;
1757 if (*port != 0) {
1758 return open_socket_out(pss, *port, timeout, pfd);
1761 ev = event_context_init(talloc_tos());
1762 if (ev == NULL) {
1763 return NT_STATUS_NO_MEMORY;
1766 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
1767 pss, 445, timeout);
1768 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
1769 pss, 139, timeout);
1770 if ((r445 == NULL) || (r139 == NULL)) {
1771 status = NT_STATUS_NO_MEMORY;
1772 goto done;
1774 r445->async.fn = smb_sock_connected;
1775 r445->async.priv = &fd445;
1776 r139->async.fn = smb_sock_connected;
1777 r139->async.priv = &fd139;
1779 while ((fd139 == -1) && (r139->state < ASYNC_REQ_DONE)
1780 && (fd445 == -1) && (r445->state < ASYNC_REQ_DONE)) {
1781 event_loop_once(ev);
1784 if ((fd139 != -1) && (fd445 != -1)) {
1785 close(fd139);
1786 fd139 = -1;
1789 if (fd445 != -1) {
1790 *port = 445;
1791 *pfd = fd445;
1792 status = NT_STATUS_OK;
1793 goto done;
1795 if (fd139 != -1) {
1796 *port = 139;
1797 *pfd = fd139;
1798 status = NT_STATUS_OK;
1799 goto done;
1802 status = open_socket_out_defer_recv(r445, &fd445);
1803 done:
1804 TALLOC_FREE(ev);
1805 return status;
1808 /****************************************************************************
1809 Open the client sockets.
1810 ****************************************************************************/
1812 NTSTATUS cli_connect(struct cli_state *cli,
1813 const char *host,
1814 struct sockaddr_storage *dest_ss)
1817 int name_type = 0x20;
1818 TALLOC_CTX *frame = talloc_stackframe();
1819 unsigned int num_addrs = 0;
1820 unsigned int i = 0;
1821 struct sockaddr_storage *ss_arr = NULL;
1822 char *p = NULL;
1824 /* reasonable default hostname */
1825 if (!host) {
1826 host = STAR_SMBSERVER;
1829 fstrcpy(cli->desthost, host);
1831 /* allow hostnames of the form NAME#xx and do a netbios lookup */
1832 if ((p = strchr(cli->desthost, '#'))) {
1833 name_type = strtol(p+1, NULL, 16);
1834 *p = 0;
1837 if (!dest_ss || is_zero_addr((struct sockaddr *)dest_ss)) {
1838 NTSTATUS status =resolve_name_list(frame,
1839 cli->desthost,
1840 name_type,
1841 &ss_arr,
1842 &num_addrs);
1843 if (!NT_STATUS_IS_OK(status)) {
1844 TALLOC_FREE(frame);
1845 return NT_STATUS_BAD_NETWORK_NAME;
1847 } else {
1848 num_addrs = 1;
1849 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
1850 if (!ss_arr) {
1851 TALLOC_FREE(frame);
1852 return NT_STATUS_NO_MEMORY;
1854 *ss_arr = *dest_ss;
1857 for (i = 0; i < num_addrs; i++) {
1858 cli->dest_ss = ss_arr[i];
1859 if (getenv("LIBSMB_PROG")) {
1860 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
1861 } else {
1862 uint16_t port = cli->port;
1863 NTSTATUS status;
1864 status = open_smb_socket(&cli->dest_ss, &port,
1865 cli->timeout, &cli->fd);
1866 if (NT_STATUS_IS_OK(status)) {
1867 cli->port = port;
1870 if (cli->fd == -1) {
1871 char addr[INET6_ADDRSTRLEN];
1872 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
1873 DEBUG(2,("Error connecting to %s (%s)\n",
1874 dest_ss?addr:host,strerror(errno)));
1875 } else {
1876 /* Exit from loop on first connection. */
1877 break;
1881 if (cli->fd == -1) {
1882 TALLOC_FREE(frame);
1883 return map_nt_error_from_unix(errno);
1886 if (dest_ss) {
1887 *dest_ss = cli->dest_ss;
1890 set_socket_options(cli->fd, lp_socket_options());
1892 TALLOC_FREE(frame);
1893 return NT_STATUS_OK;
1897 establishes a connection to after the negprot.
1898 @param output_cli A fully initialised cli structure, non-null only on success
1899 @param dest_host The netbios name of the remote host
1900 @param dest_ss (optional) The the destination IP, NULL for name based lookup
1901 @param port (optional) The destination port (0 for default)
1902 @param retry bool. Did this connection fail with a retryable error ?
1905 NTSTATUS cli_start_connection(struct cli_state **output_cli,
1906 const char *my_name,
1907 const char *dest_host,
1908 struct sockaddr_storage *dest_ss, int port,
1909 int signing_state, int flags,
1910 bool *retry)
1912 NTSTATUS nt_status;
1913 struct nmb_name calling;
1914 struct nmb_name called;
1915 struct cli_state *cli;
1916 struct sockaddr_storage ss;
1918 if (retry)
1919 *retry = False;
1921 if (!my_name)
1922 my_name = global_myname();
1924 if (!(cli = cli_initialise())) {
1925 return NT_STATUS_NO_MEMORY;
1928 make_nmb_name(&calling, my_name, 0x0);
1929 make_nmb_name(&called , dest_host, 0x20);
1931 cli_set_port(cli, port);
1932 cli_set_timeout(cli, 10000); /* 10 seconds. */
1934 if (dest_ss) {
1935 ss = *dest_ss;
1936 } else {
1937 zero_sockaddr(&ss);
1940 again:
1942 DEBUG(3,("Connecting to host=%s\n", dest_host));
1944 nt_status = cli_connect(cli, dest_host, &ss);
1945 if (!NT_STATUS_IS_OK(nt_status)) {
1946 char addr[INET6_ADDRSTRLEN];
1947 print_sockaddr(addr, sizeof(addr), &ss);
1948 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
1949 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
1950 cli_shutdown(cli);
1951 return nt_status;
1954 if (retry)
1955 *retry = True;
1957 if (!cli_session_request(cli, &calling, &called)) {
1958 char *p;
1959 DEBUG(1,("session request to %s failed (%s)\n",
1960 called.name, cli_errstr(cli)));
1961 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
1962 *p = 0;
1963 goto again;
1965 if (strcmp(called.name, STAR_SMBSERVER)) {
1966 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
1967 goto again;
1969 return NT_STATUS_BAD_NETWORK_NAME;
1972 cli_setup_signing_state(cli, signing_state);
1974 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
1975 cli->use_spnego = False;
1976 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
1977 cli->use_kerberos = True;
1979 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
1980 cli->use_kerberos) {
1981 cli->fallback_after_kerberos = true;
1984 nt_status = cli_negprot(cli);
1985 if (!NT_STATUS_IS_OK(nt_status)) {
1986 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
1987 cli_shutdown(cli);
1988 return nt_status;
1991 *output_cli = cli;
1992 return NT_STATUS_OK;
1997 establishes a connection right up to doing tconX, password specified.
1998 @param output_cli A fully initialised cli structure, non-null only on success
1999 @param dest_host The netbios name of the remote host
2000 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2001 @param port (optional) The destination port (0 for default)
2002 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2003 @param service_type The 'type' of serivice.
2004 @param user Username, unix string
2005 @param domain User's domain
2006 @param password User's password, unencrypted unix string.
2007 @param retry bool. Did this connection fail with a retryable error ?
2010 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2011 const char *my_name,
2012 const char *dest_host,
2013 struct sockaddr_storage *dest_ss, int port,
2014 const char *service, const char *service_type,
2015 const char *user, const char *domain,
2016 const char *password, int flags,
2017 int signing_state,
2018 bool *retry)
2020 NTSTATUS nt_status;
2021 struct cli_state *cli = NULL;
2022 int pw_len = password ? strlen(password)+1 : 0;
2024 *output_cli = NULL;
2026 if (password == NULL) {
2027 password = "";
2030 nt_status = cli_start_connection(&cli, my_name, dest_host,
2031 dest_ss, port, signing_state,
2032 flags, retry);
2034 if (!NT_STATUS_IS_OK(nt_status)) {
2035 return nt_status;
2038 nt_status = cli_session_setup(cli, user, password, pw_len, password,
2039 pw_len, domain);
2040 if (!NT_STATUS_IS_OK(nt_status)) {
2042 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2043 DEBUG(1,("failed session setup with %s\n",
2044 nt_errstr(nt_status)));
2045 cli_shutdown(cli);
2046 return nt_status;
2049 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2050 if (!NT_STATUS_IS_OK(nt_status)) {
2051 DEBUG(1,("anonymous failed session setup with %s\n",
2052 nt_errstr(nt_status)));
2053 cli_shutdown(cli);
2054 return nt_status;
2058 if (service) {
2059 nt_status = cli_tcon_andx(cli, service, service_type, password,
2060 pw_len);
2061 if (!NT_STATUS_IS_OK(nt_status)) {
2062 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2063 cli_shutdown(cli);
2064 if (NT_STATUS_IS_OK(nt_status)) {
2065 nt_status = NT_STATUS_UNSUCCESSFUL;
2067 return nt_status;
2071 cli_init_creds(cli, user, domain, password);
2073 *output_cli = cli;
2074 return NT_STATUS_OK;
2077 /****************************************************************************
2078 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2079 ****************************************************************************/
2081 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
2082 struct sockaddr_storage *pdest_ss)
2084 struct nmb_name calling, called;
2086 make_nmb_name(&calling, srchost, 0x0);
2089 * If the called name is an IP address
2090 * then use *SMBSERVER immediately.
2093 if(is_ipaddress(desthost)) {
2094 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
2095 } else {
2096 make_nmb_name(&called, desthost, 0x20);
2099 if (!cli_session_request(*ppcli, &calling, &called)) {
2100 NTSTATUS status;
2101 struct nmb_name smbservername;
2103 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
2106 * If the name wasn't *SMBSERVER then
2107 * try with *SMBSERVER if the first name fails.
2110 if (nmb_name_equal(&called, &smbservername)) {
2113 * The name used was *SMBSERVER, don't bother with another name.
2116 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2117 with error %s.\n", desthost, cli_errstr(*ppcli) ));
2118 return False;
2121 /* Try again... */
2122 cli_shutdown(*ppcli);
2124 *ppcli = cli_initialise();
2125 if (!*ppcli) {
2126 /* Out of memory... */
2127 return False;
2130 status = cli_connect(*ppcli, desthost, pdest_ss);
2131 if (!NT_STATUS_IS_OK(status) ||
2132 !cli_session_request(*ppcli, &calling, &smbservername)) {
2133 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2134 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
2135 return False;
2139 return True;
2142 /****************************************************************************
2143 Send an old style tcon.
2144 ****************************************************************************/
2145 NTSTATUS cli_raw_tcon(struct cli_state *cli,
2146 const char *service, const char *pass, const char *dev,
2147 uint16 *max_xmit, uint16 *tid)
2149 char *p;
2151 if (!lp_client_plaintext_auth() && (*pass)) {
2152 DEBUG(1, ("Server requested plaintext password but 'client "
2153 "plaintext auth' is disabled\n"));
2154 return NT_STATUS_ACCESS_DENIED;
2157 memset(cli->outbuf,'\0',smb_size);
2158 memset(cli->inbuf,'\0',smb_size);
2160 cli_set_message(cli->outbuf, 0, 0, True);
2161 SCVAL(cli->outbuf,smb_com,SMBtcon);
2162 cli_setup_packet(cli);
2164 p = smb_buf(cli->outbuf);
2165 *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
2166 *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
2167 *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
2169 cli_setup_bcc(cli, p);
2171 cli_send_smb(cli);
2172 if (!cli_receive_smb(cli)) {
2173 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2176 if (cli_is_error(cli)) {
2177 return cli_nt_error(cli);
2180 *max_xmit = SVAL(cli->inbuf, smb_vwv0);
2181 *tid = SVAL(cli->inbuf, smb_vwv1);
2183 return NT_STATUS_OK;
2186 /* Return a cli_state pointing at the IPC$ share for the given server */
2188 struct cli_state *get_ipc_connect(char *server,
2189 struct sockaddr_storage *server_ss,
2190 const struct user_auth_info *user_info)
2192 struct cli_state *cli;
2193 NTSTATUS nt_status;
2194 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2196 if (user_info->use_kerberos) {
2197 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2200 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
2201 user_info->username ? user_info->username : "",
2202 lp_workgroup(),
2203 user_info->password ? user_info->password : "",
2204 flags,
2205 Undefined, NULL);
2207 if (NT_STATUS_IS_OK(nt_status)) {
2208 return cli;
2209 } else if (is_ipaddress(server)) {
2210 /* windows 9* needs a correct NMB name for connections */
2211 fstring remote_name;
2213 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2214 cli = get_ipc_connect(remote_name, server_ss, user_info);
2215 if (cli)
2216 return cli;
2219 return NULL;
2223 * Given the IP address of a master browser on the network, return its
2224 * workgroup and connect to it.
2226 * This function is provided to allow additional processing beyond what
2227 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2228 * browsers and obtain each master browsers' list of domains (in case the
2229 * first master browser is recently on the network and has not yet
2230 * synchronized with other master browsers and therefore does not yet have the
2231 * entire network browse list)
2234 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2235 struct ip_service *mb_ip,
2236 const struct user_auth_info *user_info,
2237 char **pp_workgroup_out)
2239 char addr[INET6_ADDRSTRLEN];
2240 fstring name;
2241 struct cli_state *cli;
2242 struct sockaddr_storage server_ss;
2244 *pp_workgroup_out = NULL;
2246 print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2247 DEBUG(99, ("Looking up name of master browser %s\n",
2248 addr));
2251 * Do a name status query to find out the name of the master browser.
2252 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2253 * master browser will not respond to a wildcard query (or, at least,
2254 * an NT4 server acting as the domain master browser will not).
2256 * We might be able to use ONLY the query on MSBROWSE, but that's not
2257 * yet been tested with all Windows versions, so until it is, leave
2258 * the original wildcard query as the first choice and fall back to
2259 * MSBROWSE if the wildcard query fails.
2261 if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2262 !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2264 DEBUG(99, ("Could not retrieve name status for %s\n",
2265 addr));
2266 return NULL;
2269 if (!find_master_ip(name, &server_ss)) {
2270 DEBUG(99, ("Could not find master ip for %s\n", name));
2271 return NULL;
2274 *pp_workgroup_out = talloc_strdup(ctx, name);
2276 DEBUG(4, ("found master browser %s, %s\n", name, addr));
2278 print_sockaddr(addr, sizeof(addr), &server_ss);
2279 cli = get_ipc_connect(addr, &server_ss, user_info);
2281 return cli;
2285 * Return the IP address and workgroup of a master browser on the network, and
2286 * connect to it.
2289 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2290 const struct user_auth_info *user_info,
2291 char **pp_workgroup_out)
2293 struct ip_service *ip_list;
2294 struct cli_state *cli;
2295 int i, count;
2297 *pp_workgroup_out = NULL;
2299 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2301 /* Go looking for workgroups by broadcasting on the local network */
2303 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2304 &count))) {
2305 DEBUG(99, ("No master browsers responded\n"));
2306 return False;
2309 for (i = 0; i < count; i++) {
2310 char addr[INET6_ADDRSTRLEN];
2311 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2312 DEBUG(99, ("Found master browser %s\n", addr));
2314 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2315 user_info, pp_workgroup_out);
2316 if (cli)
2317 return(cli);
2320 return NULL;