Merge branch 'master' of /home/tridge/samba/git/combined
[Samba/aatanasov.git] / source3 / libsmb / cliconnect.c
blob600f8d1b4adb422dee0ded90210971162f0d5f2e
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"
22 #include "../libcli/auth/libcli_auth.h"
24 static const struct {
25 int prot;
26 const char name[24];
27 } prots[10] = {
28 {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
29 {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
30 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
31 {PROTOCOL_LANMAN1, "LANMAN1.0"},
32 {PROTOCOL_LANMAN2, "LM1.2X002"},
33 {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
34 {PROTOCOL_LANMAN2, "LANMAN2.1"},
35 {PROTOCOL_LANMAN2, "Samba"},
36 {PROTOCOL_NT1, "NT LANMAN 1.0"},
37 {PROTOCOL_NT1, "NT LM 0.12"},
40 #define STAR_SMBSERVER "*SMBSERVER"
42 /**
43 * Set the user session key for a connection
44 * @param cli The cli structure to add it too
45 * @param session_key The session key used. (A copy of this is taken for the cli struct)
49 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
51 cli->user_session_key = data_blob(session_key.data, session_key.length);
54 /****************************************************************************
55 Do an old lanman2 style session setup.
56 ****************************************************************************/
58 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
59 const char *user,
60 const char *pass, size_t passlen,
61 const char *workgroup)
63 DATA_BLOB session_key = data_blob_null;
64 DATA_BLOB lm_response = data_blob_null;
65 NTSTATUS status;
66 fstring pword;
67 char *p;
69 if (passlen > sizeof(pword)-1) {
70 return NT_STATUS_INVALID_PARAMETER;
73 /* LANMAN servers predate NT status codes and Unicode and ignore those
74 smb flags so we must disable the corresponding default capabilities
75 that would otherwise cause the Unicode and NT Status flags to be
76 set (and even returned by the server) */
78 cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
80 /* if in share level security then don't send a password now */
81 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
82 passlen = 0;
84 if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
85 /* Encrypted mode needed, and non encrypted password supplied. */
86 lm_response = data_blob(NULL, 24);
87 if (!SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data)) {
88 DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n"));
89 return NT_STATUS_ACCESS_DENIED;
91 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
92 /* Encrypted mode needed, and encrypted password supplied. */
93 lm_response = data_blob(pass, passlen);
94 } else if (passlen > 0) {
95 /* Plaintext mode needed, assume plaintext supplied. */
96 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
97 lm_response = data_blob(pass, passlen);
100 /* send a session setup command */
101 memset(cli->outbuf,'\0',smb_size);
102 cli_set_message(cli->outbuf,10, 0, True);
103 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
104 cli_setup_packet(cli);
106 SCVAL(cli->outbuf,smb_vwv0,0xFF);
107 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
108 SSVAL(cli->outbuf,smb_vwv3,2);
109 SSVAL(cli->outbuf,smb_vwv4,1);
110 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
111 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
113 p = smb_buf(cli->outbuf);
114 memcpy(p,lm_response.data,lm_response.length);
115 p += lm_response.length;
116 p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
117 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
118 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
119 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
120 cli_setup_bcc(cli, p);
122 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
123 return cli_nt_error(cli);
126 show_msg(cli->inbuf);
128 if (cli_is_error(cli)) {
129 return cli_nt_error(cli);
132 /* use the returned vuid from now on */
133 cli->vuid = SVAL(cli->inbuf,smb_uid);
134 status = cli_set_username(cli, user);
135 if (!NT_STATUS_IS_OK(status)) {
136 return status;
139 if (session_key.data) {
140 /* Have plaintext orginal */
141 cli_set_session_key(cli, session_key);
144 return NT_STATUS_OK;
147 /****************************************************************************
148 Work out suitable capabilities to offer the server.
149 ****************************************************************************/
151 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
153 uint32 capabilities = CAP_NT_SMBS;
155 if (!cli->force_dos_errors)
156 capabilities |= CAP_STATUS32;
158 if (cli->use_level_II_oplocks)
159 capabilities |= CAP_LEVEL_II_OPLOCKS;
161 capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
162 return capabilities;
165 /****************************************************************************
166 Do a NT1 guest session setup.
167 ****************************************************************************/
169 struct cli_session_setup_guest_state {
170 struct cli_state *cli;
171 uint16_t vwv[16];
172 struct iovec bytes;
175 static void cli_session_setup_guest_done(struct tevent_req *subreq);
177 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
178 struct event_context *ev,
179 struct cli_state *cli,
180 struct tevent_req **psmbreq)
182 struct tevent_req *req, *subreq;
183 struct cli_session_setup_guest_state *state;
184 uint16_t *vwv;
185 uint8_t *bytes;
187 req = tevent_req_create(mem_ctx, &state,
188 struct cli_session_setup_guest_state);
189 if (req == NULL) {
190 return NULL;
192 state->cli = cli;
193 vwv = state->vwv;
195 SCVAL(vwv+0, 0, 0xFF);
196 SCVAL(vwv+0, 1, 0);
197 SSVAL(vwv+1, 0, 0);
198 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
199 SSVAL(vwv+3, 0, 2);
200 SSVAL(vwv+4, 0, cli->pid);
201 SIVAL(vwv+5, 0, cli->sesskey);
202 SSVAL(vwv+7, 0, 0);
203 SSVAL(vwv+8, 0, 0);
204 SSVAL(vwv+9, 0, 0);
205 SSVAL(vwv+10, 0, 0);
206 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
208 bytes = talloc_array(state, uint8_t, 0);
210 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
211 NULL);
212 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
213 NULL);
214 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
215 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
217 if (bytes == NULL) {
218 TALLOC_FREE(req);
219 return NULL;
222 state->bytes.iov_base = (void *)bytes;
223 state->bytes.iov_len = talloc_get_size(bytes);
225 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
226 1, &state->bytes);
227 if (subreq == NULL) {
228 TALLOC_FREE(req);
229 return NULL;
231 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
232 *psmbreq = subreq;
233 return req;
236 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
237 struct event_context *ev,
238 struct cli_state *cli)
240 struct tevent_req *req, *subreq;
241 NTSTATUS status;
243 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
244 if (req == NULL) {
245 return NULL;
248 status = cli_smb_req_send(subreq);
249 if (NT_STATUS_IS_OK(status)) {
250 tevent_req_nterror(req, status);
251 return tevent_req_post(req, ev);
253 return req;
256 static void cli_session_setup_guest_done(struct tevent_req *subreq)
258 struct tevent_req *req = tevent_req_callback_data(
259 subreq, struct tevent_req);
260 struct cli_session_setup_guest_state *state = tevent_req_data(
261 req, struct cli_session_setup_guest_state);
262 struct cli_state *cli = state->cli;
263 uint32_t num_bytes;
264 char *inbuf;
265 uint8_t *bytes;
266 uint8_t *p;
267 NTSTATUS status;
269 status = cli_smb_recv(subreq, 0, NULL, NULL, &num_bytes, &bytes);
270 if (!NT_STATUS_IS_OK(status)) {
271 TALLOC_FREE(subreq);
272 tevent_req_nterror(req, status);
273 return;
276 inbuf = (char *)cli_smb_inbuf(subreq);
277 p = bytes;
279 cli->vuid = SVAL(inbuf, smb_uid);
281 p += clistr_pull(inbuf, cli->server_os, (char *)p, sizeof(fstring),
282 bytes+num_bytes-p, STR_TERMINATE);
283 p += clistr_pull(inbuf, cli->server_type, (char *)p, sizeof(fstring),
284 bytes+num_bytes-p, STR_TERMINATE);
285 p += clistr_pull(inbuf, cli->server_domain, (char *)p, sizeof(fstring),
286 bytes+num_bytes-p, STR_TERMINATE);
288 if (strstr(cli->server_type, "Samba")) {
289 cli->is_samba = True;
292 TALLOC_FREE(subreq);
294 status = cli_set_username(cli, "");
295 if (!NT_STATUS_IS_OK(status)) {
296 tevent_req_nterror(req, status);
297 return;
299 tevent_req_done(req);
302 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
304 return tevent_req_simple_recv_ntstatus(req);
307 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
309 TALLOC_CTX *frame = talloc_stackframe();
310 struct event_context *ev;
311 struct tevent_req *req;
312 NTSTATUS status = NT_STATUS_OK;
314 if (cli_has_async_calls(cli)) {
316 * Can't use sync call while an async call is in flight
318 status = NT_STATUS_INVALID_PARAMETER;
319 goto fail;
322 ev = event_context_init(frame);
323 if (ev == NULL) {
324 status = NT_STATUS_NO_MEMORY;
325 goto fail;
328 req = cli_session_setup_guest_send(frame, ev, cli);
329 if (req == NULL) {
330 status = NT_STATUS_NO_MEMORY;
331 goto fail;
334 if (!tevent_req_poll(req, ev)) {
335 status = map_nt_error_from_unix(errno);
336 goto fail;
339 status = cli_session_setup_guest_recv(req);
340 fail:
341 TALLOC_FREE(frame);
342 if (!NT_STATUS_IS_OK(status)) {
343 cli_set_error(cli, status);
345 return status;
348 /****************************************************************************
349 Do a NT1 plaintext session setup.
350 ****************************************************************************/
352 static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
353 const char *user, const char *pass,
354 const char *workgroup)
356 uint32 capabilities = cli_session_setup_capabilities(cli);
357 char *p;
358 NTSTATUS status;
359 fstring lanman;
361 fstr_sprintf( lanman, "Samba %s", samba_version_string());
363 memset(cli->outbuf, '\0', smb_size);
364 cli_set_message(cli->outbuf,13,0,True);
365 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
366 cli_setup_packet(cli);
368 SCVAL(cli->outbuf,smb_vwv0,0xFF);
369 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
370 SSVAL(cli->outbuf,smb_vwv3,2);
371 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
372 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
373 SSVAL(cli->outbuf,smb_vwv8,0);
374 SIVAL(cli->outbuf,smb_vwv11,capabilities);
375 p = smb_buf(cli->outbuf);
377 /* check wether to send the ASCII or UNICODE version of the password */
379 if ( (capabilities & CAP_UNICODE) == 0 ) {
380 p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
381 SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
383 else {
384 /* For ucs2 passwords clistr_push calls ucs2_align, which causes
385 * the space taken by the unicode password to be one byte too
386 * long (as we're on an odd byte boundary here). Reduce the
387 * count by 1 to cope with this. Fixes smbclient against NetApp
388 * servers which can't cope. Fix from
389 * bryan.kolodziej@allenlund.com in bug #3840.
391 p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
392 SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))-1);
395 p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
396 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
397 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
398 p += clistr_push(cli, p, lanman, -1, STR_TERMINATE);
399 cli_setup_bcc(cli, p);
401 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
402 return cli_nt_error(cli);
405 show_msg(cli->inbuf);
407 if (cli_is_error(cli)) {
408 return cli_nt_error(cli);
411 cli->vuid = SVAL(cli->inbuf,smb_uid);
412 p = smb_buf(cli->inbuf);
413 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
414 -1, STR_TERMINATE);
415 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
416 -1, STR_TERMINATE);
417 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
418 -1, STR_TERMINATE);
419 status = cli_set_username(cli, user);
420 if (!NT_STATUS_IS_OK(status)) {
421 return status;
423 if (strstr(cli->server_type, "Samba")) {
424 cli->is_samba = True;
427 return NT_STATUS_OK;
430 /****************************************************************************
431 do a NT1 NTLM/LM encrypted session setup - for when extended security
432 is not negotiated.
433 @param cli client state to create do session setup on
434 @param user username
435 @param pass *either* cleartext password (passlen !=24) or LM response.
436 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
437 @param workgroup The user's domain.
438 ****************************************************************************/
440 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
441 const char *pass, size_t passlen,
442 const char *ntpass, size_t ntpasslen,
443 const char *workgroup)
445 uint32 capabilities = cli_session_setup_capabilities(cli);
446 DATA_BLOB lm_response = data_blob_null;
447 DATA_BLOB nt_response = data_blob_null;
448 DATA_BLOB session_key = data_blob_null;
449 NTSTATUS result;
450 char *p;
451 bool ok;
453 if (passlen == 0) {
454 /* do nothing - guest login */
455 } else if (passlen != 24) {
456 if (lp_client_ntlmv2_auth()) {
457 DATA_BLOB server_chal;
458 DATA_BLOB names_blob;
459 server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8));
461 /* note that the 'workgroup' here is a best guess - we don't know
462 the server's domain at this point. The 'server name' is also
463 dodgy...
465 names_blob = NTLMv2_generate_names_blob(NULL, cli->called.name, workgroup);
467 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass, &server_chal,
468 &names_blob,
469 &lm_response, &nt_response, NULL, &session_key)) {
470 data_blob_free(&names_blob);
471 data_blob_free(&server_chal);
472 return NT_STATUS_ACCESS_DENIED;
474 data_blob_free(&names_blob);
475 data_blob_free(&server_chal);
477 } else {
478 uchar nt_hash[16];
479 E_md4hash(pass, nt_hash);
481 #ifdef LANMAN_ONLY
482 nt_response = data_blob_null;
483 #else
484 nt_response = data_blob(NULL, 24);
485 SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
486 #endif
487 /* non encrypted password supplied. Ignore ntpass. */
488 if (lp_client_lanman_auth()) {
489 lm_response = data_blob(NULL, 24);
490 if (!SMBencrypt(pass,cli->secblob.data, lm_response.data)) {
491 /* Oops, the LM response is invalid, just put
492 the NT response there instead */
493 data_blob_free(&lm_response);
494 lm_response = data_blob(nt_response.data, nt_response.length);
496 } else {
497 /* LM disabled, place NT# in LM field instead */
498 lm_response = data_blob(nt_response.data, nt_response.length);
501 session_key = data_blob(NULL, 16);
502 #ifdef LANMAN_ONLY
503 E_deshash(pass, session_key.data);
504 memset(&session_key.data[8], '\0', 8);
505 #else
506 SMBsesskeygen_ntv1(nt_hash, session_key.data);
507 #endif
509 cli_temp_set_signing(cli);
510 } else {
511 /* pre-encrypted password supplied. Only used for
512 security=server, can't do
513 signing because we don't have original key */
515 lm_response = data_blob(pass, passlen);
516 nt_response = data_blob(ntpass, ntpasslen);
519 /* send a session setup command */
520 memset(cli->outbuf,'\0',smb_size);
522 cli_set_message(cli->outbuf,13,0,True);
523 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
524 cli_setup_packet(cli);
526 SCVAL(cli->outbuf,smb_vwv0,0xFF);
527 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
528 SSVAL(cli->outbuf,smb_vwv3,2);
529 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
530 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
531 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
532 SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
533 SIVAL(cli->outbuf,smb_vwv11,capabilities);
534 p = smb_buf(cli->outbuf);
535 if (lm_response.length) {
536 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
538 if (nt_response.length) {
539 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
541 p += clistr_push(cli, p, user, -1, STR_TERMINATE);
543 /* Upper case here might help some NTLMv2 implementations */
544 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
545 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
546 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
547 cli_setup_bcc(cli, p);
549 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
550 result = cli_nt_error(cli);
551 goto end;
554 /* show_msg(cli->inbuf); */
556 if (cli_is_error(cli)) {
557 result = cli_nt_error(cli);
558 goto end;
561 #ifdef LANMAN_ONLY
562 ok = cli_simple_set_signing(cli, session_key, lm_response);
563 #else
564 ok = cli_simple_set_signing(cli, session_key, nt_response);
565 #endif
566 if (ok) {
567 if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
568 result = NT_STATUS_ACCESS_DENIED;
569 goto end;
573 /* use the returned vuid from now on */
574 cli->vuid = SVAL(cli->inbuf,smb_uid);
576 p = smb_buf(cli->inbuf);
577 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
578 -1, STR_TERMINATE);
579 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
580 -1, STR_TERMINATE);
581 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
582 -1, STR_TERMINATE);
584 if (strstr(cli->server_type, "Samba")) {
585 cli->is_samba = True;
588 result = cli_set_username(cli, user);
589 if (!NT_STATUS_IS_OK(result)) {
590 goto end;
593 if (session_key.data) {
594 /* Have plaintext orginal */
595 cli_set_session_key(cli, session_key);
598 result = NT_STATUS_OK;
599 end:
600 data_blob_free(&lm_response);
601 data_blob_free(&nt_response);
602 data_blob_free(&session_key);
603 return result;
606 /****************************************************************************
607 Send a extended security session setup blob
608 ****************************************************************************/
610 static bool cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob)
612 uint32 capabilities = cli_session_setup_capabilities(cli);
613 char *p;
615 capabilities |= CAP_EXTENDED_SECURITY;
617 /* send a session setup command */
618 memset(cli->outbuf,'\0',smb_size);
620 cli_set_message(cli->outbuf,12,0,True);
621 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
623 cli_setup_packet(cli);
625 SCVAL(cli->outbuf,smb_vwv0,0xFF);
626 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
627 SSVAL(cli->outbuf,smb_vwv3,2);
628 SSVAL(cli->outbuf,smb_vwv4,1);
629 SIVAL(cli->outbuf,smb_vwv5,0);
630 SSVAL(cli->outbuf,smb_vwv7,blob.length);
631 SIVAL(cli->outbuf,smb_vwv10,capabilities);
632 p = smb_buf(cli->outbuf);
633 memcpy(p, blob.data, blob.length);
634 p += blob.length;
635 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
636 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
637 cli_setup_bcc(cli, p);
638 return cli_send_smb(cli);
641 /****************************************************************************
642 Send a extended security session setup blob, returning a reply blob.
643 ****************************************************************************/
645 static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli)
647 DATA_BLOB blob2 = data_blob_null;
648 char *p;
649 size_t len;
651 if (!cli_receive_smb(cli))
652 return blob2;
654 show_msg(cli->inbuf);
656 if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli),
657 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
658 return blob2;
661 /* use the returned vuid from now on */
662 cli->vuid = SVAL(cli->inbuf,smb_uid);
664 p = smb_buf(cli->inbuf);
666 blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3));
668 p += blob2.length;
669 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
670 -1, STR_TERMINATE);
672 /* w2k with kerberos doesn't properly null terminate this field */
673 len = smb_bufrem(cli->inbuf, p);
674 if (p + len < cli->inbuf + cli->bufsize+SAFETY_MARGIN - 2) {
675 char *end_of_buf = p + len;
677 SSVAL(p, len, 0);
678 /* Now it's null terminated. */
679 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
680 -1, STR_TERMINATE);
682 * See if there's another string. If so it's the
683 * server domain (part of the 'standard' Samba
684 * server signature).
686 if (p < end_of_buf) {
687 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
688 -1, STR_TERMINATE);
690 } else {
692 * No room to null terminate so we can't see if there
693 * is another string (server_domain) afterwards.
695 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
696 len, 0);
698 return blob2;
701 #ifdef HAVE_KRB5
702 /****************************************************************************
703 Send a extended security session setup blob, returning a reply blob.
704 ****************************************************************************/
706 /* The following is calculated from :
707 * (smb_size-4) = 35
708 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
709 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
710 * end of packet.
713 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
715 static bool cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
717 int32 remaining = blob.length;
718 int32 cur = 0;
719 DATA_BLOB send_blob = data_blob_null;
720 int32 max_blob_size = 0;
721 DATA_BLOB receive_blob = data_blob_null;
723 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
724 DEBUG(0,("cli_session_setup_blob: cli->max_xmit too small "
725 "(was %u, need minimum %u)\n",
726 (unsigned int)cli->max_xmit,
727 BASE_SESSSETUP_BLOB_PACKET_SIZE));
728 cli_set_nt_error(cli, NT_STATUS_INVALID_PARAMETER);
729 return False;
732 max_blob_size = cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE;
734 while ( remaining > 0) {
735 if (remaining >= max_blob_size) {
736 send_blob.length = max_blob_size;
737 remaining -= max_blob_size;
738 } else {
739 send_blob.length = remaining;
740 remaining = 0;
743 send_blob.data = &blob.data[cur];
744 cur += send_blob.length;
746 DEBUG(10, ("cli_session_setup_blob: Remaining (%u) sending (%u) current (%u)\n",
747 (unsigned int)remaining,
748 (unsigned int)send_blob.length,
749 (unsigned int)cur ));
751 if (!cli_session_setup_blob_send(cli, send_blob)) {
752 DEBUG(0, ("cli_session_setup_blob: send failed\n"));
753 return False;
756 receive_blob = cli_session_setup_blob_receive(cli);
757 data_blob_free(&receive_blob);
759 if (cli_is_error(cli) &&
760 !NT_STATUS_EQUAL( cli_get_nt_error(cli),
761 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
762 DEBUG(0, ("cli_session_setup_blob: receive failed "
763 "(%s)\n", nt_errstr(cli_get_nt_error(cli))));
764 cli->vuid = 0;
765 return False;
769 return True;
772 /****************************************************************************
773 Use in-memory credentials cache
774 ****************************************************************************/
776 static void use_in_memory_ccache(void) {
777 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
780 /****************************************************************************
781 Do a spnego/kerberos encrypted session setup.
782 ****************************************************************************/
784 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
786 DATA_BLOB negTokenTarg;
787 DATA_BLOB session_key_krb5;
788 NTSTATUS nt_status;
789 int rc;
791 cli_temp_set_signing(cli);
793 DEBUG(2,("Doing kerberos session setup\n"));
795 /* generate the encapsulated kerberos5 ticket */
796 rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5, 0, NULL);
798 if (rc) {
799 DEBUG(1, ("cli_session_setup_kerberos: spnego_gen_negTokenTarg failed: %s\n",
800 error_message(rc)));
801 return ADS_ERROR_KRB5(rc);
804 #if 0
805 file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
806 #endif
808 if (!cli_session_setup_blob(cli, negTokenTarg)) {
809 nt_status = cli_nt_error(cli);
810 goto nt_error;
813 if (cli_is_error(cli)) {
814 nt_status = cli_nt_error(cli);
815 if (NT_STATUS_IS_OK(nt_status)) {
816 nt_status = NT_STATUS_UNSUCCESSFUL;
818 goto nt_error;
821 cli_set_session_key(cli, session_key_krb5);
823 if (cli_simple_set_signing(
824 cli, session_key_krb5, data_blob_null)) {
826 if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
827 nt_status = NT_STATUS_ACCESS_DENIED;
828 goto nt_error;
832 data_blob_free(&negTokenTarg);
833 data_blob_free(&session_key_krb5);
835 return ADS_ERROR_NT(NT_STATUS_OK);
837 nt_error:
838 data_blob_free(&negTokenTarg);
839 data_blob_free(&session_key_krb5);
840 cli->vuid = 0;
841 return ADS_ERROR_NT(nt_status);
843 #endif /* HAVE_KRB5 */
846 /****************************************************************************
847 Do a spnego/NTLMSSP encrypted session setup.
848 ****************************************************************************/
850 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
851 const char *pass, const char *domain)
853 struct ntlmssp_state *ntlmssp_state;
854 NTSTATUS nt_status;
855 int turn = 1;
856 DATA_BLOB msg1;
857 DATA_BLOB blob = data_blob_null;
858 DATA_BLOB blob_in = data_blob_null;
859 DATA_BLOB blob_out = data_blob_null;
861 cli_temp_set_signing(cli);
863 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
864 return nt_status;
866 ntlmssp_want_feature(ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
868 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
869 return nt_status;
871 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
872 return nt_status;
874 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
875 return nt_status;
878 do {
879 nt_status = ntlmssp_update(ntlmssp_state,
880 blob_in, &blob_out);
881 data_blob_free(&blob_in);
882 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(nt_status)) {
883 if (turn == 1) {
884 /* and wrap it in a SPNEGO wrapper */
885 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
886 } else {
887 /* wrap it in SPNEGO */
888 msg1 = spnego_gen_auth(blob_out);
891 /* now send that blob on its way */
892 if (!cli_session_setup_blob_send(cli, msg1)) {
893 DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
894 nt_status = NT_STATUS_UNSUCCESSFUL;
895 } else {
896 blob = cli_session_setup_blob_receive(cli);
898 nt_status = cli_nt_error(cli);
899 if (cli_is_error(cli) && NT_STATUS_IS_OK(nt_status)) {
900 if (cli->smb_rw_error == SMB_READ_BAD_SIG) {
901 nt_status = NT_STATUS_ACCESS_DENIED;
902 } else {
903 nt_status = NT_STATUS_UNSUCCESSFUL;
907 data_blob_free(&msg1);
910 if (!blob.length) {
911 if (NT_STATUS_IS_OK(nt_status)) {
912 nt_status = NT_STATUS_UNSUCCESSFUL;
914 } else if ((turn == 1) &&
915 NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
916 DATA_BLOB tmp_blob = data_blob_null;
917 /* the server might give us back two challenges */
918 if (!spnego_parse_challenge(blob, &blob_in,
919 &tmp_blob)) {
920 DEBUG(3,("Failed to parse challenges\n"));
921 nt_status = NT_STATUS_INVALID_PARAMETER;
923 data_blob_free(&tmp_blob);
924 } else {
925 if (!spnego_parse_auth_response(blob, nt_status, OID_NTLMSSP,
926 &blob_in)) {
927 DEBUG(3,("Failed to parse auth response\n"));
928 if (NT_STATUS_IS_OK(nt_status)
929 || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED))
930 nt_status = NT_STATUS_INVALID_PARAMETER;
933 data_blob_free(&blob);
934 data_blob_free(&blob_out);
935 turn++;
936 } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
938 data_blob_free(&blob_in);
940 if (NT_STATUS_IS_OK(nt_status)) {
942 if (cli->server_domain[0] == '\0') {
943 fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
945 cli_set_session_key(cli, ntlmssp_state->session_key);
947 if (cli_simple_set_signing(
948 cli, ntlmssp_state->session_key, data_blob_null)) {
950 if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
951 nt_status = NT_STATUS_ACCESS_DENIED;
956 /* we have a reference conter on ntlmssp_state, if we are signing
957 then the state will be kept by the signing engine */
959 ntlmssp_end(&ntlmssp_state);
961 if (!NT_STATUS_IS_OK(nt_status)) {
962 cli->vuid = 0;
964 return nt_status;
967 /****************************************************************************
968 Do a spnego encrypted session setup.
970 user_domain: The shortname of the domain the user/machine is a member of.
971 dest_realm: The realm we're connecting to, if NULL we use our default realm.
972 ****************************************************************************/
974 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
975 const char *pass, const char *user_domain,
976 const char * dest_realm)
978 char *principal = NULL;
979 char *OIDs[ASN1_MAX_OIDS];
980 int i;
981 DATA_BLOB blob;
982 const char *p = NULL;
983 char *account = NULL;
984 NTSTATUS status;
986 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
988 /* the server might not even do spnego */
989 if (cli->secblob.length <= 16) {
990 DEBUG(3,("server didn't supply a full spnego negprot\n"));
991 goto ntlmssp;
994 #if 0
995 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
996 #endif
998 /* there is 16 bytes of GUID before the real spnego packet starts */
999 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1001 /* The server sent us the first part of the SPNEGO exchange in the
1002 * negprot reply. It is WRONG to depend on the principal sent in the
1003 * negprot reply, but right now we do it. If we don't receive one,
1004 * we try to best guess, then fall back to NTLM. */
1005 if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
1006 data_blob_free(&blob);
1007 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1009 data_blob_free(&blob);
1011 /* make sure the server understands kerberos */
1012 for (i=0;OIDs[i];i++) {
1013 if (i == 0)
1014 DEBUG(3,("got OID=%s\n", OIDs[i]));
1015 else
1016 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1017 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1018 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1019 cli->got_kerberos_mechanism = True;
1021 talloc_free(OIDs[i]);
1024 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1026 status = cli_set_username(cli, user);
1027 if (!NT_STATUS_IS_OK(status)) {
1028 return ADS_ERROR_NT(status);
1031 #ifdef HAVE_KRB5
1032 /* If password is set we reauthenticate to kerberos server
1033 * and do not store results */
1035 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1036 ADS_STATUS rc;
1038 if (pass && *pass) {
1039 int ret;
1041 use_in_memory_ccache();
1042 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1044 if (ret){
1045 TALLOC_FREE(principal);
1046 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1047 if (cli->fallback_after_kerberos)
1048 goto ntlmssp;
1049 return ADS_ERROR_KRB5(ret);
1053 /* If we get a bad principal, try to guess it if
1054 we have a valid host NetBIOS name.
1056 if (strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1057 TALLOC_FREE(principal);
1060 if (principal == NULL &&
1061 !is_ipaddress(cli->desthost) &&
1062 !strequal(STAR_SMBSERVER,
1063 cli->desthost)) {
1064 char *realm = NULL;
1065 char *machine = NULL;
1066 char *host = NULL;
1067 DEBUG(3,("cli_session_setup_spnego: got a "
1068 "bad server principal, trying to guess ...\n"));
1070 host = strchr_m(cli->desthost, '.');
1071 if (host) {
1072 machine = SMB_STRNDUP(cli->desthost,
1073 host - cli->desthost);
1074 } else {
1075 machine = SMB_STRDUP(cli->desthost);
1077 if (machine == NULL) {
1078 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1081 if (dest_realm) {
1082 realm = SMB_STRDUP(dest_realm);
1083 strupper_m(realm);
1084 } else {
1085 realm = kerberos_get_default_realm_from_ccache();
1087 if (realm && *realm) {
1088 principal = talloc_asprintf(NULL, "%s$@%s",
1089 machine, realm);
1090 if (!principal) {
1091 SAFE_FREE(machine);
1092 SAFE_FREE(realm);
1093 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1095 DEBUG(3,("cli_session_setup_spnego: guessed "
1096 "server principal=%s\n",
1097 principal ? principal : "<null>"));
1099 SAFE_FREE(machine);
1100 SAFE_FREE(realm);
1103 if (principal) {
1104 rc = cli_session_setup_kerberos(cli, principal,
1105 dest_realm);
1106 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1107 TALLOC_FREE(principal);
1108 return rc;
1112 #endif
1114 TALLOC_FREE(principal);
1116 ntlmssp:
1118 account = talloc_strdup(talloc_tos(), user);
1119 if (!account) {
1120 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1123 /* when falling back to ntlmssp while authenticating with a machine
1124 * account strip off the realm - gd */
1126 if ((p = strchr_m(user, '@')) != NULL) {
1127 account[PTR_DIFF(p,user)] = '\0';
1130 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1133 /****************************************************************************
1134 Send a session setup. The username and workgroup is in UNIX character
1135 format and must be converted to DOS codepage format before sending. If the
1136 password is in plaintext, the same should be done.
1137 ****************************************************************************/
1139 NTSTATUS cli_session_setup(struct cli_state *cli,
1140 const char *user,
1141 const char *pass, int passlen,
1142 const char *ntpass, int ntpasslen,
1143 const char *workgroup)
1145 char *p;
1146 fstring user2;
1148 if (user) {
1149 fstrcpy(user2, user);
1150 } else {
1151 user2[0] ='\0';
1154 if (!workgroup) {
1155 workgroup = "";
1158 /* allow for workgroups as part of the username */
1159 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1160 (p=strchr_m(user2,*lp_winbind_separator()))) {
1161 *p = 0;
1162 user = p+1;
1163 workgroup = user2;
1166 if (cli->protocol < PROTOCOL_LANMAN1) {
1167 return NT_STATUS_OK;
1170 /* now work out what sort of session setup we are going to
1171 do. I have split this into separate functions to make the
1172 flow a bit easier to understand (tridge) */
1174 /* if its an older server then we have to use the older request format */
1176 if (cli->protocol < PROTOCOL_NT1) {
1177 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1178 DEBUG(1, ("Server requested LM password but 'client lanman auth'"
1179 " is disabled\n"));
1180 return NT_STATUS_ACCESS_DENIED;
1183 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1184 !lp_client_plaintext_auth() && (*pass)) {
1185 DEBUG(1, ("Server requested plaintext password but "
1186 "'client plaintext auth' is disabled\n"));
1187 return NT_STATUS_ACCESS_DENIED;
1190 return cli_session_setup_lanman2(cli, user, pass, passlen,
1191 workgroup);
1194 /* if no user is supplied then we have to do an anonymous connection.
1195 passwords are ignored */
1197 if (!user || !*user)
1198 return cli_session_setup_guest(cli);
1200 /* if the server is share level then send a plaintext null
1201 password at this point. The password is sent in the tree
1202 connect */
1204 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
1205 return cli_session_setup_plaintext(cli, user, "", workgroup);
1207 /* if the server doesn't support encryption then we have to use
1208 plaintext. The second password is ignored */
1210 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1211 if (!lp_client_plaintext_auth() && (*pass)) {
1212 DEBUG(1, ("Server requested plaintext password but "
1213 "'client plaintext auth' is disabled\n"));
1214 return NT_STATUS_ACCESS_DENIED;
1216 return cli_session_setup_plaintext(cli, user, pass, workgroup);
1219 /* if the server supports extended security then use SPNEGO */
1221 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
1222 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
1223 workgroup, NULL);
1224 if (!ADS_ERR_OK(status)) {
1225 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1226 return ads_ntstatus(status);
1228 } else {
1229 NTSTATUS status;
1231 /* otherwise do a NT1 style session setup */
1232 status = cli_session_setup_nt1(cli, user, pass, passlen,
1233 ntpass, ntpasslen, workgroup);
1234 if (!NT_STATUS_IS_OK(status)) {
1235 DEBUG(3,("cli_session_setup: NT1 session setup "
1236 "failed: %s\n", nt_errstr(status)));
1237 return status;
1241 if (strstr(cli->server_type, "Samba")) {
1242 cli->is_samba = True;
1245 return NT_STATUS_OK;
1248 /****************************************************************************
1249 Send a uloggoff.
1250 *****************************************************************************/
1252 bool cli_ulogoff(struct cli_state *cli)
1254 memset(cli->outbuf,'\0',smb_size);
1255 cli_set_message(cli->outbuf,2,0,True);
1256 SCVAL(cli->outbuf,smb_com,SMBulogoffX);
1257 cli_setup_packet(cli);
1258 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1259 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1261 cli_send_smb(cli);
1262 if (!cli_receive_smb(cli))
1263 return False;
1265 if (cli_is_error(cli)) {
1266 return False;
1269 cli->vuid = -1;
1270 return True;
1273 /****************************************************************************
1274 Send a tconX.
1275 ****************************************************************************/
1277 struct cli_tcon_andx_state {
1278 struct cli_state *cli;
1279 uint16_t vwv[4];
1280 struct iovec bytes;
1283 static void cli_tcon_andx_done(struct tevent_req *subreq);
1285 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1286 struct event_context *ev,
1287 struct cli_state *cli,
1288 const char *share, const char *dev,
1289 const char *pass, int passlen,
1290 struct tevent_req **psmbreq)
1292 struct tevent_req *req, *subreq;
1293 struct cli_tcon_andx_state *state;
1294 fstring pword;
1295 uint16_t *vwv;
1296 char *tmp = NULL;
1297 uint8_t *bytes;
1299 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1300 if (req == NULL) {
1301 return NULL;
1303 state->cli = cli;
1304 vwv = state->vwv;
1306 fstrcpy(cli->share, share);
1308 /* in user level security don't send a password now */
1309 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1310 passlen = 1;
1311 pass = "";
1312 } else if (pass == NULL) {
1313 DEBUG(1, ("Server not using user level security and no "
1314 "password supplied.\n"));
1315 goto access_denied;
1318 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1319 *pass && passlen != 24) {
1320 if (!lp_client_lanman_auth()) {
1321 DEBUG(1, ("Server requested LANMAN password "
1322 "(share-level security) but "
1323 "'client lanman auth' is disabled\n"));
1324 goto access_denied;
1328 * Non-encrypted passwords - convert to DOS codepage before
1329 * encryption.
1331 passlen = 24;
1332 SMBencrypt(pass, cli->secblob.data, (uchar *)pword);
1333 } else {
1334 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1335 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1336 == 0) {
1337 if (!lp_client_plaintext_auth() && (*pass)) {
1338 DEBUG(1, ("Server requested plaintext "
1339 "password but 'client plaintext "
1340 "auth' is disabled\n"));
1341 goto access_denied;
1345 * Non-encrypted passwords - convert to DOS codepage
1346 * before using.
1348 passlen = clistr_push(cli, pword, pass, sizeof(pword),
1349 STR_TERMINATE);
1350 if (passlen == -1) {
1351 DEBUG(1, ("clistr_push(pword) failed\n"));
1352 goto access_denied;
1354 } else {
1355 if (passlen) {
1356 memcpy(pword, pass, passlen);
1361 SCVAL(vwv+0, 0, 0xFF);
1362 SCVAL(vwv+0, 1, 0);
1363 SSVAL(vwv+1, 0, 0);
1364 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
1365 SSVAL(vwv+3, 0, passlen);
1367 if (passlen) {
1368 bytes = (uint8_t *)talloc_memdup(state, pword, passlen);
1369 } else {
1370 bytes = talloc_array(state, uint8_t, 0);
1374 * Add the sharename
1376 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1377 cli->desthost, share);
1378 if (tmp == NULL) {
1379 TALLOC_FREE(req);
1380 return NULL;
1382 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
1383 NULL);
1384 TALLOC_FREE(tmp);
1387 * Add the devicetype
1389 tmp = talloc_strdup_upper(talloc_tos(), dev);
1390 if (tmp == NULL) {
1391 TALLOC_FREE(req);
1392 return NULL;
1394 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
1395 TALLOC_FREE(tmp);
1397 if (bytes == NULL) {
1398 TALLOC_FREE(req);
1399 return NULL;
1402 state->bytes.iov_base = (void *)bytes;
1403 state->bytes.iov_len = talloc_get_size(bytes);
1405 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
1406 1, &state->bytes);
1407 if (subreq == NULL) {
1408 TALLOC_FREE(req);
1409 return NULL;
1411 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
1412 *psmbreq = subreq;
1413 return req;
1415 access_denied:
1416 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1417 return tevent_req_post(req, ev);
1420 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
1421 struct event_context *ev,
1422 struct cli_state *cli,
1423 const char *share, const char *dev,
1424 const char *pass, int passlen)
1426 struct tevent_req *req, *subreq;
1427 NTSTATUS status;
1429 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
1430 &subreq);
1431 if (req == NULL) {
1432 return NULL;
1434 status = cli_smb_req_send(subreq);
1435 if (!NT_STATUS_IS_OK(status)) {
1436 tevent_req_nterror(req, status);
1437 return tevent_req_post(req, ev);
1439 return req;
1442 static void cli_tcon_andx_done(struct tevent_req *subreq)
1444 struct tevent_req *req = tevent_req_callback_data(
1445 subreq, struct tevent_req);
1446 struct cli_tcon_andx_state *state = tevent_req_data(
1447 req, struct cli_tcon_andx_state);
1448 struct cli_state *cli = state->cli;
1449 char *inbuf = (char *)cli_smb_inbuf(subreq);
1450 uint8_t wct;
1451 uint16_t *vwv;
1452 uint32_t num_bytes;
1453 uint8_t *bytes;
1454 NTSTATUS status;
1456 status = cli_smb_recv(subreq, 0, &wct, &vwv, &num_bytes, &bytes);
1457 if (!NT_STATUS_IS_OK(status)) {
1458 TALLOC_FREE(subreq);
1459 tevent_req_nterror(req, status);
1460 return;
1463 clistr_pull(inbuf, cli->dev, bytes, sizeof(fstring), num_bytes,
1464 STR_TERMINATE|STR_ASCII);
1466 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
1467 /* almost certainly win95 - enable bug fixes */
1468 cli->win95 = True;
1472 * Make sure that we have the optional support 16-bit field. WCT > 2.
1473 * Avoids issues when connecting to Win9x boxes sharing files
1476 cli->dfsroot = false;
1478 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
1479 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
1482 cli->cnum = SVAL(inbuf,smb_tid);
1483 tevent_req_done(req);
1486 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
1488 return tevent_req_simple_recv_ntstatus(req);
1491 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
1492 const char *dev, const char *pass, int passlen)
1494 TALLOC_CTX *frame = talloc_stackframe();
1495 struct event_context *ev;
1496 struct tevent_req *req;
1497 NTSTATUS status = NT_STATUS_OK;
1499 if (cli_has_async_calls(cli)) {
1501 * Can't use sync call while an async call is in flight
1503 status = NT_STATUS_INVALID_PARAMETER;
1504 goto fail;
1507 ev = event_context_init(frame);
1508 if (ev == NULL) {
1509 status = NT_STATUS_NO_MEMORY;
1510 goto fail;
1513 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
1514 if (req == NULL) {
1515 status = NT_STATUS_NO_MEMORY;
1516 goto fail;
1519 if (!tevent_req_poll(req, ev)) {
1520 status = map_nt_error_from_unix(errno);
1521 goto fail;
1524 status = cli_tcon_andx_recv(req);
1525 fail:
1526 TALLOC_FREE(frame);
1527 if (!NT_STATUS_IS_OK(status)) {
1528 cli_set_error(cli, status);
1530 return status;
1533 /****************************************************************************
1534 Send a tree disconnect.
1535 ****************************************************************************/
1537 bool cli_tdis(struct cli_state *cli)
1539 memset(cli->outbuf,'\0',smb_size);
1540 cli_set_message(cli->outbuf,0,0,True);
1541 SCVAL(cli->outbuf,smb_com,SMBtdis);
1542 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1543 cli_setup_packet(cli);
1545 cli_send_smb(cli);
1546 if (!cli_receive_smb(cli))
1547 return False;
1549 if (cli_is_error(cli)) {
1550 return False;
1553 cli->cnum = -1;
1554 return True;
1557 /****************************************************************************
1558 Send a negprot command.
1559 ****************************************************************************/
1561 void cli_negprot_sendsync(struct cli_state *cli)
1563 char *p;
1564 int numprots;
1566 if (cli->protocol < PROTOCOL_NT1)
1567 cli->use_spnego = False;
1569 memset(cli->outbuf,'\0',smb_size);
1571 /* setup the protocol strings */
1572 cli_set_message(cli->outbuf,0,0,True);
1574 p = smb_buf(cli->outbuf);
1575 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1576 if (prots[numprots].prot > cli->protocol) {
1577 break;
1579 *p++ = 2;
1580 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1583 SCVAL(cli->outbuf,smb_com,SMBnegprot);
1584 cli_setup_bcc(cli, p);
1585 cli_setup_packet(cli);
1587 SCVAL(smb_buf(cli->outbuf),0,2);
1589 cli_send_smb(cli);
1592 /****************************************************************************
1593 Send a negprot command.
1594 ****************************************************************************/
1596 struct cli_negprot_state {
1597 struct cli_state *cli;
1600 static void cli_negprot_done(struct tevent_req *subreq);
1602 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
1603 struct event_context *ev,
1604 struct cli_state *cli)
1606 struct tevent_req *req, *subreq;
1607 struct cli_negprot_state *state;
1608 uint8_t *bytes = NULL;
1609 int numprots;
1610 uint16_t cnum;
1612 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
1613 if (req == NULL) {
1614 return NULL;
1616 state->cli = cli;
1618 if (cli->protocol < PROTOCOL_NT1)
1619 cli->use_spnego = False;
1621 /* setup the protocol strings */
1622 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1623 uint8_t c = 2;
1624 if (prots[numprots].prot > cli->protocol) {
1625 break;
1627 bytes = (uint8_t *)talloc_append_blob(
1628 state, bytes, data_blob_const(&c, sizeof(c)));
1629 if (tevent_req_nomem(bytes, req)) {
1630 return tevent_req_post(req, ev);
1632 bytes = smb_bytes_push_str(bytes, false,
1633 prots[numprots].name,
1634 strlen(prots[numprots].name)+1,
1635 NULL);
1636 if (tevent_req_nomem(bytes, req)) {
1637 return tevent_req_post(req, ev);
1641 cnum = cli->cnum;
1643 cli->cnum = 0;
1644 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
1645 talloc_get_size(bytes), bytes);
1646 cli->cnum = cnum;
1648 if (tevent_req_nomem(subreq, req)) {
1649 return tevent_req_post(req, ev);
1651 tevent_req_set_callback(subreq, cli_negprot_done, req);
1652 return req;
1655 static void cli_negprot_done(struct tevent_req *subreq)
1657 struct tevent_req *req = tevent_req_callback_data(
1658 subreq, struct tevent_req);
1659 struct cli_negprot_state *state = tevent_req_data(
1660 req, struct cli_negprot_state);
1661 struct cli_state *cli = state->cli;
1662 uint8_t wct;
1663 uint16_t *vwv;
1664 uint32_t num_bytes;
1665 uint8_t *bytes;
1666 NTSTATUS status;
1667 uint16_t protnum;
1669 status = cli_smb_recv(subreq, 1, &wct, &vwv, &num_bytes, &bytes);
1670 if (!NT_STATUS_IS_OK(status)) {
1671 TALLOC_FREE(subreq);
1672 return;
1675 protnum = SVAL(vwv, 0);
1677 if ((protnum >= ARRAY_SIZE(prots))
1678 || (prots[protnum].prot > cli->protocol)) {
1679 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1680 return;
1683 cli->protocol = prots[protnum].prot;
1685 if ((cli->protocol < PROTOCOL_NT1) &&
1686 client_is_signing_mandatory(cli)) {
1687 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1688 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1689 return;
1692 if (cli->protocol >= PROTOCOL_NT1) {
1693 struct timespec ts;
1694 bool negotiated_smb_signing = false;
1696 /* NT protocol */
1697 cli->sec_mode = CVAL(vwv + 1, 0);
1698 cli->max_mux = SVAL(vwv + 1, 1);
1699 cli->max_xmit = IVAL(vwv + 3, 1);
1700 cli->sesskey = IVAL(vwv + 7, 1);
1701 cli->serverzone = SVALS(vwv + 15, 1);
1702 cli->serverzone *= 60;
1703 /* this time arrives in real GMT */
1704 ts = interpret_long_date(((char *)(vwv+11))+1);
1705 cli->servertime = ts.tv_sec;
1706 cli->secblob = data_blob(bytes, num_bytes);
1707 cli->capabilities = IVAL(vwv + 9, 1);
1708 if (cli->capabilities & CAP_RAW_MODE) {
1709 cli->readbraw_supported = True;
1710 cli->writebraw_supported = True;
1712 /* work out if they sent us a workgroup */
1713 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1714 smb_buflen(cli->inbuf) > 8) {
1715 clistr_pull(cli->inbuf, cli->server_domain,
1716 bytes+8, sizeof(cli->server_domain),
1717 num_bytes-8,
1718 STR_UNICODE|STR_NOALIGN);
1722 * As signing is slow we only turn it on if either the client or
1723 * the server require it. JRA.
1726 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
1727 /* Fail if server says signing is mandatory and we don't want to support it. */
1728 if (!client_is_signing_allowed(cli)) {
1729 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1730 tevent_req_nterror(req,
1731 NT_STATUS_ACCESS_DENIED);
1732 return;
1734 negotiated_smb_signing = true;
1735 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
1736 /* Fail if client says signing is mandatory and the server doesn't support it. */
1737 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
1738 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1739 tevent_req_nterror(req,
1740 NT_STATUS_ACCESS_DENIED);
1741 return;
1743 negotiated_smb_signing = true;
1744 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
1745 negotiated_smb_signing = true;
1748 if (negotiated_smb_signing) {
1749 cli_set_signing_negotiated(cli);
1752 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
1753 SAFE_FREE(cli->outbuf);
1754 SAFE_FREE(cli->inbuf);
1755 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1756 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1757 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
1760 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1761 cli->use_spnego = False;
1762 cli->sec_mode = SVAL(vwv + 1, 0);
1763 cli->max_xmit = SVAL(vwv + 2, 0);
1764 cli->max_mux = SVAL(vwv + 3, 0);
1765 cli->sesskey = IVAL(vwv + 6, 0);
1766 cli->serverzone = SVALS(vwv + 10, 0);
1767 cli->serverzone *= 60;
1768 /* this time is converted to GMT by make_unix_date */
1769 cli->servertime = cli_make_unix_date(
1770 cli, (char *)(vwv + 8));
1771 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
1772 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
1773 cli->secblob = data_blob(bytes, num_bytes);
1774 } else {
1775 /* the old core protocol */
1776 cli->use_spnego = False;
1777 cli->sec_mode = 0;
1778 cli->serverzone = get_time_zone(time(NULL));
1781 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1783 /* a way to force ascii SMB */
1784 if (getenv("CLI_FORCE_ASCII"))
1785 cli->capabilities &= ~CAP_UNICODE;
1787 tevent_req_done(req);
1790 NTSTATUS cli_negprot_recv(struct tevent_req *req)
1792 return tevent_req_simple_recv_ntstatus(req);
1795 NTSTATUS cli_negprot(struct cli_state *cli)
1797 TALLOC_CTX *frame = talloc_stackframe();
1798 struct event_context *ev;
1799 struct tevent_req *req;
1800 NTSTATUS status = NT_STATUS_OK;
1802 if (cli_has_async_calls(cli)) {
1804 * Can't use sync call while an async call is in flight
1806 status = NT_STATUS_INVALID_PARAMETER;
1807 goto fail;
1810 ev = event_context_init(frame);
1811 if (ev == NULL) {
1812 status = NT_STATUS_NO_MEMORY;
1813 goto fail;
1816 req = cli_negprot_send(frame, ev, cli);
1817 if (req == NULL) {
1818 status = NT_STATUS_NO_MEMORY;
1819 goto fail;
1822 if (!tevent_req_poll(req, ev)) {
1823 status = map_nt_error_from_unix(errno);
1824 goto fail;
1827 status = cli_negprot_recv(req);
1828 fail:
1829 TALLOC_FREE(frame);
1830 if (!NT_STATUS_IS_OK(status)) {
1831 cli_set_error(cli, status);
1833 return status;
1836 /****************************************************************************
1837 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1838 ****************************************************************************/
1840 bool cli_session_request(struct cli_state *cli,
1841 struct nmb_name *calling, struct nmb_name *called)
1843 char *p;
1844 int len = 4;
1845 char *tmp;
1847 /* 445 doesn't have session request */
1848 if (cli->port == 445)
1849 return True;
1851 memcpy(&(cli->calling), calling, sizeof(*calling));
1852 memcpy(&(cli->called ), called , sizeof(*called ));
1854 /* put in the destination name */
1856 tmp = name_mangle(talloc_tos(), cli->called.name,
1857 cli->called.name_type);
1858 if (tmp == NULL) {
1859 return false;
1862 p = cli->outbuf+len;
1863 memcpy(p, tmp, name_len(tmp));
1864 len += name_len(tmp);
1865 TALLOC_FREE(tmp);
1867 /* and my name */
1869 tmp = name_mangle(talloc_tos(), cli->calling.name,
1870 cli->calling.name_type);
1871 if (tmp == NULL) {
1872 return false;
1875 p = cli->outbuf+len;
1876 memcpy(p, tmp, name_len(tmp));
1877 len += name_len(tmp);
1878 TALLOC_FREE(tmp);
1880 /* send a session request (RFC 1002) */
1881 /* setup the packet length
1882 * Remove four bytes from the length count, since the length
1883 * field in the NBT Session Service header counts the number
1884 * of bytes which follow. The cli_send_smb() function knows
1885 * about this and accounts for those four bytes.
1886 * CRH.
1888 len -= 4;
1889 _smb_setlen(cli->outbuf,len);
1890 SCVAL(cli->outbuf,0,0x81);
1892 cli_send_smb(cli);
1893 DEBUG(5,("Sent session request\n"));
1895 if (!cli_receive_smb(cli))
1896 return False;
1898 if (CVAL(cli->inbuf,0) == 0x84) {
1899 /* C. Hoch 9/14/95 Start */
1900 /* For information, here is the response structure.
1901 * We do the byte-twiddling to for portability.
1902 struct RetargetResponse{
1903 unsigned char type;
1904 unsigned char flags;
1905 int16 length;
1906 int32 ip_addr;
1907 int16 port;
1910 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1911 struct in_addr dest_ip;
1912 NTSTATUS status;
1914 /* SESSION RETARGET */
1915 putip((char *)&dest_ip,cli->inbuf+4);
1916 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
1918 status = open_socket_out(&cli->dest_ss, port,
1919 LONG_CONNECT_TIMEOUT, &cli->fd);
1920 if (!NT_STATUS_IS_OK(status)) {
1921 return False;
1924 DEBUG(3,("Retargeted\n"));
1926 set_socket_options(cli->fd, lp_socket_options());
1928 /* Try again */
1930 static int depth;
1931 bool ret;
1932 if (depth > 4) {
1933 DEBUG(0,("Retarget recursion - failing\n"));
1934 return False;
1936 depth++;
1937 ret = cli_session_request(cli, calling, called);
1938 depth--;
1939 return ret;
1941 } /* C. Hoch 9/14/95 End */
1943 if (CVAL(cli->inbuf,0) != 0x82) {
1944 /* This is the wrong place to put the error... JRA. */
1945 cli->rap_error = CVAL(cli->inbuf,4);
1946 return False;
1948 return(True);
1951 struct fd_struct {
1952 int fd;
1955 static void smb_sock_connected(struct tevent_req *req)
1957 struct fd_struct *pfd = tevent_req_callback_data(
1958 req, struct fd_struct);
1959 int fd;
1960 NTSTATUS status;
1962 status = open_socket_out_defer_recv(req, &fd);
1963 if (NT_STATUS_IS_OK(status)) {
1964 pfd->fd = fd;
1968 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
1969 uint16_t *port, int timeout, int *pfd)
1971 struct event_context *ev;
1972 struct tevent_req *r139, *r445;
1973 struct fd_struct *fd139, *fd445;
1974 NTSTATUS status = NT_STATUS_NO_MEMORY;
1976 if (*port != 0) {
1977 return open_socket_out(pss, *port, timeout, pfd);
1980 ev = event_context_init(talloc_tos());
1981 if (ev == NULL) {
1982 return NT_STATUS_NO_MEMORY;
1985 fd139 = talloc(ev, struct fd_struct);
1986 if (fd139 == NULL) {
1987 goto done;
1989 fd139->fd = -1;
1991 fd445 = talloc(ev, struct fd_struct);
1992 if (fd445 == NULL) {
1993 goto done;
1995 fd445->fd = -1;
1997 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
1998 pss, 445, timeout);
1999 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
2000 pss, 139, timeout);
2001 if ((r445 == NULL) || (r139 == NULL)) {
2002 goto done;
2004 tevent_req_set_callback(r445, smb_sock_connected, fd445);
2005 tevent_req_set_callback(r139, smb_sock_connected, fd139);
2007 while ((fd445->fd == -1) && (fd139->fd == -1)
2008 && (tevent_req_is_in_progress(r139)
2009 || tevent_req_is_in_progress(r445))) {
2010 event_loop_once(ev);
2013 if ((fd139->fd != -1) && (fd445->fd != -1)) {
2014 close(fd139->fd);
2015 fd139->fd = -1;
2018 if (fd445->fd != -1) {
2019 *port = 445;
2020 *pfd = fd445->fd;
2021 status = NT_STATUS_OK;
2022 goto done;
2024 if (fd139->fd != -1) {
2025 *port = 139;
2026 *pfd = fd139->fd;
2027 status = NT_STATUS_OK;
2028 goto done;
2031 status = open_socket_out_defer_recv(r445, &fd445->fd);
2032 done:
2033 TALLOC_FREE(ev);
2034 return status;
2037 /****************************************************************************
2038 Open the client sockets.
2039 ****************************************************************************/
2041 NTSTATUS cli_connect(struct cli_state *cli,
2042 const char *host,
2043 struct sockaddr_storage *dest_ss)
2046 int name_type = 0x20;
2047 TALLOC_CTX *frame = talloc_stackframe();
2048 unsigned int num_addrs = 0;
2049 unsigned int i = 0;
2050 struct sockaddr_storage *ss_arr = NULL;
2051 char *p = NULL;
2053 /* reasonable default hostname */
2054 if (!host) {
2055 host = STAR_SMBSERVER;
2058 fstrcpy(cli->desthost, host);
2060 /* allow hostnames of the form NAME#xx and do a netbios lookup */
2061 if ((p = strchr(cli->desthost, '#'))) {
2062 name_type = strtol(p+1, NULL, 16);
2063 *p = 0;
2066 if (!dest_ss || is_zero_addr((struct sockaddr *)dest_ss)) {
2067 NTSTATUS status =resolve_name_list(frame,
2068 cli->desthost,
2069 name_type,
2070 &ss_arr,
2071 &num_addrs);
2072 if (!NT_STATUS_IS_OK(status)) {
2073 TALLOC_FREE(frame);
2074 return NT_STATUS_BAD_NETWORK_NAME;
2076 } else {
2077 num_addrs = 1;
2078 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
2079 if (!ss_arr) {
2080 TALLOC_FREE(frame);
2081 return NT_STATUS_NO_MEMORY;
2083 *ss_arr = *dest_ss;
2086 for (i = 0; i < num_addrs; i++) {
2087 cli->dest_ss = ss_arr[i];
2088 if (getenv("LIBSMB_PROG")) {
2089 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
2090 } else {
2091 uint16_t port = cli->port;
2092 NTSTATUS status;
2093 status = open_smb_socket(&cli->dest_ss, &port,
2094 cli->timeout, &cli->fd);
2095 if (NT_STATUS_IS_OK(status)) {
2096 cli->port = port;
2099 if (cli->fd == -1) {
2100 char addr[INET6_ADDRSTRLEN];
2101 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
2102 DEBUG(2,("Error connecting to %s (%s)\n",
2103 dest_ss?addr:host,strerror(errno)));
2104 } else {
2105 /* Exit from loop on first connection. */
2106 break;
2110 if (cli->fd == -1) {
2111 TALLOC_FREE(frame);
2112 return map_nt_error_from_unix(errno);
2115 if (dest_ss) {
2116 *dest_ss = cli->dest_ss;
2119 set_socket_options(cli->fd, lp_socket_options());
2121 TALLOC_FREE(frame);
2122 return NT_STATUS_OK;
2126 establishes a connection to after the negprot.
2127 @param output_cli A fully initialised cli structure, non-null only on success
2128 @param dest_host The netbios name of the remote host
2129 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2130 @param port (optional) The destination port (0 for default)
2131 @param retry bool. Did this connection fail with a retryable error ?
2134 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2135 const char *my_name,
2136 const char *dest_host,
2137 struct sockaddr_storage *dest_ss, int port,
2138 int signing_state, int flags,
2139 bool *retry)
2141 NTSTATUS nt_status;
2142 struct nmb_name calling;
2143 struct nmb_name called;
2144 struct cli_state *cli;
2145 struct sockaddr_storage ss;
2147 if (retry)
2148 *retry = False;
2150 if (!my_name)
2151 my_name = global_myname();
2153 if (!(cli = cli_initialise_ex(signing_state))) {
2154 return NT_STATUS_NO_MEMORY;
2157 make_nmb_name(&calling, my_name, 0x0);
2158 make_nmb_name(&called , dest_host, 0x20);
2160 cli_set_port(cli, port);
2161 cli_set_timeout(cli, 10000); /* 10 seconds. */
2163 if (dest_ss) {
2164 ss = *dest_ss;
2165 } else {
2166 zero_sockaddr(&ss);
2169 again:
2171 DEBUG(3,("Connecting to host=%s\n", dest_host));
2173 nt_status = cli_connect(cli, dest_host, &ss);
2174 if (!NT_STATUS_IS_OK(nt_status)) {
2175 char addr[INET6_ADDRSTRLEN];
2176 print_sockaddr(addr, sizeof(addr), &ss);
2177 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
2178 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
2179 cli_shutdown(cli);
2180 return nt_status;
2183 if (retry)
2184 *retry = True;
2186 if (!cli_session_request(cli, &calling, &called)) {
2187 char *p;
2188 DEBUG(1,("session request to %s failed (%s)\n",
2189 called.name, cli_errstr(cli)));
2190 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
2191 *p = 0;
2192 goto again;
2194 if (strcmp(called.name, STAR_SMBSERVER)) {
2195 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
2196 goto again;
2198 return NT_STATUS_BAD_NETWORK_NAME;
2201 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
2202 cli->use_spnego = False;
2203 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
2204 cli->use_kerberos = True;
2206 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
2207 cli->use_kerberos) {
2208 cli->fallback_after_kerberos = true;
2211 nt_status = cli_negprot(cli);
2212 if (!NT_STATUS_IS_OK(nt_status)) {
2213 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2214 cli_shutdown(cli);
2215 return nt_status;
2218 *output_cli = cli;
2219 return NT_STATUS_OK;
2224 establishes a connection right up to doing tconX, password specified.
2225 @param output_cli A fully initialised cli structure, non-null only on success
2226 @param dest_host The netbios name of the remote host
2227 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2228 @param port (optional) The destination port (0 for default)
2229 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2230 @param service_type The 'type' of serivice.
2231 @param user Username, unix string
2232 @param domain User's domain
2233 @param password User's password, unencrypted unix string.
2234 @param retry bool. Did this connection fail with a retryable error ?
2237 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2238 const char *my_name,
2239 const char *dest_host,
2240 struct sockaddr_storage *dest_ss, int port,
2241 const char *service, const char *service_type,
2242 const char *user, const char *domain,
2243 const char *password, int flags,
2244 int signing_state,
2245 bool *retry)
2247 NTSTATUS nt_status;
2248 struct cli_state *cli = NULL;
2249 int pw_len = password ? strlen(password)+1 : 0;
2251 *output_cli = NULL;
2253 if (password == NULL) {
2254 password = "";
2257 nt_status = cli_start_connection(&cli, my_name, dest_host,
2258 dest_ss, port, signing_state,
2259 flags, retry);
2261 if (!NT_STATUS_IS_OK(nt_status)) {
2262 return nt_status;
2265 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
2266 cli->use_level_II_oplocks =
2267 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
2269 nt_status = cli_session_setup(cli, user, password, pw_len, password,
2270 pw_len, domain);
2271 if (!NT_STATUS_IS_OK(nt_status)) {
2273 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2274 DEBUG(1,("failed session setup with %s\n",
2275 nt_errstr(nt_status)));
2276 cli_shutdown(cli);
2277 return nt_status;
2280 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2281 if (!NT_STATUS_IS_OK(nt_status)) {
2282 DEBUG(1,("anonymous failed session setup with %s\n",
2283 nt_errstr(nt_status)));
2284 cli_shutdown(cli);
2285 return nt_status;
2289 if (service) {
2290 nt_status = cli_tcon_andx(cli, service, service_type, password,
2291 pw_len);
2292 if (!NT_STATUS_IS_OK(nt_status)) {
2293 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2294 cli_shutdown(cli);
2295 if (NT_STATUS_IS_OK(nt_status)) {
2296 nt_status = NT_STATUS_UNSUCCESSFUL;
2298 return nt_status;
2302 nt_status = cli_init_creds(cli, user, domain, password);
2303 if (!NT_STATUS_IS_OK(nt_status)) {
2304 cli_shutdown(cli);
2305 return nt_status;
2308 *output_cli = cli;
2309 return NT_STATUS_OK;
2312 /****************************************************************************
2313 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2314 ****************************************************************************/
2316 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
2317 struct sockaddr_storage *pdest_ss)
2319 struct nmb_name calling, called;
2321 make_nmb_name(&calling, srchost, 0x0);
2324 * If the called name is an IP address
2325 * then use *SMBSERVER immediately.
2328 if(is_ipaddress(desthost)) {
2329 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
2330 } else {
2331 make_nmb_name(&called, desthost, 0x20);
2334 if (!cli_session_request(*ppcli, &calling, &called)) {
2335 NTSTATUS status;
2336 struct nmb_name smbservername;
2338 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
2341 * If the name wasn't *SMBSERVER then
2342 * try with *SMBSERVER if the first name fails.
2345 if (nmb_name_equal(&called, &smbservername)) {
2348 * The name used was *SMBSERVER, don't bother with another name.
2351 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2352 with error %s.\n", desthost, cli_errstr(*ppcli) ));
2353 return False;
2356 /* Try again... */
2357 cli_shutdown(*ppcli);
2359 *ppcli = cli_initialise();
2360 if (!*ppcli) {
2361 /* Out of memory... */
2362 return False;
2365 status = cli_connect(*ppcli, desthost, pdest_ss);
2366 if (!NT_STATUS_IS_OK(status) ||
2367 !cli_session_request(*ppcli, &calling, &smbservername)) {
2368 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2369 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
2370 return False;
2374 return True;
2377 /****************************************************************************
2378 Send an old style tcon.
2379 ****************************************************************************/
2380 NTSTATUS cli_raw_tcon(struct cli_state *cli,
2381 const char *service, const char *pass, const char *dev,
2382 uint16 *max_xmit, uint16 *tid)
2384 char *p;
2386 if (!lp_client_plaintext_auth() && (*pass)) {
2387 DEBUG(1, ("Server requested plaintext password but 'client "
2388 "plaintext auth' is disabled\n"));
2389 return NT_STATUS_ACCESS_DENIED;
2392 memset(cli->outbuf,'\0',smb_size);
2393 memset(cli->inbuf,'\0',smb_size);
2395 cli_set_message(cli->outbuf, 0, 0, True);
2396 SCVAL(cli->outbuf,smb_com,SMBtcon);
2397 cli_setup_packet(cli);
2399 p = smb_buf(cli->outbuf);
2400 *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
2401 *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
2402 *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
2404 cli_setup_bcc(cli, p);
2406 cli_send_smb(cli);
2407 if (!cli_receive_smb(cli)) {
2408 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2411 if (cli_is_error(cli)) {
2412 return cli_nt_error(cli);
2415 *max_xmit = SVAL(cli->inbuf, smb_vwv0);
2416 *tid = SVAL(cli->inbuf, smb_vwv1);
2418 return NT_STATUS_OK;
2421 /* Return a cli_state pointing at the IPC$ share for the given server */
2423 struct cli_state *get_ipc_connect(char *server,
2424 struct sockaddr_storage *server_ss,
2425 const struct user_auth_info *user_info)
2427 struct cli_state *cli;
2428 NTSTATUS nt_status;
2429 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2431 if (user_info->use_kerberos) {
2432 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2435 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
2436 user_info->username ? user_info->username : "",
2437 lp_workgroup(),
2438 user_info->password ? user_info->password : "",
2439 flags,
2440 Undefined, NULL);
2442 if (NT_STATUS_IS_OK(nt_status)) {
2443 return cli;
2444 } else if (is_ipaddress(server)) {
2445 /* windows 9* needs a correct NMB name for connections */
2446 fstring remote_name;
2448 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2449 cli = get_ipc_connect(remote_name, server_ss, user_info);
2450 if (cli)
2451 return cli;
2454 return NULL;
2458 * Given the IP address of a master browser on the network, return its
2459 * workgroup and connect to it.
2461 * This function is provided to allow additional processing beyond what
2462 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2463 * browsers and obtain each master browsers' list of domains (in case the
2464 * first master browser is recently on the network and has not yet
2465 * synchronized with other master browsers and therefore does not yet have the
2466 * entire network browse list)
2469 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2470 struct ip_service *mb_ip,
2471 const struct user_auth_info *user_info,
2472 char **pp_workgroup_out)
2474 char addr[INET6_ADDRSTRLEN];
2475 fstring name;
2476 struct cli_state *cli;
2477 struct sockaddr_storage server_ss;
2479 *pp_workgroup_out = NULL;
2481 print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2482 DEBUG(99, ("Looking up name of master browser %s\n",
2483 addr));
2486 * Do a name status query to find out the name of the master browser.
2487 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2488 * master browser will not respond to a wildcard query (or, at least,
2489 * an NT4 server acting as the domain master browser will not).
2491 * We might be able to use ONLY the query on MSBROWSE, but that's not
2492 * yet been tested with all Windows versions, so until it is, leave
2493 * the original wildcard query as the first choice and fall back to
2494 * MSBROWSE if the wildcard query fails.
2496 if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2497 !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2499 DEBUG(99, ("Could not retrieve name status for %s\n",
2500 addr));
2501 return NULL;
2504 if (!find_master_ip(name, &server_ss)) {
2505 DEBUG(99, ("Could not find master ip for %s\n", name));
2506 return NULL;
2509 *pp_workgroup_out = talloc_strdup(ctx, name);
2511 DEBUG(4, ("found master browser %s, %s\n", name, addr));
2513 print_sockaddr(addr, sizeof(addr), &server_ss);
2514 cli = get_ipc_connect(addr, &server_ss, user_info);
2516 return cli;
2520 * Return the IP address and workgroup of a master browser on the network, and
2521 * connect to it.
2524 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2525 const struct user_auth_info *user_info,
2526 char **pp_workgroup_out)
2528 struct ip_service *ip_list;
2529 struct cli_state *cli;
2530 int i, count;
2532 *pp_workgroup_out = NULL;
2534 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2536 /* Go looking for workgroups by broadcasting on the local network */
2538 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2539 &count))) {
2540 DEBUG(99, ("No master browsers responded\n"));
2541 return False;
2544 for (i = 0; i < count; i++) {
2545 char addr[INET6_ADDRSTRLEN];
2546 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2547 DEBUG(99, ("Found master browser %s\n", addr));
2549 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2550 user_info, pp_workgroup_out);
2551 if (cli)
2552 return(cli);
2555 return NULL;