Add a bad hack to enable level 2 oplocks in torture_open_connection_share
[Samba.git] / source3 / libsmb / cliconnect.c
blob53a812d222f5a14acf3542ee6e3b0512b7a97636
1 /*
2 Unix SMB/CIFS implementation.
3 client connect/disconnect routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Andrew Bartlett 2001-2003
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
23 static const struct {
24 int prot;
25 const char name[24];
26 } prots[10] = {
27 {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
28 {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
29 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
30 {PROTOCOL_LANMAN1, "LANMAN1.0"},
31 {PROTOCOL_LANMAN2, "LM1.2X002"},
32 {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
33 {PROTOCOL_LANMAN2, "LANMAN2.1"},
34 {PROTOCOL_LANMAN2, "Samba"},
35 {PROTOCOL_NT1, "NT LANMAN 1.0"},
36 {PROTOCOL_NT1, "NT LM 0.12"},
39 #define STAR_SMBSERVER "*SMBSERVER"
41 /**
42 * Set the user session key for a connection
43 * @param cli The cli structure to add it too
44 * @param session_key The session key used. (A copy of this is taken for the cli struct)
48 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
50 cli->user_session_key = data_blob(session_key.data, session_key.length);
53 /****************************************************************************
54 Do an old lanman2 style session setup.
55 ****************************************************************************/
57 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
58 const char *user,
59 const char *pass, size_t passlen,
60 const char *workgroup)
62 DATA_BLOB session_key = data_blob_null;
63 DATA_BLOB lm_response = data_blob_null;
64 NTSTATUS status;
65 fstring pword;
66 char *p;
68 if (passlen > sizeof(pword)-1) {
69 return NT_STATUS_INVALID_PARAMETER;
72 /* LANMAN servers predate NT status codes and Unicode and ignore those
73 smb flags so we must disable the corresponding default capabilities
74 that would otherwise cause the Unicode and NT Status flags to be
75 set (and even returned by the server) */
77 cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
79 /* if in share level security then don't send a password now */
80 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
81 passlen = 0;
83 if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
84 /* Encrypted mode needed, and non encrypted password supplied. */
85 lm_response = data_blob(NULL, 24);
86 if (!SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data)) {
87 DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n"));
88 return NT_STATUS_ACCESS_DENIED;
90 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
91 /* Encrypted mode needed, and encrypted password supplied. */
92 lm_response = data_blob(pass, passlen);
93 } else if (passlen > 0) {
94 /* Plaintext mode needed, assume plaintext supplied. */
95 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
96 lm_response = data_blob(pass, passlen);
99 /* send a session setup command */
100 memset(cli->outbuf,'\0',smb_size);
101 cli_set_message(cli->outbuf,10, 0, True);
102 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
103 cli_setup_packet(cli);
105 SCVAL(cli->outbuf,smb_vwv0,0xFF);
106 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
107 SSVAL(cli->outbuf,smb_vwv3,2);
108 SSVAL(cli->outbuf,smb_vwv4,1);
109 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
110 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
112 p = smb_buf(cli->outbuf);
113 memcpy(p,lm_response.data,lm_response.length);
114 p += lm_response.length;
115 p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
116 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
117 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
118 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
119 cli_setup_bcc(cli, p);
121 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
122 return cli_nt_error(cli);
125 show_msg(cli->inbuf);
127 if (cli_is_error(cli)) {
128 return cli_nt_error(cli);
131 /* use the returned vuid from now on */
132 cli->vuid = SVAL(cli->inbuf,smb_uid);
133 status = cli_set_username(cli, user);
134 if (!NT_STATUS_IS_OK(status)) {
135 return status;
138 if (session_key.data) {
139 /* Have plaintext orginal */
140 cli_set_session_key(cli, session_key);
143 return NT_STATUS_OK;
146 /****************************************************************************
147 Work out suitable capabilities to offer the server.
148 ****************************************************************************/
150 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
152 uint32 capabilities = CAP_NT_SMBS;
154 if (!cli->force_dos_errors)
155 capabilities |= CAP_STATUS32;
157 if (cli->use_level_II_oplocks)
158 capabilities |= CAP_LEVEL_II_OPLOCKS;
160 capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
161 return capabilities;
164 /****************************************************************************
165 Do a NT1 guest session setup.
166 ****************************************************************************/
168 struct cli_session_setup_guest_state {
169 struct cli_state *cli;
170 uint16_t vwv[16];
173 static void cli_session_setup_guest_done(struct tevent_req *subreq);
175 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
176 struct event_context *ev,
177 struct cli_state *cli)
179 struct tevent_req *req, *subreq;
180 struct cli_session_setup_guest_state *state;
181 uint16_t *vwv;
182 uint8_t *bytes;
184 req = tevent_req_create(mem_ctx, &state,
185 struct cli_session_setup_guest_state);
186 if (req == NULL) {
187 return NULL;
189 state->cli = cli;
190 vwv = state->vwv;
192 SCVAL(vwv+0, 0, 0xFF);
193 SCVAL(vwv+0, 1, 0);
194 SSVAL(vwv+1, 0, 0);
195 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
196 SSVAL(vwv+3, 0, 2);
197 SSVAL(vwv+4, 0, cli->pid);
198 SIVAL(vwv+5, 0, cli->sesskey);
199 SSVAL(vwv+7, 0, 0);
200 SSVAL(vwv+8, 0, 0);
201 SSVAL(vwv+9, 0, 0);
202 SSVAL(vwv+10, 0, 0);
203 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
205 bytes = talloc_array(state, uint8_t, 0);
207 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
208 NULL);
209 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
210 NULL);
211 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
212 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
214 if (tevent_req_nomem(bytes, req)) {
215 return tevent_req_post(req, ev);
218 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
219 talloc_get_size(bytes), bytes);
220 if (tevent_req_nomem(subreq, req)) {
221 return tevent_req_post(req, ev);
223 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
224 return req;
227 static void cli_session_setup_guest_done(struct tevent_req *subreq)
229 struct tevent_req *req = tevent_req_callback_data(
230 subreq, struct tevent_req);
231 struct cli_session_setup_guest_state *state = tevent_req_data(
232 req, struct cli_session_setup_guest_state);
233 struct cli_state *cli = state->cli;
234 uint32_t num_bytes;
235 char *inbuf;
236 uint8_t *bytes;
237 uint8_t *p;
238 NTSTATUS status;
240 status = cli_smb_recv(subreq, 0, NULL, NULL, &num_bytes, &bytes);
241 if (!NT_STATUS_IS_OK(status)) {
242 TALLOC_FREE(subreq);
243 tevent_req_nterror(req, status);
244 return;
247 inbuf = (char *)cli_smb_inbuf(subreq);
248 p = bytes;
250 cli->vuid = SVAL(inbuf, smb_uid);
252 p += clistr_pull(inbuf, cli->server_os, (char *)p, sizeof(fstring),
253 bytes+num_bytes-p, STR_TERMINATE);
254 p += clistr_pull(inbuf, cli->server_type, (char *)p, sizeof(fstring),
255 bytes+num_bytes-p, STR_TERMINATE);
256 p += clistr_pull(inbuf, cli->server_domain, (char *)p, sizeof(fstring),
257 bytes+num_bytes-p, STR_TERMINATE);
259 if (strstr(cli->server_type, "Samba")) {
260 cli->is_samba = True;
263 TALLOC_FREE(subreq);
265 status = cli_set_username(cli, "");
266 if (!NT_STATUS_IS_OK(status)) {
267 tevent_req_nterror(req, status);
268 return;
270 tevent_req_done(req);
273 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
275 return tevent_req_simple_recv_ntstatus(req);
278 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
280 TALLOC_CTX *frame = talloc_stackframe();
281 struct event_context *ev;
282 struct tevent_req *req;
283 NTSTATUS status = NT_STATUS_OK;
285 if (cli_has_async_calls(cli)) {
287 * Can't use sync call while an async call is in flight
289 status = NT_STATUS_INVALID_PARAMETER;
290 goto fail;
293 ev = event_context_init(frame);
294 if (ev == NULL) {
295 status = NT_STATUS_NO_MEMORY;
296 goto fail;
299 req = cli_session_setup_guest_send(frame, ev, cli);
300 if (req == NULL) {
301 status = NT_STATUS_NO_MEMORY;
302 goto fail;
305 if (!tevent_req_poll(req, ev)) {
306 status = map_nt_error_from_unix(errno);
307 goto fail;
310 status = cli_session_setup_guest_recv(req);
311 fail:
312 TALLOC_FREE(frame);
313 if (!NT_STATUS_IS_OK(status)) {
314 cli_set_error(cli, status);
316 return status;
319 /****************************************************************************
320 Do a NT1 plaintext session setup.
321 ****************************************************************************/
323 static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
324 const char *user, const char *pass,
325 const char *workgroup)
327 uint32 capabilities = cli_session_setup_capabilities(cli);
328 char *p;
329 NTSTATUS status;
330 fstring lanman;
332 fstr_sprintf( lanman, "Samba %s", samba_version_string());
334 memset(cli->outbuf, '\0', smb_size);
335 cli_set_message(cli->outbuf,13,0,True);
336 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
337 cli_setup_packet(cli);
339 SCVAL(cli->outbuf,smb_vwv0,0xFF);
340 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
341 SSVAL(cli->outbuf,smb_vwv3,2);
342 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
343 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
344 SSVAL(cli->outbuf,smb_vwv8,0);
345 SIVAL(cli->outbuf,smb_vwv11,capabilities);
346 p = smb_buf(cli->outbuf);
348 /* check wether to send the ASCII or UNICODE version of the password */
350 if ( (capabilities & CAP_UNICODE) == 0 ) {
351 p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
352 SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
354 else {
355 /* For ucs2 passwords clistr_push calls ucs2_align, which causes
356 * the space taken by the unicode password to be one byte too
357 * long (as we're on an odd byte boundary here). Reduce the
358 * count by 1 to cope with this. Fixes smbclient against NetApp
359 * servers which can't cope. Fix from
360 * bryan.kolodziej@allenlund.com in bug #3840.
362 p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
363 SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))-1);
366 p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
367 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
368 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
369 p += clistr_push(cli, p, lanman, -1, STR_TERMINATE);
370 cli_setup_bcc(cli, p);
372 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
373 return cli_nt_error(cli);
376 show_msg(cli->inbuf);
378 if (cli_is_error(cli)) {
379 return cli_nt_error(cli);
382 cli->vuid = SVAL(cli->inbuf,smb_uid);
383 p = smb_buf(cli->inbuf);
384 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
385 -1, STR_TERMINATE);
386 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
387 -1, STR_TERMINATE);
388 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
389 -1, STR_TERMINATE);
390 status = cli_set_username(cli, user);
391 if (!NT_STATUS_IS_OK(status)) {
392 return status;
394 if (strstr(cli->server_type, "Samba")) {
395 cli->is_samba = True;
398 return NT_STATUS_OK;
401 /****************************************************************************
402 do a NT1 NTLM/LM encrypted session setup - for when extended security
403 is not negotiated.
404 @param cli client state to create do session setup on
405 @param user username
406 @param pass *either* cleartext password (passlen !=24) or LM response.
407 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
408 @param workgroup The user's domain.
409 ****************************************************************************/
411 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
412 const char *pass, size_t passlen,
413 const char *ntpass, size_t ntpasslen,
414 const char *workgroup)
416 uint32 capabilities = cli_session_setup_capabilities(cli);
417 DATA_BLOB lm_response = data_blob_null;
418 DATA_BLOB nt_response = data_blob_null;
419 DATA_BLOB session_key = data_blob_null;
420 NTSTATUS result;
421 char *p;
422 bool ok;
424 if (passlen == 0) {
425 /* do nothing - guest login */
426 } else if (passlen != 24) {
427 if (lp_client_ntlmv2_auth()) {
428 DATA_BLOB server_chal;
429 DATA_BLOB names_blob;
430 server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8));
432 /* note that the 'workgroup' here is a best guess - we don't know
433 the server's domain at this point. The 'server name' is also
434 dodgy...
436 names_blob = NTLMv2_generate_names_blob(cli->called.name, workgroup);
438 if (!SMBNTLMv2encrypt(user, workgroup, pass, &server_chal,
439 &names_blob,
440 &lm_response, &nt_response, &session_key)) {
441 data_blob_free(&names_blob);
442 data_blob_free(&server_chal);
443 return NT_STATUS_ACCESS_DENIED;
445 data_blob_free(&names_blob);
446 data_blob_free(&server_chal);
448 } else {
449 uchar nt_hash[16];
450 E_md4hash(pass, nt_hash);
452 #ifdef LANMAN_ONLY
453 nt_response = data_blob_null;
454 #else
455 nt_response = data_blob(NULL, 24);
456 SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
457 #endif
458 /* non encrypted password supplied. Ignore ntpass. */
459 if (lp_client_lanman_auth()) {
460 lm_response = data_blob(NULL, 24);
461 if (!SMBencrypt(pass,cli->secblob.data, lm_response.data)) {
462 /* Oops, the LM response is invalid, just put
463 the NT response there instead */
464 data_blob_free(&lm_response);
465 lm_response = data_blob(nt_response.data, nt_response.length);
467 } else {
468 /* LM disabled, place NT# in LM field instead */
469 lm_response = data_blob(nt_response.data, nt_response.length);
472 session_key = data_blob(NULL, 16);
473 #ifdef LANMAN_ONLY
474 E_deshash(pass, session_key.data);
475 memset(&session_key.data[8], '\0', 8);
476 #else
477 SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
478 #endif
480 cli_temp_set_signing(cli);
481 } else {
482 /* pre-encrypted password supplied. Only used for
483 security=server, can't do
484 signing because we don't have original key */
486 lm_response = data_blob(pass, passlen);
487 nt_response = data_blob(ntpass, ntpasslen);
490 /* send a session setup command */
491 memset(cli->outbuf,'\0',smb_size);
493 cli_set_message(cli->outbuf,13,0,True);
494 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
495 cli_setup_packet(cli);
497 SCVAL(cli->outbuf,smb_vwv0,0xFF);
498 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
499 SSVAL(cli->outbuf,smb_vwv3,2);
500 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
501 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
502 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
503 SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
504 SIVAL(cli->outbuf,smb_vwv11,capabilities);
505 p = smb_buf(cli->outbuf);
506 if (lm_response.length) {
507 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
509 if (nt_response.length) {
510 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
512 p += clistr_push(cli, p, user, -1, STR_TERMINATE);
514 /* Upper case here might help some NTLMv2 implementations */
515 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
516 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
517 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
518 cli_setup_bcc(cli, p);
520 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
521 result = cli_nt_error(cli);
522 goto end;
525 /* show_msg(cli->inbuf); */
527 if (cli_is_error(cli)) {
528 result = cli_nt_error(cli);
529 goto end;
532 #ifdef LANMAN_ONLY
533 ok = cli_simple_set_signing(cli, session_key, lm_response);
534 #else
535 ok = cli_simple_set_signing(cli, session_key, nt_response);
536 #endif
537 if (ok) {
538 if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
539 result = NT_STATUS_ACCESS_DENIED;
540 goto end;
544 /* use the returned vuid from now on */
545 cli->vuid = SVAL(cli->inbuf,smb_uid);
547 p = smb_buf(cli->inbuf);
548 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
549 -1, STR_TERMINATE);
550 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
551 -1, STR_TERMINATE);
552 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
553 -1, STR_TERMINATE);
555 if (strstr(cli->server_type, "Samba")) {
556 cli->is_samba = True;
559 result = cli_set_username(cli, user);
560 if (!NT_STATUS_IS_OK(result)) {
561 goto end;
564 if (session_key.data) {
565 /* Have plaintext orginal */
566 cli_set_session_key(cli, session_key);
569 result = NT_STATUS_OK;
570 end:
571 data_blob_free(&lm_response);
572 data_blob_free(&nt_response);
573 data_blob_free(&session_key);
574 return result;
577 /****************************************************************************
578 Send a extended security session setup blob
579 ****************************************************************************/
581 static bool cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob)
583 uint32 capabilities = cli_session_setup_capabilities(cli);
584 char *p;
586 capabilities |= CAP_EXTENDED_SECURITY;
588 /* send a session setup command */
589 memset(cli->outbuf,'\0',smb_size);
591 cli_set_message(cli->outbuf,12,0,True);
592 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
594 cli_setup_packet(cli);
596 SCVAL(cli->outbuf,smb_vwv0,0xFF);
597 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
598 SSVAL(cli->outbuf,smb_vwv3,2);
599 SSVAL(cli->outbuf,smb_vwv4,1);
600 SIVAL(cli->outbuf,smb_vwv5,0);
601 SSVAL(cli->outbuf,smb_vwv7,blob.length);
602 SIVAL(cli->outbuf,smb_vwv10,capabilities);
603 p = smb_buf(cli->outbuf);
604 memcpy(p, blob.data, blob.length);
605 p += blob.length;
606 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
607 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
608 cli_setup_bcc(cli, p);
609 return cli_send_smb(cli);
612 /****************************************************************************
613 Send a extended security session setup blob, returning a reply blob.
614 ****************************************************************************/
616 static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli)
618 DATA_BLOB blob2 = data_blob_null;
619 char *p;
620 size_t len;
622 if (!cli_receive_smb(cli))
623 return blob2;
625 show_msg(cli->inbuf);
627 if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli),
628 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
629 return blob2;
632 /* use the returned vuid from now on */
633 cli->vuid = SVAL(cli->inbuf,smb_uid);
635 p = smb_buf(cli->inbuf);
637 blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3));
639 p += blob2.length;
640 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
641 -1, STR_TERMINATE);
643 /* w2k with kerberos doesn't properly null terminate this field */
644 len = smb_bufrem(cli->inbuf, p);
645 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
646 len, 0);
648 return blob2;
651 #ifdef HAVE_KRB5
652 /****************************************************************************
653 Send a extended security session setup blob, returning a reply blob.
654 ****************************************************************************/
656 /* The following is calculated from :
657 * (smb_size-4) = 35
658 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
659 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
660 * end of packet.
663 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
665 static bool cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
667 int32 remaining = blob.length;
668 int32 cur = 0;
669 DATA_BLOB send_blob = data_blob_null;
670 int32 max_blob_size = 0;
671 DATA_BLOB receive_blob = data_blob_null;
673 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
674 DEBUG(0,("cli_session_setup_blob: cli->max_xmit too small "
675 "(was %u, need minimum %u)\n",
676 (unsigned int)cli->max_xmit,
677 BASE_SESSSETUP_BLOB_PACKET_SIZE));
678 cli_set_nt_error(cli, NT_STATUS_INVALID_PARAMETER);
679 return False;
682 max_blob_size = cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE;
684 while ( remaining > 0) {
685 if (remaining >= max_blob_size) {
686 send_blob.length = max_blob_size;
687 remaining -= max_blob_size;
688 } else {
689 send_blob.length = remaining;
690 remaining = 0;
693 send_blob.data = &blob.data[cur];
694 cur += send_blob.length;
696 DEBUG(10, ("cli_session_setup_blob: Remaining (%u) sending (%u) current (%u)\n",
697 (unsigned int)remaining,
698 (unsigned int)send_blob.length,
699 (unsigned int)cur ));
701 if (!cli_session_setup_blob_send(cli, send_blob)) {
702 DEBUG(0, ("cli_session_setup_blob: send failed\n"));
703 return False;
706 receive_blob = cli_session_setup_blob_receive(cli);
707 data_blob_free(&receive_blob);
709 if (cli_is_error(cli) &&
710 !NT_STATUS_EQUAL( cli_get_nt_error(cli),
711 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
712 DEBUG(0, ("cli_session_setup_blob: receive failed "
713 "(%s)\n", nt_errstr(cli_get_nt_error(cli))));
714 cli->vuid = 0;
715 return False;
719 return True;
722 /****************************************************************************
723 Use in-memory credentials cache
724 ****************************************************************************/
726 static void use_in_memory_ccache(void) {
727 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
730 /****************************************************************************
731 Do a spnego/kerberos encrypted session setup.
732 ****************************************************************************/
734 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
736 DATA_BLOB negTokenTarg;
737 DATA_BLOB session_key_krb5;
738 NTSTATUS nt_status;
739 int rc;
741 cli_temp_set_signing(cli);
743 DEBUG(2,("Doing kerberos session setup\n"));
745 /* generate the encapsulated kerberos5 ticket */
746 rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5, 0, NULL);
748 if (rc) {
749 DEBUG(1, ("cli_session_setup_kerberos: spnego_gen_negTokenTarg failed: %s\n",
750 error_message(rc)));
751 return ADS_ERROR_KRB5(rc);
754 #if 0
755 file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
756 #endif
758 if (!cli_session_setup_blob(cli, negTokenTarg)) {
759 nt_status = cli_nt_error(cli);
760 goto nt_error;
763 if (cli_is_error(cli)) {
764 nt_status = cli_nt_error(cli);
765 if (NT_STATUS_IS_OK(nt_status)) {
766 nt_status = NT_STATUS_UNSUCCESSFUL;
768 goto nt_error;
771 cli_set_session_key(cli, session_key_krb5);
773 if (cli_simple_set_signing(
774 cli, session_key_krb5, data_blob_null)) {
776 if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
777 nt_status = NT_STATUS_ACCESS_DENIED;
778 goto nt_error;
782 data_blob_free(&negTokenTarg);
783 data_blob_free(&session_key_krb5);
785 return ADS_ERROR_NT(NT_STATUS_OK);
787 nt_error:
788 data_blob_free(&negTokenTarg);
789 data_blob_free(&session_key_krb5);
790 cli->vuid = 0;
791 return ADS_ERROR_NT(nt_status);
793 #endif /* HAVE_KRB5 */
796 /****************************************************************************
797 Do a spnego/NTLMSSP encrypted session setup.
798 ****************************************************************************/
800 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
801 const char *pass, const char *domain)
803 struct ntlmssp_state *ntlmssp_state;
804 NTSTATUS nt_status;
805 int turn = 1;
806 DATA_BLOB msg1;
807 DATA_BLOB blob = data_blob_null;
808 DATA_BLOB blob_in = data_blob_null;
809 DATA_BLOB blob_out = data_blob_null;
811 cli_temp_set_signing(cli);
813 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
814 return nt_status;
816 ntlmssp_want_feature(ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
818 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
819 return nt_status;
821 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
822 return nt_status;
824 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
825 return nt_status;
828 do {
829 nt_status = ntlmssp_update(ntlmssp_state,
830 blob_in, &blob_out);
831 data_blob_free(&blob_in);
832 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(nt_status)) {
833 if (turn == 1) {
834 /* and wrap it in a SPNEGO wrapper */
835 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
836 } else {
837 /* wrap it in SPNEGO */
838 msg1 = spnego_gen_auth(blob_out);
841 /* now send that blob on its way */
842 if (!cli_session_setup_blob_send(cli, msg1)) {
843 DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
844 nt_status = NT_STATUS_UNSUCCESSFUL;
845 } else {
846 blob = cli_session_setup_blob_receive(cli);
848 nt_status = cli_nt_error(cli);
849 if (cli_is_error(cli) && NT_STATUS_IS_OK(nt_status)) {
850 if (cli->smb_rw_error == SMB_READ_BAD_SIG) {
851 nt_status = NT_STATUS_ACCESS_DENIED;
852 } else {
853 nt_status = NT_STATUS_UNSUCCESSFUL;
857 data_blob_free(&msg1);
860 if (!blob.length) {
861 if (NT_STATUS_IS_OK(nt_status)) {
862 nt_status = NT_STATUS_UNSUCCESSFUL;
864 } else if ((turn == 1) &&
865 NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
866 DATA_BLOB tmp_blob = data_blob_null;
867 /* the server might give us back two challenges */
868 if (!spnego_parse_challenge(blob, &blob_in,
869 &tmp_blob)) {
870 DEBUG(3,("Failed to parse challenges\n"));
871 nt_status = NT_STATUS_INVALID_PARAMETER;
873 data_blob_free(&tmp_blob);
874 } else {
875 if (!spnego_parse_auth_response(blob, nt_status, OID_NTLMSSP,
876 &blob_in)) {
877 DEBUG(3,("Failed to parse auth response\n"));
878 if (NT_STATUS_IS_OK(nt_status)
879 || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED))
880 nt_status = NT_STATUS_INVALID_PARAMETER;
883 data_blob_free(&blob);
884 data_blob_free(&blob_out);
885 turn++;
886 } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
888 data_blob_free(&blob_in);
890 if (NT_STATUS_IS_OK(nt_status)) {
892 fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
893 cli_set_session_key(cli, ntlmssp_state->session_key);
895 if (cli_simple_set_signing(
896 cli, ntlmssp_state->session_key, data_blob_null)) {
898 if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
899 nt_status = NT_STATUS_ACCESS_DENIED;
904 /* we have a reference conter on ntlmssp_state, if we are signing
905 then the state will be kept by the signing engine */
907 ntlmssp_end(&ntlmssp_state);
909 if (!NT_STATUS_IS_OK(nt_status)) {
910 cli->vuid = 0;
912 return nt_status;
915 /****************************************************************************
916 Do a spnego encrypted session setup.
918 user_domain: The shortname of the domain the user/machine is a member of.
919 dest_realm: The realm we're connecting to, if NULL we use our default realm.
920 ****************************************************************************/
922 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
923 const char *pass, const char *user_domain,
924 const char * dest_realm)
926 char *principal = NULL;
927 char *OIDs[ASN1_MAX_OIDS];
928 int i;
929 DATA_BLOB blob;
930 const char *p = NULL;
931 char *account = NULL;
932 NTSTATUS status;
934 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
936 /* the server might not even do spnego */
937 if (cli->secblob.length <= 16) {
938 DEBUG(3,("server didn't supply a full spnego negprot\n"));
939 goto ntlmssp;
942 #if 0
943 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
944 #endif
946 /* there is 16 bytes of GUID before the real spnego packet starts */
947 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
949 /* The server sent us the first part of the SPNEGO exchange in the
950 * negprot reply. It is WRONG to depend on the principal sent in the
951 * negprot reply, but right now we do it. If we don't receive one,
952 * we try to best guess, then fall back to NTLM. */
953 if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
954 data_blob_free(&blob);
955 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
957 data_blob_free(&blob);
959 /* make sure the server understands kerberos */
960 for (i=0;OIDs[i];i++) {
961 DEBUG(3,("got OID=%s\n", OIDs[i]));
962 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
963 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
964 cli->got_kerberos_mechanism = True;
966 talloc_free(OIDs[i]);
969 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
971 status = cli_set_username(cli, user);
972 if (!NT_STATUS_IS_OK(status)) {
973 return ADS_ERROR_NT(status);
976 #ifdef HAVE_KRB5
977 /* If password is set we reauthenticate to kerberos server
978 * and do not store results */
980 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
981 ADS_STATUS rc;
983 if (pass && *pass) {
984 int ret;
986 use_in_memory_ccache();
987 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
989 if (ret){
990 TALLOC_FREE(principal);
991 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
992 if (cli->fallback_after_kerberos)
993 goto ntlmssp;
994 return ADS_ERROR_KRB5(ret);
998 /* If we get a bad principal, try to guess it if
999 we have a valid host NetBIOS name.
1001 if (strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1002 TALLOC_FREE(principal);
1005 if (principal == NULL &&
1006 !is_ipaddress(cli->desthost) &&
1007 !strequal(STAR_SMBSERVER,
1008 cli->desthost)) {
1009 char *realm = NULL;
1010 char *machine = NULL;
1011 char *host = NULL;
1012 DEBUG(3,("cli_session_setup_spnego: got a "
1013 "bad server principal, trying to guess ...\n"));
1015 host = strchr_m(cli->desthost, '.');
1016 if (host) {
1017 machine = SMB_STRNDUP(cli->desthost,
1018 host - cli->desthost);
1019 } else {
1020 machine = SMB_STRDUP(cli->desthost);
1022 if (machine == NULL) {
1023 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1026 if (dest_realm) {
1027 realm = SMB_STRDUP(dest_realm);
1028 strupper_m(realm);
1029 } else {
1030 realm = kerberos_get_default_realm_from_ccache();
1032 if (realm && *realm) {
1033 principal = talloc_asprintf(NULL, "%s$@%s",
1034 machine, realm);
1035 if (!principal) {
1036 SAFE_FREE(machine);
1037 SAFE_FREE(realm);
1038 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1040 DEBUG(3,("cli_session_setup_spnego: guessed "
1041 "server principal=%s\n",
1042 principal ? principal : "<null>"));
1044 SAFE_FREE(machine);
1045 SAFE_FREE(realm);
1048 if (principal) {
1049 rc = cli_session_setup_kerberos(cli, principal,
1050 dest_realm);
1051 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1052 TALLOC_FREE(principal);
1053 return rc;
1057 #endif
1059 TALLOC_FREE(principal);
1061 ntlmssp:
1063 account = talloc_strdup(talloc_tos(), user);
1064 if (!account) {
1065 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1068 /* when falling back to ntlmssp while authenticating with a machine
1069 * account strip off the realm - gd */
1071 if ((p = strchr_m(user, '@')) != NULL) {
1072 account[PTR_DIFF(p,user)] = '\0';
1075 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1078 /****************************************************************************
1079 Send a session setup. The username and workgroup is in UNIX character
1080 format and must be converted to DOS codepage format before sending. If the
1081 password is in plaintext, the same should be done.
1082 ****************************************************************************/
1084 NTSTATUS cli_session_setup(struct cli_state *cli,
1085 const char *user,
1086 const char *pass, int passlen,
1087 const char *ntpass, int ntpasslen,
1088 const char *workgroup)
1090 char *p;
1091 fstring user2;
1093 if (user) {
1094 fstrcpy(user2, user);
1095 } else {
1096 user2[0] ='\0';
1099 if (!workgroup) {
1100 workgroup = "";
1103 /* allow for workgroups as part of the username */
1104 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1105 (p=strchr_m(user2,*lp_winbind_separator()))) {
1106 *p = 0;
1107 user = p+1;
1108 workgroup = user2;
1111 if (cli->protocol < PROTOCOL_LANMAN1) {
1112 return NT_STATUS_OK;
1115 /* now work out what sort of session setup we are going to
1116 do. I have split this into separate functions to make the
1117 flow a bit easier to understand (tridge) */
1119 /* if its an older server then we have to use the older request format */
1121 if (cli->protocol < PROTOCOL_NT1) {
1122 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1123 DEBUG(1, ("Server requested LM password but 'client lanman auth'"
1124 " is disabled\n"));
1125 return NT_STATUS_ACCESS_DENIED;
1128 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1129 !lp_client_plaintext_auth() && (*pass)) {
1130 DEBUG(1, ("Server requested plaintext password but "
1131 "'client plaintext auth' is disabled\n"));
1132 return NT_STATUS_ACCESS_DENIED;
1135 return cli_session_setup_lanman2(cli, user, pass, passlen,
1136 workgroup);
1139 /* if no user is supplied then we have to do an anonymous connection.
1140 passwords are ignored */
1142 if (!user || !*user)
1143 return cli_session_setup_guest(cli);
1145 /* if the server is share level then send a plaintext null
1146 password at this point. The password is sent in the tree
1147 connect */
1149 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
1150 return cli_session_setup_plaintext(cli, user, "", workgroup);
1152 /* if the server doesn't support encryption then we have to use
1153 plaintext. The second password is ignored */
1155 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1156 if (!lp_client_plaintext_auth() && (*pass)) {
1157 DEBUG(1, ("Server requested plaintext password but "
1158 "'client plaintext auth' is disabled\n"));
1159 return NT_STATUS_ACCESS_DENIED;
1161 return cli_session_setup_plaintext(cli, user, pass, workgroup);
1164 /* if the server supports extended security then use SPNEGO */
1166 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
1167 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
1168 workgroup, NULL);
1169 if (!ADS_ERR_OK(status)) {
1170 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1171 return ads_ntstatus(status);
1173 } else {
1174 NTSTATUS status;
1176 /* otherwise do a NT1 style session setup */
1177 status = cli_session_setup_nt1(cli, user, pass, passlen,
1178 ntpass, ntpasslen, workgroup);
1179 if (!NT_STATUS_IS_OK(status)) {
1180 DEBUG(3,("cli_session_setup: NT1 session setup "
1181 "failed: %s\n", nt_errstr(status)));
1182 return status;
1186 if (strstr(cli->server_type, "Samba")) {
1187 cli->is_samba = True;
1190 return NT_STATUS_OK;
1193 /****************************************************************************
1194 Send a uloggoff.
1195 *****************************************************************************/
1197 bool cli_ulogoff(struct cli_state *cli)
1199 memset(cli->outbuf,'\0',smb_size);
1200 cli_set_message(cli->outbuf,2,0,True);
1201 SCVAL(cli->outbuf,smb_com,SMBulogoffX);
1202 cli_setup_packet(cli);
1203 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1204 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1206 cli_send_smb(cli);
1207 if (!cli_receive_smb(cli))
1208 return False;
1210 if (cli_is_error(cli)) {
1211 return False;
1214 cli->cnum = -1;
1215 return True;
1218 /****************************************************************************
1219 Send a tconX.
1220 ****************************************************************************/
1222 struct cli_tcon_andx_state {
1223 struct cli_state *cli;
1224 uint16_t vwv[4];
1227 static void cli_tcon_andx_done(struct tevent_req *subreq);
1229 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
1230 struct event_context *ev,
1231 struct cli_state *cli,
1232 const char *share, const char *dev,
1233 const char *pass, int passlen)
1235 struct tevent_req *req, *subreq;
1236 struct cli_tcon_andx_state *state;
1237 fstring pword;
1238 uint16_t *vwv;
1239 char *tmp = NULL;
1240 uint8_t *bytes;
1242 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1243 if (req == NULL) {
1244 return NULL;
1246 state->cli = cli;
1247 vwv = state->vwv;
1249 fstrcpy(cli->share, share);
1251 /* in user level security don't send a password now */
1252 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1253 passlen = 1;
1254 pass = "";
1255 } else if (pass == NULL) {
1256 DEBUG(1, ("Server not using user level security and no "
1257 "password supplied.\n"));
1258 goto access_denied;
1261 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1262 *pass && passlen != 24) {
1263 if (!lp_client_lanman_auth()) {
1264 DEBUG(1, ("Server requested LANMAN password "
1265 "(share-level security) but "
1266 "'client lanman auth' is disabled\n"));
1267 goto access_denied;
1271 * Non-encrypted passwords - convert to DOS codepage before
1272 * encryption.
1274 passlen = 24;
1275 SMBencrypt(pass, cli->secblob.data, (uchar *)pword);
1276 } else {
1277 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1278 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1279 == 0) {
1280 if (!lp_client_plaintext_auth() && (*pass)) {
1281 DEBUG(1, ("Server requested plaintext "
1282 "password but 'client plaintext "
1283 "auth' is disabled\n"));
1284 goto access_denied;
1288 * Non-encrypted passwords - convert to DOS codepage
1289 * before using.
1291 passlen = clistr_push(cli, pword, pass, sizeof(pword),
1292 STR_TERMINATE);
1293 if (passlen == -1) {
1294 DEBUG(1, ("clistr_push(pword) failed\n"));
1295 goto access_denied;
1297 } else {
1298 if (passlen) {
1299 memcpy(pword, pass, passlen);
1304 SCVAL(vwv+0, 0, 0xFF);
1305 SCVAL(vwv+0, 1, 0);
1306 SSVAL(vwv+1, 0, 0);
1307 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
1308 SSVAL(vwv+3, 0, passlen);
1310 if (passlen) {
1311 bytes = (uint8_t *)talloc_memdup(state, pword, passlen);
1312 } else {
1313 bytes = talloc_array(state, uint8_t, 0);
1317 * Add the sharename
1319 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1320 cli->desthost, share);
1321 if (tevent_req_nomem(tmp, req)) {
1322 return tevent_req_post(req, ev);
1324 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
1325 NULL);
1326 TALLOC_FREE(tmp);
1329 * Add the devicetype
1331 tmp = talloc_strdup_upper(talloc_tos(), dev);
1332 if (tevent_req_nomem(tmp, req)) {
1333 return tevent_req_post(req, ev);
1335 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
1336 TALLOC_FREE(tmp);
1338 if (tevent_req_nomem(bytes, req)) {
1339 return tevent_req_post(req, ev);
1342 subreq = cli_smb_send(state, ev, cli, SMBtconX, 0, 4, vwv,
1343 talloc_get_size(bytes), bytes);
1344 if (tevent_req_nomem(subreq, req)) {
1345 return tevent_req_post(req, ev);
1347 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
1348 return req;
1350 access_denied:
1351 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1352 return tevent_req_post(req, ev);
1355 static void cli_tcon_andx_done(struct tevent_req *subreq)
1357 struct tevent_req *req = tevent_req_callback_data(
1358 subreq, struct tevent_req);
1359 struct cli_tcon_andx_state *state = tevent_req_data(
1360 req, struct cli_tcon_andx_state);
1361 struct cli_state *cli = state->cli;
1362 char *inbuf = (char *)cli_smb_inbuf(subreq);
1363 uint8_t wct;
1364 uint16_t *vwv;
1365 uint32_t num_bytes;
1366 uint8_t *bytes;
1367 NTSTATUS status;
1369 status = cli_smb_recv(subreq, 0, &wct, &vwv, &num_bytes, &bytes);
1370 if (!NT_STATUS_IS_OK(status)) {
1371 TALLOC_FREE(subreq);
1372 tevent_req_nterror(req, status);
1373 return;
1376 clistr_pull(inbuf, cli->dev, bytes, sizeof(fstring), num_bytes,
1377 STR_TERMINATE|STR_ASCII);
1379 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
1380 /* almost certainly win95 - enable bug fixes */
1381 cli->win95 = True;
1385 * Make sure that we have the optional support 16-bit field. WCT > 2.
1386 * Avoids issues when connecting to Win9x boxes sharing files
1389 cli->dfsroot = false;
1391 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
1392 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
1395 cli->cnum = SVAL(inbuf,smb_tid);
1396 tevent_req_done(req);
1399 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
1401 return tevent_req_simple_recv_ntstatus(req);
1404 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
1405 const char *dev, const char *pass, int passlen)
1407 TALLOC_CTX *frame = talloc_stackframe();
1408 struct event_context *ev;
1409 struct tevent_req *req;
1410 NTSTATUS status = NT_STATUS_OK;
1412 if (cli_has_async_calls(cli)) {
1414 * Can't use sync call while an async call is in flight
1416 status = NT_STATUS_INVALID_PARAMETER;
1417 goto fail;
1420 ev = event_context_init(frame);
1421 if (ev == NULL) {
1422 status = NT_STATUS_NO_MEMORY;
1423 goto fail;
1426 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
1427 if (req == NULL) {
1428 status = NT_STATUS_NO_MEMORY;
1429 goto fail;
1432 if (!tevent_req_poll(req, ev)) {
1433 status = map_nt_error_from_unix(errno);
1434 goto fail;
1437 status = cli_tcon_andx_recv(req);
1438 fail:
1439 TALLOC_FREE(frame);
1440 if (!NT_STATUS_IS_OK(status)) {
1441 cli_set_error(cli, status);
1443 return status;
1446 /****************************************************************************
1447 Send a tree disconnect.
1448 ****************************************************************************/
1450 bool cli_tdis(struct cli_state *cli)
1452 memset(cli->outbuf,'\0',smb_size);
1453 cli_set_message(cli->outbuf,0,0,True);
1454 SCVAL(cli->outbuf,smb_com,SMBtdis);
1455 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1456 cli_setup_packet(cli);
1458 cli_send_smb(cli);
1459 if (!cli_receive_smb(cli))
1460 return False;
1462 if (cli_is_error(cli)) {
1463 return False;
1466 cli->cnum = -1;
1467 return True;
1470 /****************************************************************************
1471 Send a negprot command.
1472 ****************************************************************************/
1474 void cli_negprot_sendsync(struct cli_state *cli)
1476 char *p;
1477 int numprots;
1479 if (cli->protocol < PROTOCOL_NT1)
1480 cli->use_spnego = False;
1482 memset(cli->outbuf,'\0',smb_size);
1484 /* setup the protocol strings */
1485 cli_set_message(cli->outbuf,0,0,True);
1487 p = smb_buf(cli->outbuf);
1488 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1489 if (prots[numprots].prot > cli->protocol) {
1490 break;
1492 *p++ = 2;
1493 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1496 SCVAL(cli->outbuf,smb_com,SMBnegprot);
1497 cli_setup_bcc(cli, p);
1498 cli_setup_packet(cli);
1500 SCVAL(smb_buf(cli->outbuf),0,2);
1502 cli_send_smb(cli);
1505 /****************************************************************************
1506 Send a negprot command.
1507 ****************************************************************************/
1509 struct cli_negprot_state {
1510 struct cli_state *cli;
1513 static void cli_negprot_done(struct tevent_req *subreq);
1515 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
1516 struct event_context *ev,
1517 struct cli_state *cli)
1519 struct tevent_req *req, *subreq;
1520 struct cli_negprot_state *state;
1521 uint8_t *bytes = NULL;
1522 int numprots;
1524 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
1525 if (req == NULL) {
1526 return NULL;
1528 state->cli = cli;
1530 if (cli->protocol < PROTOCOL_NT1)
1531 cli->use_spnego = False;
1533 /* setup the protocol strings */
1534 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1535 uint8_t c = 2;
1536 if (prots[numprots].prot > cli->protocol) {
1537 break;
1539 bytes = (uint8_t *)talloc_append_blob(
1540 state, bytes, data_blob_const(&c, sizeof(c)));
1541 if (tevent_req_nomem(bytes, req)) {
1542 return tevent_req_post(req, ev);
1544 bytes = smb_bytes_push_str(bytes, false,
1545 prots[numprots].name,
1546 strlen(prots[numprots].name)+1,
1547 NULL);
1548 if (tevent_req_nomem(bytes, req)) {
1549 return tevent_req_post(req, ev);
1553 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
1554 talloc_get_size(bytes), bytes);
1555 if (tevent_req_nomem(subreq, req)) {
1556 return tevent_req_post(req, ev);
1558 tevent_req_set_callback(subreq, cli_negprot_done, req);
1559 return req;
1562 static void cli_negprot_done(struct tevent_req *subreq)
1564 struct tevent_req *req = tevent_req_callback_data(
1565 subreq, struct tevent_req);
1566 struct cli_negprot_state *state = tevent_req_data(
1567 req, struct cli_negprot_state);
1568 struct cli_state *cli = state->cli;
1569 uint8_t wct;
1570 uint16_t *vwv;
1571 uint32_t num_bytes;
1572 uint8_t *bytes;
1573 NTSTATUS status;
1574 uint16_t protnum;
1576 status = cli_smb_recv(subreq, 1, &wct, &vwv, &num_bytes, &bytes);
1577 if (!NT_STATUS_IS_OK(status)) {
1578 TALLOC_FREE(subreq);
1579 return;
1582 protnum = SVAL(vwv, 0);
1584 if ((protnum >= ARRAY_SIZE(prots))
1585 || (prots[protnum].prot > cli->protocol)) {
1586 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1587 return;
1590 cli->protocol = prots[protnum].prot;
1592 if ((cli->protocol < PROTOCOL_NT1) &&
1593 client_is_signing_mandatory(cli)) {
1594 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1595 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1596 return;
1599 if (cli->protocol >= PROTOCOL_NT1) {
1600 struct timespec ts;
1601 bool negotiated_smb_signing = false;
1603 /* NT protocol */
1604 cli->sec_mode = CVAL(vwv + 1, 0);
1605 cli->max_mux = SVAL(vwv + 1, 1);
1606 cli->max_xmit = IVAL(vwv + 3, 1);
1607 cli->sesskey = IVAL(vwv + 7, 1);
1608 cli->serverzone = SVALS(vwv + 15, 1);
1609 cli->serverzone *= 60;
1610 /* this time arrives in real GMT */
1611 ts = interpret_long_date(((char *)(vwv+11))+1);
1612 cli->servertime = ts.tv_sec;
1613 cli->secblob = data_blob(bytes, num_bytes);
1614 cli->capabilities = IVAL(vwv + 9, 1);
1615 if (cli->capabilities & CAP_RAW_MODE) {
1616 cli->readbraw_supported = True;
1617 cli->writebraw_supported = True;
1619 /* work out if they sent us a workgroup */
1620 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1621 smb_buflen(cli->inbuf) > 8) {
1622 clistr_pull(cli->inbuf, cli->server_domain,
1623 bytes+8, sizeof(cli->server_domain),
1624 num_bytes-8,
1625 STR_UNICODE|STR_NOALIGN);
1629 * As signing is slow we only turn it on if either the client or
1630 * the server require it. JRA.
1633 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
1634 /* Fail if server says signing is mandatory and we don't want to support it. */
1635 if (!client_is_signing_allowed(cli)) {
1636 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1637 tevent_req_nterror(req,
1638 NT_STATUS_ACCESS_DENIED);
1639 return;
1641 negotiated_smb_signing = true;
1642 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
1643 /* Fail if client says signing is mandatory and the server doesn't support it. */
1644 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
1645 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1646 tevent_req_nterror(req,
1647 NT_STATUS_ACCESS_DENIED);
1648 return;
1650 negotiated_smb_signing = true;
1651 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
1652 negotiated_smb_signing = true;
1655 if (negotiated_smb_signing) {
1656 cli_set_signing_negotiated(cli);
1659 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
1660 SAFE_FREE(cli->outbuf);
1661 SAFE_FREE(cli->inbuf);
1662 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1663 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1664 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
1667 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1668 cli->use_spnego = False;
1669 cli->sec_mode = SVAL(vwv + 1, 0);
1670 cli->max_xmit = SVAL(vwv + 2, 0);
1671 cli->max_mux = SVAL(vwv + 3, 0);
1672 cli->sesskey = IVAL(vwv + 6, 0);
1673 cli->serverzone = SVALS(vwv + 10, 0);
1674 cli->serverzone *= 60;
1675 /* this time is converted to GMT by make_unix_date */
1676 cli->servertime = cli_make_unix_date(
1677 cli, (char *)(vwv + 8));
1678 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
1679 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
1680 cli->secblob = data_blob(bytes, num_bytes);
1681 } else {
1682 /* the old core protocol */
1683 cli->use_spnego = False;
1684 cli->sec_mode = 0;
1685 cli->serverzone = get_time_zone(time(NULL));
1688 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1690 /* a way to force ascii SMB */
1691 if (getenv("CLI_FORCE_ASCII"))
1692 cli->capabilities &= ~CAP_UNICODE;
1694 tevent_req_done(req);
1697 NTSTATUS cli_negprot_recv(struct tevent_req *req)
1699 return tevent_req_simple_recv_ntstatus(req);
1702 NTSTATUS cli_negprot(struct cli_state *cli)
1704 TALLOC_CTX *frame = talloc_stackframe();
1705 struct event_context *ev;
1706 struct tevent_req *req;
1707 NTSTATUS status = NT_STATUS_OK;
1709 if (cli_has_async_calls(cli)) {
1711 * Can't use sync call while an async call is in flight
1713 status = NT_STATUS_INVALID_PARAMETER;
1714 goto fail;
1717 ev = event_context_init(frame);
1718 if (ev == NULL) {
1719 status = NT_STATUS_NO_MEMORY;
1720 goto fail;
1723 req = cli_negprot_send(frame, ev, cli);
1724 if (req == NULL) {
1725 status = NT_STATUS_NO_MEMORY;
1726 goto fail;
1729 if (!tevent_req_poll(req, ev)) {
1730 status = map_nt_error_from_unix(errno);
1731 goto fail;
1734 status = cli_negprot_recv(req);
1735 fail:
1736 TALLOC_FREE(frame);
1737 if (!NT_STATUS_IS_OK(status)) {
1738 cli_set_error(cli, status);
1740 return status;
1743 /****************************************************************************
1744 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1745 ****************************************************************************/
1747 bool cli_session_request(struct cli_state *cli,
1748 struct nmb_name *calling, struct nmb_name *called)
1750 char *p;
1751 int len = 4;
1752 char *tmp;
1754 /* 445 doesn't have session request */
1755 if (cli->port == 445)
1756 return True;
1758 memcpy(&(cli->calling), calling, sizeof(*calling));
1759 memcpy(&(cli->called ), called , sizeof(*called ));
1761 /* put in the destination name */
1763 tmp = name_mangle(talloc_tos(), cli->called.name,
1764 cli->called.name_type);
1765 if (tmp == NULL) {
1766 return false;
1769 p = cli->outbuf+len;
1770 memcpy(p, tmp, name_len(tmp));
1771 len += name_len(tmp);
1772 TALLOC_FREE(tmp);
1774 /* and my name */
1776 tmp = name_mangle(talloc_tos(), cli->calling.name,
1777 cli->calling.name_type);
1778 if (tmp == NULL) {
1779 return false;
1782 p = cli->outbuf+len;
1783 memcpy(p, tmp, name_len(tmp));
1784 len += name_len(tmp);
1785 TALLOC_FREE(tmp);
1787 /* send a session request (RFC 1002) */
1788 /* setup the packet length
1789 * Remove four bytes from the length count, since the length
1790 * field in the NBT Session Service header counts the number
1791 * of bytes which follow. The cli_send_smb() function knows
1792 * about this and accounts for those four bytes.
1793 * CRH.
1795 len -= 4;
1796 _smb_setlen(cli->outbuf,len);
1797 SCVAL(cli->outbuf,0,0x81);
1799 cli_send_smb(cli);
1800 DEBUG(5,("Sent session request\n"));
1802 if (!cli_receive_smb(cli))
1803 return False;
1805 if (CVAL(cli->inbuf,0) == 0x84) {
1806 /* C. Hoch 9/14/95 Start */
1807 /* For information, here is the response structure.
1808 * We do the byte-twiddling to for portability.
1809 struct RetargetResponse{
1810 unsigned char type;
1811 unsigned char flags;
1812 int16 length;
1813 int32 ip_addr;
1814 int16 port;
1817 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1818 struct in_addr dest_ip;
1819 NTSTATUS status;
1821 /* SESSION RETARGET */
1822 putip((char *)&dest_ip,cli->inbuf+4);
1823 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
1825 status = open_socket_out(&cli->dest_ss, port,
1826 LONG_CONNECT_TIMEOUT, &cli->fd);
1827 if (!NT_STATUS_IS_OK(status)) {
1828 return False;
1831 DEBUG(3,("Retargeted\n"));
1833 set_socket_options(cli->fd, lp_socket_options());
1835 /* Try again */
1837 static int depth;
1838 bool ret;
1839 if (depth > 4) {
1840 DEBUG(0,("Retarget recursion - failing\n"));
1841 return False;
1843 depth++;
1844 ret = cli_session_request(cli, calling, called);
1845 depth--;
1846 return ret;
1848 } /* C. Hoch 9/14/95 End */
1850 if (CVAL(cli->inbuf,0) != 0x82) {
1851 /* This is the wrong place to put the error... JRA. */
1852 cli->rap_error = CVAL(cli->inbuf,4);
1853 return False;
1855 return(True);
1858 struct fd_struct {
1859 int fd;
1862 static void smb_sock_connected(struct tevent_req *req)
1864 struct fd_struct *pfd = tevent_req_callback_data(
1865 req, struct fd_struct);
1866 int fd;
1867 NTSTATUS status;
1869 status = open_socket_out_defer_recv(req, &fd);
1870 if (NT_STATUS_IS_OK(status)) {
1871 pfd->fd = fd;
1875 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
1876 uint16_t *port, int timeout, int *pfd)
1878 struct event_context *ev;
1879 struct tevent_req *r139, *r445;
1880 struct fd_struct *fd139, *fd445;
1881 NTSTATUS status = NT_STATUS_NO_MEMORY;
1883 if (*port != 0) {
1884 return open_socket_out(pss, *port, timeout, pfd);
1887 ev = event_context_init(talloc_tos());
1888 if (ev == NULL) {
1889 return NT_STATUS_NO_MEMORY;
1892 fd139 = talloc(ev, struct fd_struct);
1893 if (fd139 == NULL) {
1894 goto done;
1896 fd139->fd = -1;
1898 fd445 = talloc(ev, struct fd_struct);
1899 if (fd445 == NULL) {
1900 goto done;
1902 fd445->fd = -1;
1904 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
1905 pss, 445, timeout);
1906 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
1907 pss, 139, timeout);
1908 if ((r445 == NULL) || (r139 == NULL)) {
1909 goto done;
1911 tevent_req_set_callback(r445, smb_sock_connected, fd445);
1912 tevent_req_set_callback(r139, smb_sock_connected, fd139);
1914 while ((fd445->fd == -1) && (fd139->fd == -1)
1915 && (tevent_req_is_in_progress(r139)
1916 || tevent_req_is_in_progress(r445))) {
1917 event_loop_once(ev);
1920 if ((fd139->fd != -1) && (fd445->fd != -1)) {
1921 close(fd139->fd);
1922 fd139->fd = -1;
1925 if (fd445->fd != -1) {
1926 *port = 445;
1927 *pfd = fd445->fd;
1928 status = NT_STATUS_OK;
1929 goto done;
1931 if (fd139->fd != -1) {
1932 *port = 139;
1933 *pfd = fd139->fd;
1934 status = NT_STATUS_OK;
1935 goto done;
1938 status = open_socket_out_defer_recv(r445, &fd445->fd);
1939 done:
1940 TALLOC_FREE(ev);
1941 return status;
1944 /****************************************************************************
1945 Open the client sockets.
1946 ****************************************************************************/
1948 NTSTATUS cli_connect(struct cli_state *cli,
1949 const char *host,
1950 struct sockaddr_storage *dest_ss)
1953 int name_type = 0x20;
1954 TALLOC_CTX *frame = talloc_stackframe();
1955 unsigned int num_addrs = 0;
1956 unsigned int i = 0;
1957 struct sockaddr_storage *ss_arr = NULL;
1958 char *p = NULL;
1960 /* reasonable default hostname */
1961 if (!host) {
1962 host = STAR_SMBSERVER;
1965 fstrcpy(cli->desthost, host);
1967 /* allow hostnames of the form NAME#xx and do a netbios lookup */
1968 if ((p = strchr(cli->desthost, '#'))) {
1969 name_type = strtol(p+1, NULL, 16);
1970 *p = 0;
1973 if (!dest_ss || is_zero_addr((struct sockaddr *)dest_ss)) {
1974 NTSTATUS status =resolve_name_list(frame,
1975 cli->desthost,
1976 name_type,
1977 &ss_arr,
1978 &num_addrs);
1979 if (!NT_STATUS_IS_OK(status)) {
1980 TALLOC_FREE(frame);
1981 return NT_STATUS_BAD_NETWORK_NAME;
1983 } else {
1984 num_addrs = 1;
1985 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
1986 if (!ss_arr) {
1987 TALLOC_FREE(frame);
1988 return NT_STATUS_NO_MEMORY;
1990 *ss_arr = *dest_ss;
1993 for (i = 0; i < num_addrs; i++) {
1994 cli->dest_ss = ss_arr[i];
1995 if (getenv("LIBSMB_PROG")) {
1996 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
1997 } else {
1998 uint16_t port = cli->port;
1999 NTSTATUS status;
2000 status = open_smb_socket(&cli->dest_ss, &port,
2001 cli->timeout, &cli->fd);
2002 if (NT_STATUS_IS_OK(status)) {
2003 cli->port = port;
2006 if (cli->fd == -1) {
2007 char addr[INET6_ADDRSTRLEN];
2008 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
2009 DEBUG(2,("Error connecting to %s (%s)\n",
2010 dest_ss?addr:host,strerror(errno)));
2011 } else {
2012 /* Exit from loop on first connection. */
2013 break;
2017 if (cli->fd == -1) {
2018 TALLOC_FREE(frame);
2019 return map_nt_error_from_unix(errno);
2022 if (dest_ss) {
2023 *dest_ss = cli->dest_ss;
2026 set_socket_options(cli->fd, lp_socket_options());
2028 TALLOC_FREE(frame);
2029 return NT_STATUS_OK;
2033 establishes a connection to after the negprot.
2034 @param output_cli A fully initialised cli structure, non-null only on success
2035 @param dest_host The netbios name of the remote host
2036 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2037 @param port (optional) The destination port (0 for default)
2038 @param retry bool. Did this connection fail with a retryable error ?
2041 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2042 const char *my_name,
2043 const char *dest_host,
2044 struct sockaddr_storage *dest_ss, int port,
2045 int signing_state, int flags,
2046 bool *retry)
2048 NTSTATUS nt_status;
2049 struct nmb_name calling;
2050 struct nmb_name called;
2051 struct cli_state *cli;
2052 struct sockaddr_storage ss;
2054 if (retry)
2055 *retry = False;
2057 if (!my_name)
2058 my_name = global_myname();
2060 if (!(cli = cli_initialise_ex(signing_state))) {
2061 return NT_STATUS_NO_MEMORY;
2064 make_nmb_name(&calling, my_name, 0x0);
2065 make_nmb_name(&called , dest_host, 0x20);
2067 cli_set_port(cli, port);
2068 cli_set_timeout(cli, 10000); /* 10 seconds. */
2070 if (dest_ss) {
2071 ss = *dest_ss;
2072 } else {
2073 zero_sockaddr(&ss);
2076 again:
2078 DEBUG(3,("Connecting to host=%s\n", dest_host));
2080 nt_status = cli_connect(cli, dest_host, &ss);
2081 if (!NT_STATUS_IS_OK(nt_status)) {
2082 char addr[INET6_ADDRSTRLEN];
2083 print_sockaddr(addr, sizeof(addr), &ss);
2084 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
2085 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
2086 cli_shutdown(cli);
2087 return nt_status;
2090 if (retry)
2091 *retry = True;
2093 if (!cli_session_request(cli, &calling, &called)) {
2094 char *p;
2095 DEBUG(1,("session request to %s failed (%s)\n",
2096 called.name, cli_errstr(cli)));
2097 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
2098 *p = 0;
2099 goto again;
2101 if (strcmp(called.name, STAR_SMBSERVER)) {
2102 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
2103 goto again;
2105 return NT_STATUS_BAD_NETWORK_NAME;
2108 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
2109 cli->use_spnego = False;
2110 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
2111 cli->use_kerberos = True;
2113 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
2114 cli->use_kerberos) {
2115 cli->fallback_after_kerberos = true;
2118 nt_status = cli_negprot(cli);
2119 if (!NT_STATUS_IS_OK(nt_status)) {
2120 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2121 cli_shutdown(cli);
2122 return nt_status;
2125 *output_cli = cli;
2126 return NT_STATUS_OK;
2131 establishes a connection right up to doing tconX, password specified.
2132 @param output_cli A fully initialised cli structure, non-null only on success
2133 @param dest_host The netbios name of the remote host
2134 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2135 @param port (optional) The destination port (0 for default)
2136 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2137 @param service_type The 'type' of serivice.
2138 @param user Username, unix string
2139 @param domain User's domain
2140 @param password User's password, unencrypted unix string.
2141 @param retry bool. Did this connection fail with a retryable error ?
2144 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2145 const char *my_name,
2146 const char *dest_host,
2147 struct sockaddr_storage *dest_ss, int port,
2148 const char *service, const char *service_type,
2149 const char *user, const char *domain,
2150 const char *password, int flags,
2151 int signing_state,
2152 bool *retry)
2154 NTSTATUS nt_status;
2155 struct cli_state *cli = NULL;
2156 int pw_len = password ? strlen(password)+1 : 0;
2158 *output_cli = NULL;
2160 if (password == NULL) {
2161 password = "";
2164 nt_status = cli_start_connection(&cli, my_name, dest_host,
2165 dest_ss, port, signing_state,
2166 flags, retry);
2168 if (!NT_STATUS_IS_OK(nt_status)) {
2169 return nt_status;
2172 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
2173 cli->use_level_II_oplocks =
2174 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
2176 nt_status = cli_session_setup(cli, user, password, pw_len, password,
2177 pw_len, domain);
2178 if (!NT_STATUS_IS_OK(nt_status)) {
2180 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2181 DEBUG(1,("failed session setup with %s\n",
2182 nt_errstr(nt_status)));
2183 cli_shutdown(cli);
2184 return nt_status;
2187 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2188 if (!NT_STATUS_IS_OK(nt_status)) {
2189 DEBUG(1,("anonymous failed session setup with %s\n",
2190 nt_errstr(nt_status)));
2191 cli_shutdown(cli);
2192 return nt_status;
2196 if (service) {
2197 nt_status = cli_tcon_andx(cli, service, service_type, password,
2198 pw_len);
2199 if (!NT_STATUS_IS_OK(nt_status)) {
2200 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2201 cli_shutdown(cli);
2202 if (NT_STATUS_IS_OK(nt_status)) {
2203 nt_status = NT_STATUS_UNSUCCESSFUL;
2205 return nt_status;
2209 nt_status = cli_init_creds(cli, user, domain, password);
2210 if (!NT_STATUS_IS_OK(nt_status)) {
2211 cli_shutdown(cli);
2212 return nt_status;
2215 *output_cli = cli;
2216 return NT_STATUS_OK;
2219 /****************************************************************************
2220 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2221 ****************************************************************************/
2223 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
2224 struct sockaddr_storage *pdest_ss)
2226 struct nmb_name calling, called;
2228 make_nmb_name(&calling, srchost, 0x0);
2231 * If the called name is an IP address
2232 * then use *SMBSERVER immediately.
2235 if(is_ipaddress(desthost)) {
2236 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
2237 } else {
2238 make_nmb_name(&called, desthost, 0x20);
2241 if (!cli_session_request(*ppcli, &calling, &called)) {
2242 NTSTATUS status;
2243 struct nmb_name smbservername;
2245 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
2248 * If the name wasn't *SMBSERVER then
2249 * try with *SMBSERVER if the first name fails.
2252 if (nmb_name_equal(&called, &smbservername)) {
2255 * The name used was *SMBSERVER, don't bother with another name.
2258 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2259 with error %s.\n", desthost, cli_errstr(*ppcli) ));
2260 return False;
2263 /* Try again... */
2264 cli_shutdown(*ppcli);
2266 *ppcli = cli_initialise();
2267 if (!*ppcli) {
2268 /* Out of memory... */
2269 return False;
2272 status = cli_connect(*ppcli, desthost, pdest_ss);
2273 if (!NT_STATUS_IS_OK(status) ||
2274 !cli_session_request(*ppcli, &calling, &smbservername)) {
2275 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2276 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
2277 return False;
2281 return True;
2284 /****************************************************************************
2285 Send an old style tcon.
2286 ****************************************************************************/
2287 NTSTATUS cli_raw_tcon(struct cli_state *cli,
2288 const char *service, const char *pass, const char *dev,
2289 uint16 *max_xmit, uint16 *tid)
2291 char *p;
2293 if (!lp_client_plaintext_auth() && (*pass)) {
2294 DEBUG(1, ("Server requested plaintext password but 'client "
2295 "plaintext auth' is disabled\n"));
2296 return NT_STATUS_ACCESS_DENIED;
2299 memset(cli->outbuf,'\0',smb_size);
2300 memset(cli->inbuf,'\0',smb_size);
2302 cli_set_message(cli->outbuf, 0, 0, True);
2303 SCVAL(cli->outbuf,smb_com,SMBtcon);
2304 cli_setup_packet(cli);
2306 p = smb_buf(cli->outbuf);
2307 *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
2308 *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
2309 *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
2311 cli_setup_bcc(cli, p);
2313 cli_send_smb(cli);
2314 if (!cli_receive_smb(cli)) {
2315 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2318 if (cli_is_error(cli)) {
2319 return cli_nt_error(cli);
2322 *max_xmit = SVAL(cli->inbuf, smb_vwv0);
2323 *tid = SVAL(cli->inbuf, smb_vwv1);
2325 return NT_STATUS_OK;
2328 /* Return a cli_state pointing at the IPC$ share for the given server */
2330 struct cli_state *get_ipc_connect(char *server,
2331 struct sockaddr_storage *server_ss,
2332 const struct user_auth_info *user_info)
2334 struct cli_state *cli;
2335 NTSTATUS nt_status;
2336 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2338 if (user_info->use_kerberos) {
2339 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2342 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
2343 user_info->username ? user_info->username : "",
2344 lp_workgroup(),
2345 user_info->password ? user_info->password : "",
2346 flags,
2347 Undefined, NULL);
2349 if (NT_STATUS_IS_OK(nt_status)) {
2350 return cli;
2351 } else if (is_ipaddress(server)) {
2352 /* windows 9* needs a correct NMB name for connections */
2353 fstring remote_name;
2355 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2356 cli = get_ipc_connect(remote_name, server_ss, user_info);
2357 if (cli)
2358 return cli;
2361 return NULL;
2365 * Given the IP address of a master browser on the network, return its
2366 * workgroup and connect to it.
2368 * This function is provided to allow additional processing beyond what
2369 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2370 * browsers and obtain each master browsers' list of domains (in case the
2371 * first master browser is recently on the network and has not yet
2372 * synchronized with other master browsers and therefore does not yet have the
2373 * entire network browse list)
2376 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2377 struct ip_service *mb_ip,
2378 const struct user_auth_info *user_info,
2379 char **pp_workgroup_out)
2381 char addr[INET6_ADDRSTRLEN];
2382 fstring name;
2383 struct cli_state *cli;
2384 struct sockaddr_storage server_ss;
2386 *pp_workgroup_out = NULL;
2388 print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2389 DEBUG(99, ("Looking up name of master browser %s\n",
2390 addr));
2393 * Do a name status query to find out the name of the master browser.
2394 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2395 * master browser will not respond to a wildcard query (or, at least,
2396 * an NT4 server acting as the domain master browser will not).
2398 * We might be able to use ONLY the query on MSBROWSE, but that's not
2399 * yet been tested with all Windows versions, so until it is, leave
2400 * the original wildcard query as the first choice and fall back to
2401 * MSBROWSE if the wildcard query fails.
2403 if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2404 !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2406 DEBUG(99, ("Could not retrieve name status for %s\n",
2407 addr));
2408 return NULL;
2411 if (!find_master_ip(name, &server_ss)) {
2412 DEBUG(99, ("Could not find master ip for %s\n", name));
2413 return NULL;
2416 *pp_workgroup_out = talloc_strdup(ctx, name);
2418 DEBUG(4, ("found master browser %s, %s\n", name, addr));
2420 print_sockaddr(addr, sizeof(addr), &server_ss);
2421 cli = get_ipc_connect(addr, &server_ss, user_info);
2423 return cli;
2427 * Return the IP address and workgroup of a master browser on the network, and
2428 * connect to it.
2431 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2432 const struct user_auth_info *user_info,
2433 char **pp_workgroup_out)
2435 struct ip_service *ip_list;
2436 struct cli_state *cli;
2437 int i, count;
2439 *pp_workgroup_out = NULL;
2441 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2443 /* Go looking for workgroups by broadcasting on the local network */
2445 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2446 &count))) {
2447 DEBUG(99, ("No master browsers responded\n"));
2448 return False;
2451 for (i = 0; i < count; i++) {
2452 char addr[INET6_ADDRSTRLEN];
2453 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2454 DEBUG(99, ("Found master browser %s\n", addr));
2456 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2457 user_info, pp_workgroup_out);
2458 if (cli)
2459 return(cli);
2462 return NULL;