Fix the build of nfs4_acls.c
[Samba.git] / source3 / libsmb / cliconnect.c
blob16c15ce7db96505f3eef1cea76b3475489ae426f
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 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
675 len, 0);
677 return blob2;
680 #ifdef HAVE_KRB5
681 /****************************************************************************
682 Send a extended security session setup blob, returning a reply blob.
683 ****************************************************************************/
685 /* The following is calculated from :
686 * (smb_size-4) = 35
687 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
688 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
689 * end of packet.
692 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
694 static bool cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
696 int32 remaining = blob.length;
697 int32 cur = 0;
698 DATA_BLOB send_blob = data_blob_null;
699 int32 max_blob_size = 0;
700 DATA_BLOB receive_blob = data_blob_null;
702 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
703 DEBUG(0,("cli_session_setup_blob: cli->max_xmit too small "
704 "(was %u, need minimum %u)\n",
705 (unsigned int)cli->max_xmit,
706 BASE_SESSSETUP_BLOB_PACKET_SIZE));
707 cli_set_nt_error(cli, NT_STATUS_INVALID_PARAMETER);
708 return False;
711 max_blob_size = cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE;
713 while ( remaining > 0) {
714 if (remaining >= max_blob_size) {
715 send_blob.length = max_blob_size;
716 remaining -= max_blob_size;
717 } else {
718 send_blob.length = remaining;
719 remaining = 0;
722 send_blob.data = &blob.data[cur];
723 cur += send_blob.length;
725 DEBUG(10, ("cli_session_setup_blob: Remaining (%u) sending (%u) current (%u)\n",
726 (unsigned int)remaining,
727 (unsigned int)send_blob.length,
728 (unsigned int)cur ));
730 if (!cli_session_setup_blob_send(cli, send_blob)) {
731 DEBUG(0, ("cli_session_setup_blob: send failed\n"));
732 return False;
735 receive_blob = cli_session_setup_blob_receive(cli);
736 data_blob_free(&receive_blob);
738 if (cli_is_error(cli) &&
739 !NT_STATUS_EQUAL( cli_get_nt_error(cli),
740 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
741 DEBUG(0, ("cli_session_setup_blob: receive failed "
742 "(%s)\n", nt_errstr(cli_get_nt_error(cli))));
743 cli->vuid = 0;
744 return False;
748 return True;
751 /****************************************************************************
752 Use in-memory credentials cache
753 ****************************************************************************/
755 static void use_in_memory_ccache(void) {
756 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
759 /****************************************************************************
760 Do a spnego/kerberos encrypted session setup.
761 ****************************************************************************/
763 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
765 DATA_BLOB negTokenTarg;
766 DATA_BLOB session_key_krb5;
767 NTSTATUS nt_status;
768 int rc;
770 cli_temp_set_signing(cli);
772 DEBUG(2,("Doing kerberos session setup\n"));
774 /* generate the encapsulated kerberos5 ticket */
775 rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5, 0, NULL);
777 if (rc) {
778 DEBUG(1, ("cli_session_setup_kerberos: spnego_gen_negTokenTarg failed: %s\n",
779 error_message(rc)));
780 return ADS_ERROR_KRB5(rc);
783 #if 0
784 file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
785 #endif
787 if (!cli_session_setup_blob(cli, negTokenTarg)) {
788 nt_status = cli_nt_error(cli);
789 goto nt_error;
792 if (cli_is_error(cli)) {
793 nt_status = cli_nt_error(cli);
794 if (NT_STATUS_IS_OK(nt_status)) {
795 nt_status = NT_STATUS_UNSUCCESSFUL;
797 goto nt_error;
800 cli_set_session_key(cli, session_key_krb5);
802 if (cli_simple_set_signing(
803 cli, session_key_krb5, data_blob_null)) {
805 if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
806 nt_status = NT_STATUS_ACCESS_DENIED;
807 goto nt_error;
811 data_blob_free(&negTokenTarg);
812 data_blob_free(&session_key_krb5);
814 return ADS_ERROR_NT(NT_STATUS_OK);
816 nt_error:
817 data_blob_free(&negTokenTarg);
818 data_blob_free(&session_key_krb5);
819 cli->vuid = 0;
820 return ADS_ERROR_NT(nt_status);
822 #endif /* HAVE_KRB5 */
825 /****************************************************************************
826 Do a spnego/NTLMSSP encrypted session setup.
827 ****************************************************************************/
829 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
830 const char *pass, const char *domain)
832 struct ntlmssp_state *ntlmssp_state;
833 NTSTATUS nt_status;
834 int turn = 1;
835 DATA_BLOB msg1;
836 DATA_BLOB blob = data_blob_null;
837 DATA_BLOB blob_in = data_blob_null;
838 DATA_BLOB blob_out = data_blob_null;
840 cli_temp_set_signing(cli);
842 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
843 return nt_status;
845 ntlmssp_want_feature(ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
847 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
848 return nt_status;
850 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
851 return nt_status;
853 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
854 return nt_status;
857 do {
858 nt_status = ntlmssp_update(ntlmssp_state,
859 blob_in, &blob_out);
860 data_blob_free(&blob_in);
861 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(nt_status)) {
862 if (turn == 1) {
863 /* and wrap it in a SPNEGO wrapper */
864 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
865 } else {
866 /* wrap it in SPNEGO */
867 msg1 = spnego_gen_auth(blob_out);
870 /* now send that blob on its way */
871 if (!cli_session_setup_blob_send(cli, msg1)) {
872 DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
873 nt_status = NT_STATUS_UNSUCCESSFUL;
874 } else {
875 blob = cli_session_setup_blob_receive(cli);
877 nt_status = cli_nt_error(cli);
878 if (cli_is_error(cli) && NT_STATUS_IS_OK(nt_status)) {
879 if (cli->smb_rw_error == SMB_READ_BAD_SIG) {
880 nt_status = NT_STATUS_ACCESS_DENIED;
881 } else {
882 nt_status = NT_STATUS_UNSUCCESSFUL;
886 data_blob_free(&msg1);
889 if (!blob.length) {
890 if (NT_STATUS_IS_OK(nt_status)) {
891 nt_status = NT_STATUS_UNSUCCESSFUL;
893 } else if ((turn == 1) &&
894 NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
895 DATA_BLOB tmp_blob = data_blob_null;
896 /* the server might give us back two challenges */
897 if (!spnego_parse_challenge(blob, &blob_in,
898 &tmp_blob)) {
899 DEBUG(3,("Failed to parse challenges\n"));
900 nt_status = NT_STATUS_INVALID_PARAMETER;
902 data_blob_free(&tmp_blob);
903 } else {
904 if (!spnego_parse_auth_response(blob, nt_status, OID_NTLMSSP,
905 &blob_in)) {
906 DEBUG(3,("Failed to parse auth response\n"));
907 if (NT_STATUS_IS_OK(nt_status)
908 || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED))
909 nt_status = NT_STATUS_INVALID_PARAMETER;
912 data_blob_free(&blob);
913 data_blob_free(&blob_out);
914 turn++;
915 } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
917 data_blob_free(&blob_in);
919 if (NT_STATUS_IS_OK(nt_status)) {
921 fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
922 cli_set_session_key(cli, ntlmssp_state->session_key);
924 if (cli_simple_set_signing(
925 cli, ntlmssp_state->session_key, data_blob_null)) {
927 if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
928 nt_status = NT_STATUS_ACCESS_DENIED;
933 /* we have a reference conter on ntlmssp_state, if we are signing
934 then the state will be kept by the signing engine */
936 ntlmssp_end(&ntlmssp_state);
938 if (!NT_STATUS_IS_OK(nt_status)) {
939 cli->vuid = 0;
941 return nt_status;
944 /****************************************************************************
945 Do a spnego encrypted session setup.
947 user_domain: The shortname of the domain the user/machine is a member of.
948 dest_realm: The realm we're connecting to, if NULL we use our default realm.
949 ****************************************************************************/
951 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
952 const char *pass, const char *user_domain,
953 const char * dest_realm)
955 char *principal = NULL;
956 char *OIDs[ASN1_MAX_OIDS];
957 int i;
958 DATA_BLOB blob;
959 const char *p = NULL;
960 char *account = NULL;
961 NTSTATUS status;
963 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
965 /* the server might not even do spnego */
966 if (cli->secblob.length <= 16) {
967 DEBUG(3,("server didn't supply a full spnego negprot\n"));
968 goto ntlmssp;
971 #if 0
972 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
973 #endif
975 /* there is 16 bytes of GUID before the real spnego packet starts */
976 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
978 /* The server sent us the first part of the SPNEGO exchange in the
979 * negprot reply. It is WRONG to depend on the principal sent in the
980 * negprot reply, but right now we do it. If we don't receive one,
981 * we try to best guess, then fall back to NTLM. */
982 if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
983 data_blob_free(&blob);
984 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
986 data_blob_free(&blob);
988 /* make sure the server understands kerberos */
989 for (i=0;OIDs[i];i++) {
990 DEBUG(3,("got OID=%s\n", OIDs[i]));
991 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
992 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
993 cli->got_kerberos_mechanism = True;
995 talloc_free(OIDs[i]);
998 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1000 status = cli_set_username(cli, user);
1001 if (!NT_STATUS_IS_OK(status)) {
1002 return ADS_ERROR_NT(status);
1005 #ifdef HAVE_KRB5
1006 /* If password is set we reauthenticate to kerberos server
1007 * and do not store results */
1009 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1010 ADS_STATUS rc;
1012 if (pass && *pass) {
1013 int ret;
1015 use_in_memory_ccache();
1016 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1018 if (ret){
1019 TALLOC_FREE(principal);
1020 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1021 if (cli->fallback_after_kerberos)
1022 goto ntlmssp;
1023 return ADS_ERROR_KRB5(ret);
1027 /* If we get a bad principal, try to guess it if
1028 we have a valid host NetBIOS name.
1030 if (strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1031 TALLOC_FREE(principal);
1034 if (principal == NULL &&
1035 !is_ipaddress(cli->desthost) &&
1036 !strequal(STAR_SMBSERVER,
1037 cli->desthost)) {
1038 char *realm = NULL;
1039 char *machine = NULL;
1040 char *host = NULL;
1041 DEBUG(3,("cli_session_setup_spnego: got a "
1042 "bad server principal, trying to guess ...\n"));
1044 host = strchr_m(cli->desthost, '.');
1045 if (host) {
1046 machine = SMB_STRNDUP(cli->desthost,
1047 host - cli->desthost);
1048 } else {
1049 machine = SMB_STRDUP(cli->desthost);
1051 if (machine == NULL) {
1052 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1055 if (dest_realm) {
1056 realm = SMB_STRDUP(dest_realm);
1057 strupper_m(realm);
1058 } else {
1059 realm = kerberos_get_default_realm_from_ccache();
1061 if (realm && *realm) {
1062 principal = talloc_asprintf(NULL, "%s$@%s",
1063 machine, realm);
1064 if (!principal) {
1065 SAFE_FREE(machine);
1066 SAFE_FREE(realm);
1067 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1069 DEBUG(3,("cli_session_setup_spnego: guessed "
1070 "server principal=%s\n",
1071 principal ? principal : "<null>"));
1073 SAFE_FREE(machine);
1074 SAFE_FREE(realm);
1077 if (principal) {
1078 rc = cli_session_setup_kerberos(cli, principal,
1079 dest_realm);
1080 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1081 TALLOC_FREE(principal);
1082 return rc;
1086 #endif
1088 TALLOC_FREE(principal);
1090 ntlmssp:
1092 account = talloc_strdup(talloc_tos(), user);
1093 if (!account) {
1094 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1097 /* when falling back to ntlmssp while authenticating with a machine
1098 * account strip off the realm - gd */
1100 if ((p = strchr_m(user, '@')) != NULL) {
1101 account[PTR_DIFF(p,user)] = '\0';
1104 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1107 /****************************************************************************
1108 Send a session setup. The username and workgroup is in UNIX character
1109 format and must be converted to DOS codepage format before sending. If the
1110 password is in plaintext, the same should be done.
1111 ****************************************************************************/
1113 NTSTATUS cli_session_setup(struct cli_state *cli,
1114 const char *user,
1115 const char *pass, int passlen,
1116 const char *ntpass, int ntpasslen,
1117 const char *workgroup)
1119 char *p;
1120 fstring user2;
1122 if (user) {
1123 fstrcpy(user2, user);
1124 } else {
1125 user2[0] ='\0';
1128 if (!workgroup) {
1129 workgroup = "";
1132 /* allow for workgroups as part of the username */
1133 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1134 (p=strchr_m(user2,*lp_winbind_separator()))) {
1135 *p = 0;
1136 user = p+1;
1137 workgroup = user2;
1140 if (cli->protocol < PROTOCOL_LANMAN1) {
1141 return NT_STATUS_OK;
1144 /* now work out what sort of session setup we are going to
1145 do. I have split this into separate functions to make the
1146 flow a bit easier to understand (tridge) */
1148 /* if its an older server then we have to use the older request format */
1150 if (cli->protocol < PROTOCOL_NT1) {
1151 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1152 DEBUG(1, ("Server requested LM password but 'client lanman auth'"
1153 " is disabled\n"));
1154 return NT_STATUS_ACCESS_DENIED;
1157 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1158 !lp_client_plaintext_auth() && (*pass)) {
1159 DEBUG(1, ("Server requested plaintext password but "
1160 "'client plaintext auth' is disabled\n"));
1161 return NT_STATUS_ACCESS_DENIED;
1164 return cli_session_setup_lanman2(cli, user, pass, passlen,
1165 workgroup);
1168 /* if no user is supplied then we have to do an anonymous connection.
1169 passwords are ignored */
1171 if (!user || !*user)
1172 return cli_session_setup_guest(cli);
1174 /* if the server is share level then send a plaintext null
1175 password at this point. The password is sent in the tree
1176 connect */
1178 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
1179 return cli_session_setup_plaintext(cli, user, "", workgroup);
1181 /* if the server doesn't support encryption then we have to use
1182 plaintext. The second password is ignored */
1184 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1185 if (!lp_client_plaintext_auth() && (*pass)) {
1186 DEBUG(1, ("Server requested plaintext password but "
1187 "'client plaintext auth' is disabled\n"));
1188 return NT_STATUS_ACCESS_DENIED;
1190 return cli_session_setup_plaintext(cli, user, pass, workgroup);
1193 /* if the server supports extended security then use SPNEGO */
1195 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
1196 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
1197 workgroup, NULL);
1198 if (!ADS_ERR_OK(status)) {
1199 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1200 return ads_ntstatus(status);
1202 } else {
1203 NTSTATUS status;
1205 /* otherwise do a NT1 style session setup */
1206 status = cli_session_setup_nt1(cli, user, pass, passlen,
1207 ntpass, ntpasslen, workgroup);
1208 if (!NT_STATUS_IS_OK(status)) {
1209 DEBUG(3,("cli_session_setup: NT1 session setup "
1210 "failed: %s\n", nt_errstr(status)));
1211 return status;
1215 if (strstr(cli->server_type, "Samba")) {
1216 cli->is_samba = True;
1219 return NT_STATUS_OK;
1222 /****************************************************************************
1223 Send a uloggoff.
1224 *****************************************************************************/
1226 bool cli_ulogoff(struct cli_state *cli)
1228 memset(cli->outbuf,'\0',smb_size);
1229 cli_set_message(cli->outbuf,2,0,True);
1230 SCVAL(cli->outbuf,smb_com,SMBulogoffX);
1231 cli_setup_packet(cli);
1232 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1233 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1235 cli_send_smb(cli);
1236 if (!cli_receive_smb(cli))
1237 return False;
1239 if (cli_is_error(cli)) {
1240 return False;
1243 cli->vuid = -1;
1244 return True;
1247 /****************************************************************************
1248 Send a tconX.
1249 ****************************************************************************/
1251 struct cli_tcon_andx_state {
1252 struct cli_state *cli;
1253 uint16_t vwv[4];
1254 struct iovec bytes;
1257 static void cli_tcon_andx_done(struct tevent_req *subreq);
1259 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1260 struct event_context *ev,
1261 struct cli_state *cli,
1262 const char *share, const char *dev,
1263 const char *pass, int passlen,
1264 struct tevent_req **psmbreq)
1266 struct tevent_req *req, *subreq;
1267 struct cli_tcon_andx_state *state;
1268 fstring pword;
1269 uint16_t *vwv;
1270 char *tmp = NULL;
1271 uint8_t *bytes;
1273 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1274 if (req == NULL) {
1275 return NULL;
1277 state->cli = cli;
1278 vwv = state->vwv;
1280 fstrcpy(cli->share, share);
1282 /* in user level security don't send a password now */
1283 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1284 passlen = 1;
1285 pass = "";
1286 } else if (pass == NULL) {
1287 DEBUG(1, ("Server not using user level security and no "
1288 "password supplied.\n"));
1289 goto access_denied;
1292 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1293 *pass && passlen != 24) {
1294 if (!lp_client_lanman_auth()) {
1295 DEBUG(1, ("Server requested LANMAN password "
1296 "(share-level security) but "
1297 "'client lanman auth' is disabled\n"));
1298 goto access_denied;
1302 * Non-encrypted passwords - convert to DOS codepage before
1303 * encryption.
1305 passlen = 24;
1306 SMBencrypt(pass, cli->secblob.data, (uchar *)pword);
1307 } else {
1308 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1309 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1310 == 0) {
1311 if (!lp_client_plaintext_auth() && (*pass)) {
1312 DEBUG(1, ("Server requested plaintext "
1313 "password but 'client plaintext "
1314 "auth' is disabled\n"));
1315 goto access_denied;
1319 * Non-encrypted passwords - convert to DOS codepage
1320 * before using.
1322 passlen = clistr_push(cli, pword, pass, sizeof(pword),
1323 STR_TERMINATE);
1324 if (passlen == -1) {
1325 DEBUG(1, ("clistr_push(pword) failed\n"));
1326 goto access_denied;
1328 } else {
1329 if (passlen) {
1330 memcpy(pword, pass, passlen);
1335 SCVAL(vwv+0, 0, 0xFF);
1336 SCVAL(vwv+0, 1, 0);
1337 SSVAL(vwv+1, 0, 0);
1338 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
1339 SSVAL(vwv+3, 0, passlen);
1341 if (passlen) {
1342 bytes = (uint8_t *)talloc_memdup(state, pword, passlen);
1343 } else {
1344 bytes = talloc_array(state, uint8_t, 0);
1348 * Add the sharename
1350 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1351 cli->desthost, share);
1352 if (tmp == NULL) {
1353 TALLOC_FREE(req);
1354 return NULL;
1356 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
1357 NULL);
1358 TALLOC_FREE(tmp);
1361 * Add the devicetype
1363 tmp = talloc_strdup_upper(talloc_tos(), dev);
1364 if (tmp == NULL) {
1365 TALLOC_FREE(req);
1366 return NULL;
1368 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
1369 TALLOC_FREE(tmp);
1371 if (bytes == NULL) {
1372 TALLOC_FREE(req);
1373 return NULL;
1376 state->bytes.iov_base = (void *)bytes;
1377 state->bytes.iov_len = talloc_get_size(bytes);
1379 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
1380 1, &state->bytes);
1381 if (subreq == NULL) {
1382 TALLOC_FREE(req);
1383 return NULL;
1385 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
1386 *psmbreq = subreq;
1387 return req;
1389 access_denied:
1390 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1391 return tevent_req_post(req, ev);
1394 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
1395 struct event_context *ev,
1396 struct cli_state *cli,
1397 const char *share, const char *dev,
1398 const char *pass, int passlen)
1400 struct tevent_req *req, *subreq;
1401 NTSTATUS status;
1403 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
1404 &subreq);
1405 if (req == NULL) {
1406 return NULL;
1408 status = cli_smb_req_send(subreq);
1409 if (!NT_STATUS_IS_OK(status)) {
1410 tevent_req_nterror(req, status);
1411 return tevent_req_post(req, ev);
1413 return req;
1416 static void cli_tcon_andx_done(struct tevent_req *subreq)
1418 struct tevent_req *req = tevent_req_callback_data(
1419 subreq, struct tevent_req);
1420 struct cli_tcon_andx_state *state = tevent_req_data(
1421 req, struct cli_tcon_andx_state);
1422 struct cli_state *cli = state->cli;
1423 char *inbuf = (char *)cli_smb_inbuf(subreq);
1424 uint8_t wct;
1425 uint16_t *vwv;
1426 uint32_t num_bytes;
1427 uint8_t *bytes;
1428 NTSTATUS status;
1430 status = cli_smb_recv(subreq, 0, &wct, &vwv, &num_bytes, &bytes);
1431 if (!NT_STATUS_IS_OK(status)) {
1432 TALLOC_FREE(subreq);
1433 tevent_req_nterror(req, status);
1434 return;
1437 clistr_pull(inbuf, cli->dev, bytes, sizeof(fstring), num_bytes,
1438 STR_TERMINATE|STR_ASCII);
1440 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
1441 /* almost certainly win95 - enable bug fixes */
1442 cli->win95 = True;
1446 * Make sure that we have the optional support 16-bit field. WCT > 2.
1447 * Avoids issues when connecting to Win9x boxes sharing files
1450 cli->dfsroot = false;
1452 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
1453 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
1456 cli->cnum = SVAL(inbuf,smb_tid);
1457 tevent_req_done(req);
1460 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
1462 return tevent_req_simple_recv_ntstatus(req);
1465 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
1466 const char *dev, const char *pass, int passlen)
1468 TALLOC_CTX *frame = talloc_stackframe();
1469 struct event_context *ev;
1470 struct tevent_req *req;
1471 NTSTATUS status = NT_STATUS_OK;
1473 if (cli_has_async_calls(cli)) {
1475 * Can't use sync call while an async call is in flight
1477 status = NT_STATUS_INVALID_PARAMETER;
1478 goto fail;
1481 ev = event_context_init(frame);
1482 if (ev == NULL) {
1483 status = NT_STATUS_NO_MEMORY;
1484 goto fail;
1487 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
1488 if (req == NULL) {
1489 status = NT_STATUS_NO_MEMORY;
1490 goto fail;
1493 if (!tevent_req_poll(req, ev)) {
1494 status = map_nt_error_from_unix(errno);
1495 goto fail;
1498 status = cli_tcon_andx_recv(req);
1499 fail:
1500 TALLOC_FREE(frame);
1501 if (!NT_STATUS_IS_OK(status)) {
1502 cli_set_error(cli, status);
1504 return status;
1507 /****************************************************************************
1508 Send a tree disconnect.
1509 ****************************************************************************/
1511 bool cli_tdis(struct cli_state *cli)
1513 memset(cli->outbuf,'\0',smb_size);
1514 cli_set_message(cli->outbuf,0,0,True);
1515 SCVAL(cli->outbuf,smb_com,SMBtdis);
1516 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1517 cli_setup_packet(cli);
1519 cli_send_smb(cli);
1520 if (!cli_receive_smb(cli))
1521 return False;
1523 if (cli_is_error(cli)) {
1524 return False;
1527 cli->cnum = -1;
1528 return True;
1531 /****************************************************************************
1532 Send a negprot command.
1533 ****************************************************************************/
1535 void cli_negprot_sendsync(struct cli_state *cli)
1537 char *p;
1538 int numprots;
1540 if (cli->protocol < PROTOCOL_NT1)
1541 cli->use_spnego = False;
1543 memset(cli->outbuf,'\0',smb_size);
1545 /* setup the protocol strings */
1546 cli_set_message(cli->outbuf,0,0,True);
1548 p = smb_buf(cli->outbuf);
1549 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1550 if (prots[numprots].prot > cli->protocol) {
1551 break;
1553 *p++ = 2;
1554 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1557 SCVAL(cli->outbuf,smb_com,SMBnegprot);
1558 cli_setup_bcc(cli, p);
1559 cli_setup_packet(cli);
1561 SCVAL(smb_buf(cli->outbuf),0,2);
1563 cli_send_smb(cli);
1566 /****************************************************************************
1567 Send a negprot command.
1568 ****************************************************************************/
1570 struct cli_negprot_state {
1571 struct cli_state *cli;
1574 static void cli_negprot_done(struct tevent_req *subreq);
1576 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
1577 struct event_context *ev,
1578 struct cli_state *cli)
1580 struct tevent_req *req, *subreq;
1581 struct cli_negprot_state *state;
1582 uint8_t *bytes = NULL;
1583 int numprots;
1585 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
1586 if (req == NULL) {
1587 return NULL;
1589 state->cli = cli;
1591 if (cli->protocol < PROTOCOL_NT1)
1592 cli->use_spnego = False;
1594 /* setup the protocol strings */
1595 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1596 uint8_t c = 2;
1597 if (prots[numprots].prot > cli->protocol) {
1598 break;
1600 bytes = (uint8_t *)talloc_append_blob(
1601 state, bytes, data_blob_const(&c, sizeof(c)));
1602 if (tevent_req_nomem(bytes, req)) {
1603 return tevent_req_post(req, ev);
1605 bytes = smb_bytes_push_str(bytes, false,
1606 prots[numprots].name,
1607 strlen(prots[numprots].name)+1,
1608 NULL);
1609 if (tevent_req_nomem(bytes, req)) {
1610 return tevent_req_post(req, ev);
1614 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
1615 talloc_get_size(bytes), bytes);
1616 if (tevent_req_nomem(subreq, req)) {
1617 return tevent_req_post(req, ev);
1619 tevent_req_set_callback(subreq, cli_negprot_done, req);
1620 return req;
1623 static void cli_negprot_done(struct tevent_req *subreq)
1625 struct tevent_req *req = tevent_req_callback_data(
1626 subreq, struct tevent_req);
1627 struct cli_negprot_state *state = tevent_req_data(
1628 req, struct cli_negprot_state);
1629 struct cli_state *cli = state->cli;
1630 uint8_t wct;
1631 uint16_t *vwv;
1632 uint32_t num_bytes;
1633 uint8_t *bytes;
1634 NTSTATUS status;
1635 uint16_t protnum;
1637 status = cli_smb_recv(subreq, 1, &wct, &vwv, &num_bytes, &bytes);
1638 if (!NT_STATUS_IS_OK(status)) {
1639 TALLOC_FREE(subreq);
1640 return;
1643 protnum = SVAL(vwv, 0);
1645 if ((protnum >= ARRAY_SIZE(prots))
1646 || (prots[protnum].prot > cli->protocol)) {
1647 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1648 return;
1651 cli->protocol = prots[protnum].prot;
1653 if ((cli->protocol < PROTOCOL_NT1) &&
1654 client_is_signing_mandatory(cli)) {
1655 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1656 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1657 return;
1660 if (cli->protocol >= PROTOCOL_NT1) {
1661 struct timespec ts;
1662 bool negotiated_smb_signing = false;
1664 /* NT protocol */
1665 cli->sec_mode = CVAL(vwv + 1, 0);
1666 cli->max_mux = SVAL(vwv + 1, 1);
1667 cli->max_xmit = IVAL(vwv + 3, 1);
1668 cli->sesskey = IVAL(vwv + 7, 1);
1669 cli->serverzone = SVALS(vwv + 15, 1);
1670 cli->serverzone *= 60;
1671 /* this time arrives in real GMT */
1672 ts = interpret_long_date(((char *)(vwv+11))+1);
1673 cli->servertime = ts.tv_sec;
1674 cli->secblob = data_blob(bytes, num_bytes);
1675 cli->capabilities = IVAL(vwv + 9, 1);
1676 if (cli->capabilities & CAP_RAW_MODE) {
1677 cli->readbraw_supported = True;
1678 cli->writebraw_supported = True;
1680 /* work out if they sent us a workgroup */
1681 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1682 smb_buflen(cli->inbuf) > 8) {
1683 clistr_pull(cli->inbuf, cli->server_domain,
1684 bytes+8, sizeof(cli->server_domain),
1685 num_bytes-8,
1686 STR_UNICODE|STR_NOALIGN);
1690 * As signing is slow we only turn it on if either the client or
1691 * the server require it. JRA.
1694 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
1695 /* Fail if server says signing is mandatory and we don't want to support it. */
1696 if (!client_is_signing_allowed(cli)) {
1697 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1698 tevent_req_nterror(req,
1699 NT_STATUS_ACCESS_DENIED);
1700 return;
1702 negotiated_smb_signing = true;
1703 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
1704 /* Fail if client says signing is mandatory and the server doesn't support it. */
1705 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
1706 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1707 tevent_req_nterror(req,
1708 NT_STATUS_ACCESS_DENIED);
1709 return;
1711 negotiated_smb_signing = true;
1712 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
1713 negotiated_smb_signing = true;
1716 if (negotiated_smb_signing) {
1717 cli_set_signing_negotiated(cli);
1720 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
1721 SAFE_FREE(cli->outbuf);
1722 SAFE_FREE(cli->inbuf);
1723 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1724 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1725 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
1728 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1729 cli->use_spnego = False;
1730 cli->sec_mode = SVAL(vwv + 1, 0);
1731 cli->max_xmit = SVAL(vwv + 2, 0);
1732 cli->max_mux = SVAL(vwv + 3, 0);
1733 cli->sesskey = IVAL(vwv + 6, 0);
1734 cli->serverzone = SVALS(vwv + 10, 0);
1735 cli->serverzone *= 60;
1736 /* this time is converted to GMT by make_unix_date */
1737 cli->servertime = cli_make_unix_date(
1738 cli, (char *)(vwv + 8));
1739 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
1740 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
1741 cli->secblob = data_blob(bytes, num_bytes);
1742 } else {
1743 /* the old core protocol */
1744 cli->use_spnego = False;
1745 cli->sec_mode = 0;
1746 cli->serverzone = get_time_zone(time(NULL));
1749 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1751 /* a way to force ascii SMB */
1752 if (getenv("CLI_FORCE_ASCII"))
1753 cli->capabilities &= ~CAP_UNICODE;
1755 tevent_req_done(req);
1758 NTSTATUS cli_negprot_recv(struct tevent_req *req)
1760 return tevent_req_simple_recv_ntstatus(req);
1763 NTSTATUS cli_negprot(struct cli_state *cli)
1765 TALLOC_CTX *frame = talloc_stackframe();
1766 struct event_context *ev;
1767 struct tevent_req *req;
1768 NTSTATUS status = NT_STATUS_OK;
1770 if (cli_has_async_calls(cli)) {
1772 * Can't use sync call while an async call is in flight
1774 status = NT_STATUS_INVALID_PARAMETER;
1775 goto fail;
1778 ev = event_context_init(frame);
1779 if (ev == NULL) {
1780 status = NT_STATUS_NO_MEMORY;
1781 goto fail;
1784 req = cli_negprot_send(frame, ev, cli);
1785 if (req == NULL) {
1786 status = NT_STATUS_NO_MEMORY;
1787 goto fail;
1790 if (!tevent_req_poll(req, ev)) {
1791 status = map_nt_error_from_unix(errno);
1792 goto fail;
1795 status = cli_negprot_recv(req);
1796 fail:
1797 TALLOC_FREE(frame);
1798 if (!NT_STATUS_IS_OK(status)) {
1799 cli_set_error(cli, status);
1801 return status;
1804 /****************************************************************************
1805 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1806 ****************************************************************************/
1808 bool cli_session_request(struct cli_state *cli,
1809 struct nmb_name *calling, struct nmb_name *called)
1811 char *p;
1812 int len = 4;
1813 char *tmp;
1815 /* 445 doesn't have session request */
1816 if (cli->port == 445)
1817 return True;
1819 memcpy(&(cli->calling), calling, sizeof(*calling));
1820 memcpy(&(cli->called ), called , sizeof(*called ));
1822 /* put in the destination name */
1824 tmp = name_mangle(talloc_tos(), cli->called.name,
1825 cli->called.name_type);
1826 if (tmp == NULL) {
1827 return false;
1830 p = cli->outbuf+len;
1831 memcpy(p, tmp, name_len(tmp));
1832 len += name_len(tmp);
1833 TALLOC_FREE(tmp);
1835 /* and my name */
1837 tmp = name_mangle(talloc_tos(), cli->calling.name,
1838 cli->calling.name_type);
1839 if (tmp == NULL) {
1840 return false;
1843 p = cli->outbuf+len;
1844 memcpy(p, tmp, name_len(tmp));
1845 len += name_len(tmp);
1846 TALLOC_FREE(tmp);
1848 /* send a session request (RFC 1002) */
1849 /* setup the packet length
1850 * Remove four bytes from the length count, since the length
1851 * field in the NBT Session Service header counts the number
1852 * of bytes which follow. The cli_send_smb() function knows
1853 * about this and accounts for those four bytes.
1854 * CRH.
1856 len -= 4;
1857 _smb_setlen(cli->outbuf,len);
1858 SCVAL(cli->outbuf,0,0x81);
1860 cli_send_smb(cli);
1861 DEBUG(5,("Sent session request\n"));
1863 if (!cli_receive_smb(cli))
1864 return False;
1866 if (CVAL(cli->inbuf,0) == 0x84) {
1867 /* C. Hoch 9/14/95 Start */
1868 /* For information, here is the response structure.
1869 * We do the byte-twiddling to for portability.
1870 struct RetargetResponse{
1871 unsigned char type;
1872 unsigned char flags;
1873 int16 length;
1874 int32 ip_addr;
1875 int16 port;
1878 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1879 struct in_addr dest_ip;
1880 NTSTATUS status;
1882 /* SESSION RETARGET */
1883 putip((char *)&dest_ip,cli->inbuf+4);
1884 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
1886 status = open_socket_out(&cli->dest_ss, port,
1887 LONG_CONNECT_TIMEOUT, &cli->fd);
1888 if (!NT_STATUS_IS_OK(status)) {
1889 return False;
1892 DEBUG(3,("Retargeted\n"));
1894 set_socket_options(cli->fd, lp_socket_options());
1896 /* Try again */
1898 static int depth;
1899 bool ret;
1900 if (depth > 4) {
1901 DEBUG(0,("Retarget recursion - failing\n"));
1902 return False;
1904 depth++;
1905 ret = cli_session_request(cli, calling, called);
1906 depth--;
1907 return ret;
1909 } /* C. Hoch 9/14/95 End */
1911 if (CVAL(cli->inbuf,0) != 0x82) {
1912 /* This is the wrong place to put the error... JRA. */
1913 cli->rap_error = CVAL(cli->inbuf,4);
1914 return False;
1916 return(True);
1919 struct fd_struct {
1920 int fd;
1923 static void smb_sock_connected(struct tevent_req *req)
1925 struct fd_struct *pfd = tevent_req_callback_data(
1926 req, struct fd_struct);
1927 int fd;
1928 NTSTATUS status;
1930 status = open_socket_out_defer_recv(req, &fd);
1931 if (NT_STATUS_IS_OK(status)) {
1932 pfd->fd = fd;
1936 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
1937 uint16_t *port, int timeout, int *pfd)
1939 struct event_context *ev;
1940 struct tevent_req *r139, *r445;
1941 struct fd_struct *fd139, *fd445;
1942 NTSTATUS status = NT_STATUS_NO_MEMORY;
1944 if (*port != 0) {
1945 return open_socket_out(pss, *port, timeout, pfd);
1948 ev = event_context_init(talloc_tos());
1949 if (ev == NULL) {
1950 return NT_STATUS_NO_MEMORY;
1953 fd139 = talloc(ev, struct fd_struct);
1954 if (fd139 == NULL) {
1955 goto done;
1957 fd139->fd = -1;
1959 fd445 = talloc(ev, struct fd_struct);
1960 if (fd445 == NULL) {
1961 goto done;
1963 fd445->fd = -1;
1965 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
1966 pss, 445, timeout);
1967 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
1968 pss, 139, timeout);
1969 if ((r445 == NULL) || (r139 == NULL)) {
1970 goto done;
1972 tevent_req_set_callback(r445, smb_sock_connected, fd445);
1973 tevent_req_set_callback(r139, smb_sock_connected, fd139);
1975 while ((fd445->fd == -1) && (fd139->fd == -1)
1976 && (tevent_req_is_in_progress(r139)
1977 || tevent_req_is_in_progress(r445))) {
1978 event_loop_once(ev);
1981 if ((fd139->fd != -1) && (fd445->fd != -1)) {
1982 close(fd139->fd);
1983 fd139->fd = -1;
1986 if (fd445->fd != -1) {
1987 *port = 445;
1988 *pfd = fd445->fd;
1989 status = NT_STATUS_OK;
1990 goto done;
1992 if (fd139->fd != -1) {
1993 *port = 139;
1994 *pfd = fd139->fd;
1995 status = NT_STATUS_OK;
1996 goto done;
1999 status = open_socket_out_defer_recv(r445, &fd445->fd);
2000 done:
2001 TALLOC_FREE(ev);
2002 return status;
2005 /****************************************************************************
2006 Open the client sockets.
2007 ****************************************************************************/
2009 NTSTATUS cli_connect(struct cli_state *cli,
2010 const char *host,
2011 struct sockaddr_storage *dest_ss)
2014 int name_type = 0x20;
2015 TALLOC_CTX *frame = talloc_stackframe();
2016 unsigned int num_addrs = 0;
2017 unsigned int i = 0;
2018 struct sockaddr_storage *ss_arr = NULL;
2019 char *p = NULL;
2021 /* reasonable default hostname */
2022 if (!host) {
2023 host = STAR_SMBSERVER;
2026 fstrcpy(cli->desthost, host);
2028 /* allow hostnames of the form NAME#xx and do a netbios lookup */
2029 if ((p = strchr(cli->desthost, '#'))) {
2030 name_type = strtol(p+1, NULL, 16);
2031 *p = 0;
2034 if (!dest_ss || is_zero_addr((struct sockaddr *)dest_ss)) {
2035 NTSTATUS status =resolve_name_list(frame,
2036 cli->desthost,
2037 name_type,
2038 &ss_arr,
2039 &num_addrs);
2040 if (!NT_STATUS_IS_OK(status)) {
2041 TALLOC_FREE(frame);
2042 return NT_STATUS_BAD_NETWORK_NAME;
2044 } else {
2045 num_addrs = 1;
2046 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
2047 if (!ss_arr) {
2048 TALLOC_FREE(frame);
2049 return NT_STATUS_NO_MEMORY;
2051 *ss_arr = *dest_ss;
2054 for (i = 0; i < num_addrs; i++) {
2055 cli->dest_ss = ss_arr[i];
2056 if (getenv("LIBSMB_PROG")) {
2057 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
2058 } else {
2059 uint16_t port = cli->port;
2060 NTSTATUS status;
2061 status = open_smb_socket(&cli->dest_ss, &port,
2062 cli->timeout, &cli->fd);
2063 if (NT_STATUS_IS_OK(status)) {
2064 cli->port = port;
2067 if (cli->fd == -1) {
2068 char addr[INET6_ADDRSTRLEN];
2069 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
2070 DEBUG(2,("Error connecting to %s (%s)\n",
2071 dest_ss?addr:host,strerror(errno)));
2072 } else {
2073 /* Exit from loop on first connection. */
2074 break;
2078 if (cli->fd == -1) {
2079 TALLOC_FREE(frame);
2080 return map_nt_error_from_unix(errno);
2083 if (dest_ss) {
2084 *dest_ss = cli->dest_ss;
2087 set_socket_options(cli->fd, lp_socket_options());
2089 TALLOC_FREE(frame);
2090 return NT_STATUS_OK;
2094 establishes a connection to after the negprot.
2095 @param output_cli A fully initialised cli structure, non-null only on success
2096 @param dest_host The netbios name of the remote host
2097 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2098 @param port (optional) The destination port (0 for default)
2099 @param retry bool. Did this connection fail with a retryable error ?
2102 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2103 const char *my_name,
2104 const char *dest_host,
2105 struct sockaddr_storage *dest_ss, int port,
2106 int signing_state, int flags,
2107 bool *retry)
2109 NTSTATUS nt_status;
2110 struct nmb_name calling;
2111 struct nmb_name called;
2112 struct cli_state *cli;
2113 struct sockaddr_storage ss;
2115 if (retry)
2116 *retry = False;
2118 if (!my_name)
2119 my_name = global_myname();
2121 if (!(cli = cli_initialise_ex(signing_state))) {
2122 return NT_STATUS_NO_MEMORY;
2125 make_nmb_name(&calling, my_name, 0x0);
2126 make_nmb_name(&called , dest_host, 0x20);
2128 cli_set_port(cli, port);
2129 cli_set_timeout(cli, 10000); /* 10 seconds. */
2131 if (dest_ss) {
2132 ss = *dest_ss;
2133 } else {
2134 zero_sockaddr(&ss);
2137 again:
2139 DEBUG(3,("Connecting to host=%s\n", dest_host));
2141 nt_status = cli_connect(cli, dest_host, &ss);
2142 if (!NT_STATUS_IS_OK(nt_status)) {
2143 char addr[INET6_ADDRSTRLEN];
2144 print_sockaddr(addr, sizeof(addr), &ss);
2145 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
2146 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
2147 cli_shutdown(cli);
2148 return nt_status;
2151 if (retry)
2152 *retry = True;
2154 if (!cli_session_request(cli, &calling, &called)) {
2155 char *p;
2156 DEBUG(1,("session request to %s failed (%s)\n",
2157 called.name, cli_errstr(cli)));
2158 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
2159 *p = 0;
2160 goto again;
2162 if (strcmp(called.name, STAR_SMBSERVER)) {
2163 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
2164 goto again;
2166 return NT_STATUS_BAD_NETWORK_NAME;
2169 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
2170 cli->use_spnego = False;
2171 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
2172 cli->use_kerberos = True;
2174 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
2175 cli->use_kerberos) {
2176 cli->fallback_after_kerberos = true;
2179 nt_status = cli_negprot(cli);
2180 if (!NT_STATUS_IS_OK(nt_status)) {
2181 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2182 cli_shutdown(cli);
2183 return nt_status;
2186 *output_cli = cli;
2187 return NT_STATUS_OK;
2192 establishes a connection right up to doing tconX, password specified.
2193 @param output_cli A fully initialised cli structure, non-null only on success
2194 @param dest_host The netbios name of the remote host
2195 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2196 @param port (optional) The destination port (0 for default)
2197 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2198 @param service_type The 'type' of serivice.
2199 @param user Username, unix string
2200 @param domain User's domain
2201 @param password User's password, unencrypted unix string.
2202 @param retry bool. Did this connection fail with a retryable error ?
2205 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2206 const char *my_name,
2207 const char *dest_host,
2208 struct sockaddr_storage *dest_ss, int port,
2209 const char *service, const char *service_type,
2210 const char *user, const char *domain,
2211 const char *password, int flags,
2212 int signing_state,
2213 bool *retry)
2215 NTSTATUS nt_status;
2216 struct cli_state *cli = NULL;
2217 int pw_len = password ? strlen(password)+1 : 0;
2219 *output_cli = NULL;
2221 if (password == NULL) {
2222 password = "";
2225 nt_status = cli_start_connection(&cli, my_name, dest_host,
2226 dest_ss, port, signing_state,
2227 flags, retry);
2229 if (!NT_STATUS_IS_OK(nt_status)) {
2230 return nt_status;
2233 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
2234 cli->use_level_II_oplocks =
2235 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
2237 nt_status = cli_session_setup(cli, user, password, pw_len, password,
2238 pw_len, domain);
2239 if (!NT_STATUS_IS_OK(nt_status)) {
2241 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2242 DEBUG(1,("failed session setup with %s\n",
2243 nt_errstr(nt_status)));
2244 cli_shutdown(cli);
2245 return nt_status;
2248 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2249 if (!NT_STATUS_IS_OK(nt_status)) {
2250 DEBUG(1,("anonymous failed session setup with %s\n",
2251 nt_errstr(nt_status)));
2252 cli_shutdown(cli);
2253 return nt_status;
2257 if (service) {
2258 nt_status = cli_tcon_andx(cli, service, service_type, password,
2259 pw_len);
2260 if (!NT_STATUS_IS_OK(nt_status)) {
2261 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2262 cli_shutdown(cli);
2263 if (NT_STATUS_IS_OK(nt_status)) {
2264 nt_status = NT_STATUS_UNSUCCESSFUL;
2266 return nt_status;
2270 nt_status = cli_init_creds(cli, user, domain, password);
2271 if (!NT_STATUS_IS_OK(nt_status)) {
2272 cli_shutdown(cli);
2273 return nt_status;
2276 *output_cli = cli;
2277 return NT_STATUS_OK;
2280 /****************************************************************************
2281 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2282 ****************************************************************************/
2284 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
2285 struct sockaddr_storage *pdest_ss)
2287 struct nmb_name calling, called;
2289 make_nmb_name(&calling, srchost, 0x0);
2292 * If the called name is an IP address
2293 * then use *SMBSERVER immediately.
2296 if(is_ipaddress(desthost)) {
2297 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
2298 } else {
2299 make_nmb_name(&called, desthost, 0x20);
2302 if (!cli_session_request(*ppcli, &calling, &called)) {
2303 NTSTATUS status;
2304 struct nmb_name smbservername;
2306 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
2309 * If the name wasn't *SMBSERVER then
2310 * try with *SMBSERVER if the first name fails.
2313 if (nmb_name_equal(&called, &smbservername)) {
2316 * The name used was *SMBSERVER, don't bother with another name.
2319 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2320 with error %s.\n", desthost, cli_errstr(*ppcli) ));
2321 return False;
2324 /* Try again... */
2325 cli_shutdown(*ppcli);
2327 *ppcli = cli_initialise();
2328 if (!*ppcli) {
2329 /* Out of memory... */
2330 return False;
2333 status = cli_connect(*ppcli, desthost, pdest_ss);
2334 if (!NT_STATUS_IS_OK(status) ||
2335 !cli_session_request(*ppcli, &calling, &smbservername)) {
2336 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2337 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
2338 return False;
2342 return True;
2345 /****************************************************************************
2346 Send an old style tcon.
2347 ****************************************************************************/
2348 NTSTATUS cli_raw_tcon(struct cli_state *cli,
2349 const char *service, const char *pass, const char *dev,
2350 uint16 *max_xmit, uint16 *tid)
2352 char *p;
2354 if (!lp_client_plaintext_auth() && (*pass)) {
2355 DEBUG(1, ("Server requested plaintext password but 'client "
2356 "plaintext auth' is disabled\n"));
2357 return NT_STATUS_ACCESS_DENIED;
2360 memset(cli->outbuf,'\0',smb_size);
2361 memset(cli->inbuf,'\0',smb_size);
2363 cli_set_message(cli->outbuf, 0, 0, True);
2364 SCVAL(cli->outbuf,smb_com,SMBtcon);
2365 cli_setup_packet(cli);
2367 p = smb_buf(cli->outbuf);
2368 *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
2369 *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
2370 *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
2372 cli_setup_bcc(cli, p);
2374 cli_send_smb(cli);
2375 if (!cli_receive_smb(cli)) {
2376 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2379 if (cli_is_error(cli)) {
2380 return cli_nt_error(cli);
2383 *max_xmit = SVAL(cli->inbuf, smb_vwv0);
2384 *tid = SVAL(cli->inbuf, smb_vwv1);
2386 return NT_STATUS_OK;
2389 /* Return a cli_state pointing at the IPC$ share for the given server */
2391 struct cli_state *get_ipc_connect(char *server,
2392 struct sockaddr_storage *server_ss,
2393 const struct user_auth_info *user_info)
2395 struct cli_state *cli;
2396 NTSTATUS nt_status;
2397 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2399 if (user_info->use_kerberos) {
2400 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2403 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
2404 user_info->username ? user_info->username : "",
2405 lp_workgroup(),
2406 user_info->password ? user_info->password : "",
2407 flags,
2408 Undefined, NULL);
2410 if (NT_STATUS_IS_OK(nt_status)) {
2411 return cli;
2412 } else if (is_ipaddress(server)) {
2413 /* windows 9* needs a correct NMB name for connections */
2414 fstring remote_name;
2416 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2417 cli = get_ipc_connect(remote_name, server_ss, user_info);
2418 if (cli)
2419 return cli;
2422 return NULL;
2426 * Given the IP address of a master browser on the network, return its
2427 * workgroup and connect to it.
2429 * This function is provided to allow additional processing beyond what
2430 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2431 * browsers and obtain each master browsers' list of domains (in case the
2432 * first master browser is recently on the network and has not yet
2433 * synchronized with other master browsers and therefore does not yet have the
2434 * entire network browse list)
2437 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2438 struct ip_service *mb_ip,
2439 const struct user_auth_info *user_info,
2440 char **pp_workgroup_out)
2442 char addr[INET6_ADDRSTRLEN];
2443 fstring name;
2444 struct cli_state *cli;
2445 struct sockaddr_storage server_ss;
2447 *pp_workgroup_out = NULL;
2449 print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2450 DEBUG(99, ("Looking up name of master browser %s\n",
2451 addr));
2454 * Do a name status query to find out the name of the master browser.
2455 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2456 * master browser will not respond to a wildcard query (or, at least,
2457 * an NT4 server acting as the domain master browser will not).
2459 * We might be able to use ONLY the query on MSBROWSE, but that's not
2460 * yet been tested with all Windows versions, so until it is, leave
2461 * the original wildcard query as the first choice and fall back to
2462 * MSBROWSE if the wildcard query fails.
2464 if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2465 !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2467 DEBUG(99, ("Could not retrieve name status for %s\n",
2468 addr));
2469 return NULL;
2472 if (!find_master_ip(name, &server_ss)) {
2473 DEBUG(99, ("Could not find master ip for %s\n", name));
2474 return NULL;
2477 *pp_workgroup_out = talloc_strdup(ctx, name);
2479 DEBUG(4, ("found master browser %s, %s\n", name, addr));
2481 print_sockaddr(addr, sizeof(addr), &server_ss);
2482 cli = get_ipc_connect(addr, &server_ss, user_info);
2484 return cli;
2488 * Return the IP address and workgroup of a master browser on the network, and
2489 * connect to it.
2492 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2493 const struct user_auth_info *user_info,
2494 char **pp_workgroup_out)
2496 struct ip_service *ip_list;
2497 struct cli_state *cli;
2498 int i, count;
2500 *pp_workgroup_out = NULL;
2502 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2504 /* Go looking for workgroups by broadcasting on the local network */
2506 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2507 &count))) {
2508 DEBUG(99, ("No master browsers responded\n"));
2509 return False;
2512 for (i = 0; i < count; i++) {
2513 char addr[INET6_ADDRSTRLEN];
2514 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2515 DEBUG(99, ("Found master browser %s\n", addr));
2517 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2518 user_info, pp_workgroup_out);
2519 if (cli)
2520 return(cli);
2523 return NULL;