Fix connect to port 139 only -- thanks gd for bugging me :-)
[Samba/gebeck_regimport.git] / source3 / libsmb / cliconnect.c
blob525c361bebfa3334882bbbfada05f637a7c5361b
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 async_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
169 struct event_context *ev,
170 struct cli_state *cli)
172 struct async_req *result;
173 uint16_t vwv[13];
174 uint8_t *bytes;
176 SCVAL(vwv+0, 0, 0xFF);
177 SCVAL(vwv+0, 1, 0);
178 SSVAL(vwv+1, 0, 0);
179 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
180 SSVAL(vwv+3, 0, 2);
181 SSVAL(vwv+4, 0, cli->pid);
182 SIVAL(vwv+5, 0, cli->sesskey);
183 SSVAL(vwv+7, 0, 0);
184 SSVAL(vwv+8, 0, 0);
185 SSVAL(vwv+9, 0, 0);
186 SSVAL(vwv+10, 0, 0);
187 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
189 bytes = talloc_array(talloc_tos(), uint8_t, 0);
191 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
192 NULL);
193 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
194 NULL);
195 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
196 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
198 if (bytes == NULL) {
199 return NULL;
202 result = cli_request_send(mem_ctx, ev, cli, SMBsesssetupX, 0,
203 13, vwv, 0, talloc_get_size(bytes), bytes);
204 TALLOC_FREE(bytes);
205 return result;
208 NTSTATUS cli_session_setup_guest_recv(struct async_req *req)
210 struct cli_request *cli_req = talloc_get_type_abort(
211 req->private_data, struct cli_request);
212 struct cli_state *cli = cli_req->cli;
213 uint8_t wct;
214 uint16_t *vwv;
215 uint16_t num_bytes;
216 uint8_t *bytes;
217 uint8_t *p;
218 NTSTATUS status;
220 if (async_req_is_nterror(req, &status)) {
221 return status;
224 status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
225 if (!NT_STATUS_IS_OK(status)) {
226 return status;
229 p = bytes;
231 cli->vuid = SVAL(cli_req->inbuf, smb_uid);
233 p += clistr_pull(cli_req->inbuf, cli->server_os, (char *)p,
234 sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE);
235 p += clistr_pull(cli_req->inbuf, cli->server_type, (char *)p,
236 sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE);
237 p += clistr_pull(cli_req->inbuf, cli->server_domain, (char *)p,
238 sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE);
240 if (strstr(cli->server_type, "Samba")) {
241 cli->is_samba = True;
244 status = cli_set_username(cli, "");
245 if (!NT_STATUS_IS_OK(status)) {
246 return status;
249 return NT_STATUS_OK;
252 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
254 TALLOC_CTX *frame = talloc_stackframe();
255 struct event_context *ev;
256 struct async_req *req;
257 NTSTATUS status;
259 if (cli->fd_event != NULL) {
261 * Can't use sync call while an async call is in flight
263 status = NT_STATUS_INVALID_PARAMETER;
264 goto fail;
267 ev = event_context_init(frame);
268 if (ev == NULL) {
269 status = NT_STATUS_NO_MEMORY;
270 goto fail;
273 req = cli_session_setup_guest_send(frame, ev, cli);
274 if (req == NULL) {
275 status = NT_STATUS_NO_MEMORY;
276 goto fail;
279 while (req->state < ASYNC_REQ_DONE) {
280 event_loop_once(ev);
283 status = cli_session_setup_guest_recv(req);
284 fail:
285 TALLOC_FREE(frame);
286 return status;
289 /****************************************************************************
290 Do a NT1 plaintext session setup.
291 ****************************************************************************/
293 static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
294 const char *user, const char *pass,
295 const char *workgroup)
297 uint32 capabilities = cli_session_setup_capabilities(cli);
298 char *p;
299 NTSTATUS status;
300 fstring lanman;
302 fstr_sprintf( lanman, "Samba %s", samba_version_string());
304 memset(cli->outbuf, '\0', smb_size);
305 cli_set_message(cli->outbuf,13,0,True);
306 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
307 cli_setup_packet(cli);
309 SCVAL(cli->outbuf,smb_vwv0,0xFF);
310 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
311 SSVAL(cli->outbuf,smb_vwv3,2);
312 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
313 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
314 SSVAL(cli->outbuf,smb_vwv8,0);
315 SIVAL(cli->outbuf,smb_vwv11,capabilities);
316 p = smb_buf(cli->outbuf);
318 /* check wether to send the ASCII or UNICODE version of the password */
320 if ( (capabilities & CAP_UNICODE) == 0 ) {
321 p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
322 SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
324 else {
325 /* For ucs2 passwords clistr_push calls ucs2_align, which causes
326 * the space taken by the unicode password to be one byte too
327 * long (as we're on an odd byte boundary here). Reduce the
328 * count by 1 to cope with this. Fixes smbclient against NetApp
329 * servers which can't cope. Fix from
330 * bryan.kolodziej@allenlund.com in bug #3840.
332 p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
333 SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))-1);
336 p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
337 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
338 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
339 p += clistr_push(cli, p, lanman, -1, STR_TERMINATE);
340 cli_setup_bcc(cli, p);
342 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
343 return cli_nt_error(cli);
346 show_msg(cli->inbuf);
348 if (cli_is_error(cli)) {
349 return cli_nt_error(cli);
352 cli->vuid = SVAL(cli->inbuf,smb_uid);
353 p = smb_buf(cli->inbuf);
354 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
355 -1, STR_TERMINATE);
356 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
357 -1, STR_TERMINATE);
358 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
359 -1, STR_TERMINATE);
360 status = cli_set_username(cli, user);
361 if (!NT_STATUS_IS_OK(status)) {
362 return status;
364 if (strstr(cli->server_type, "Samba")) {
365 cli->is_samba = True;
368 return NT_STATUS_OK;
371 /****************************************************************************
372 do a NT1 NTLM/LM encrypted session setup - for when extended security
373 is not negotiated.
374 @param cli client state to create do session setup on
375 @param user username
376 @param pass *either* cleartext password (passlen !=24) or LM response.
377 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
378 @param workgroup The user's domain.
379 ****************************************************************************/
381 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
382 const char *pass, size_t passlen,
383 const char *ntpass, size_t ntpasslen,
384 const char *workgroup)
386 uint32 capabilities = cli_session_setup_capabilities(cli);
387 DATA_BLOB lm_response = data_blob_null;
388 DATA_BLOB nt_response = data_blob_null;
389 DATA_BLOB session_key = data_blob_null;
390 NTSTATUS result;
391 char *p;
392 bool ok;
394 if (passlen == 0) {
395 /* do nothing - guest login */
396 } else if (passlen != 24) {
397 if (lp_client_ntlmv2_auth()) {
398 DATA_BLOB server_chal;
399 DATA_BLOB names_blob;
400 server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8));
402 /* note that the 'workgroup' here is a best guess - we don't know
403 the server's domain at this point. The 'server name' is also
404 dodgy...
406 names_blob = NTLMv2_generate_names_blob(cli->called.name, workgroup);
408 if (!SMBNTLMv2encrypt(user, workgroup, pass, &server_chal,
409 &names_blob,
410 &lm_response, &nt_response, &session_key)) {
411 data_blob_free(&names_blob);
412 data_blob_free(&server_chal);
413 return NT_STATUS_ACCESS_DENIED;
415 data_blob_free(&names_blob);
416 data_blob_free(&server_chal);
418 } else {
419 uchar nt_hash[16];
420 E_md4hash(pass, nt_hash);
422 #ifdef LANMAN_ONLY
423 nt_response = data_blob_null;
424 #else
425 nt_response = data_blob(NULL, 24);
426 SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
427 #endif
428 /* non encrypted password supplied. Ignore ntpass. */
429 if (lp_client_lanman_auth()) {
430 lm_response = data_blob(NULL, 24);
431 if (!SMBencrypt(pass,cli->secblob.data, lm_response.data)) {
432 /* Oops, the LM response is invalid, just put
433 the NT response there instead */
434 data_blob_free(&lm_response);
435 lm_response = data_blob(nt_response.data, nt_response.length);
437 } else {
438 /* LM disabled, place NT# in LM field instead */
439 lm_response = data_blob(nt_response.data, nt_response.length);
442 session_key = data_blob(NULL, 16);
443 #ifdef LANMAN_ONLY
444 E_deshash(pass, session_key.data);
445 memset(&session_key.data[8], '\0', 8);
446 #else
447 SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
448 #endif
450 cli_temp_set_signing(cli);
451 } else {
452 /* pre-encrypted password supplied. Only used for
453 security=server, can't do
454 signing because we don't have original key */
456 lm_response = data_blob(pass, passlen);
457 nt_response = data_blob(ntpass, ntpasslen);
460 /* send a session setup command */
461 memset(cli->outbuf,'\0',smb_size);
463 cli_set_message(cli->outbuf,13,0,True);
464 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
465 cli_setup_packet(cli);
467 SCVAL(cli->outbuf,smb_vwv0,0xFF);
468 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
469 SSVAL(cli->outbuf,smb_vwv3,2);
470 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
471 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
472 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
473 SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
474 SIVAL(cli->outbuf,smb_vwv11,capabilities);
475 p = smb_buf(cli->outbuf);
476 if (lm_response.length) {
477 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
479 if (nt_response.length) {
480 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
482 p += clistr_push(cli, p, user, -1, STR_TERMINATE);
484 /* Upper case here might help some NTLMv2 implementations */
485 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
486 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
487 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
488 cli_setup_bcc(cli, p);
490 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
491 result = cli_nt_error(cli);
492 goto end;
495 /* show_msg(cli->inbuf); */
497 if (cli_is_error(cli)) {
498 result = cli_nt_error(cli);
499 goto end;
502 #ifdef LANMAN_ONLY
503 ok = cli_simple_set_signing(cli, session_key, lm_response);
504 #else
505 ok = cli_simple_set_signing(cli, session_key, nt_response);
506 #endif
507 if (ok) {
508 /* 'resign' the last message, so we get the right sequence numbers
509 for checking the first reply from the server */
510 cli_calculate_sign_mac(cli, cli->outbuf);
512 if (!cli_check_sign_mac(cli, cli->inbuf)) {
513 result = NT_STATUS_ACCESS_DENIED;
514 goto end;
518 /* use the returned vuid from now on */
519 cli->vuid = SVAL(cli->inbuf,smb_uid);
521 p = smb_buf(cli->inbuf);
522 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
523 -1, STR_TERMINATE);
524 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
525 -1, STR_TERMINATE);
526 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
527 -1, STR_TERMINATE);
529 if (strstr(cli->server_type, "Samba")) {
530 cli->is_samba = True;
533 result = cli_set_username(cli, user);
534 if (!NT_STATUS_IS_OK(result)) {
535 goto end;
538 if (session_key.data) {
539 /* Have plaintext orginal */
540 cli_set_session_key(cli, session_key);
543 result = NT_STATUS_OK;
544 end:
545 data_blob_free(&lm_response);
546 data_blob_free(&nt_response);
547 data_blob_free(&session_key);
548 return result;
551 /****************************************************************************
552 Send a extended security session setup blob
553 ****************************************************************************/
555 static bool cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob)
557 uint32 capabilities = cli_session_setup_capabilities(cli);
558 char *p;
560 capabilities |= CAP_EXTENDED_SECURITY;
562 /* send a session setup command */
563 memset(cli->outbuf,'\0',smb_size);
565 cli_set_message(cli->outbuf,12,0,True);
566 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
568 cli_setup_packet(cli);
570 SCVAL(cli->outbuf,smb_vwv0,0xFF);
571 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
572 SSVAL(cli->outbuf,smb_vwv3,2);
573 SSVAL(cli->outbuf,smb_vwv4,1);
574 SIVAL(cli->outbuf,smb_vwv5,0);
575 SSVAL(cli->outbuf,smb_vwv7,blob.length);
576 SIVAL(cli->outbuf,smb_vwv10,capabilities);
577 p = smb_buf(cli->outbuf);
578 memcpy(p, blob.data, blob.length);
579 p += blob.length;
580 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
581 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
582 cli_setup_bcc(cli, p);
583 return cli_send_smb(cli);
586 /****************************************************************************
587 Send a extended security session setup blob, returning a reply blob.
588 ****************************************************************************/
590 static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli)
592 DATA_BLOB blob2 = data_blob_null;
593 char *p;
594 size_t len;
596 if (!cli_receive_smb(cli))
597 return blob2;
599 show_msg(cli->inbuf);
601 if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli),
602 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
603 return blob2;
606 /* use the returned vuid from now on */
607 cli->vuid = SVAL(cli->inbuf,smb_uid);
609 p = smb_buf(cli->inbuf);
611 blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3));
613 p += blob2.length;
614 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
615 -1, STR_TERMINATE);
617 /* w2k with kerberos doesn't properly null terminate this field */
618 len = smb_bufrem(cli->inbuf, p);
619 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
620 len, 0);
622 return blob2;
625 #ifdef HAVE_KRB5
626 /****************************************************************************
627 Send a extended security session setup blob, returning a reply blob.
628 ****************************************************************************/
630 /* The following is calculated from :
631 * (smb_size-4) = 35
632 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
633 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
634 * end of packet.
637 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
639 static bool cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
641 int32 remaining = blob.length;
642 int32 cur = 0;
643 DATA_BLOB send_blob = data_blob_null;
644 int32 max_blob_size = 0;
645 DATA_BLOB receive_blob = data_blob_null;
647 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
648 DEBUG(0,("cli_session_setup_blob: cli->max_xmit too small "
649 "(was %u, need minimum %u)\n",
650 (unsigned int)cli->max_xmit,
651 BASE_SESSSETUP_BLOB_PACKET_SIZE));
652 cli_set_nt_error(cli, NT_STATUS_INVALID_PARAMETER);
653 return False;
656 max_blob_size = cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE;
658 while ( remaining > 0) {
659 if (remaining >= max_blob_size) {
660 send_blob.length = max_blob_size;
661 remaining -= max_blob_size;
662 } else {
663 send_blob.length = remaining;
664 remaining = 0;
667 send_blob.data = &blob.data[cur];
668 cur += send_blob.length;
670 DEBUG(10, ("cli_session_setup_blob: Remaining (%u) sending (%u) current (%u)\n",
671 (unsigned int)remaining,
672 (unsigned int)send_blob.length,
673 (unsigned int)cur ));
675 if (!cli_session_setup_blob_send(cli, send_blob)) {
676 DEBUG(0, ("cli_session_setup_blob: send failed\n"));
677 return False;
680 receive_blob = cli_session_setup_blob_receive(cli);
681 data_blob_free(&receive_blob);
683 if (cli_is_error(cli) &&
684 !NT_STATUS_EQUAL( cli_get_nt_error(cli),
685 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
686 DEBUG(0, ("cli_session_setup_blob: receive failed "
687 "(%s)\n", nt_errstr(cli_get_nt_error(cli))));
688 cli->vuid = 0;
689 return False;
693 return True;
696 /****************************************************************************
697 Use in-memory credentials cache
698 ****************************************************************************/
700 static void use_in_memory_ccache(void) {
701 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
704 /****************************************************************************
705 Do a spnego/kerberos encrypted session setup.
706 ****************************************************************************/
708 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
710 DATA_BLOB negTokenTarg;
711 DATA_BLOB session_key_krb5;
712 NTSTATUS nt_status;
713 int rc;
715 cli_temp_set_signing(cli);
717 DEBUG(2,("Doing kerberos session setup\n"));
719 /* generate the encapsulated kerberos5 ticket */
720 rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5, 0, NULL);
722 if (rc) {
723 DEBUG(1, ("cli_session_setup_kerberos: spnego_gen_negTokenTarg failed: %s\n",
724 error_message(rc)));
725 return ADS_ERROR_KRB5(rc);
728 #if 0
729 file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
730 #endif
732 if (!cli_session_setup_blob(cli, negTokenTarg)) {
733 nt_status = cli_nt_error(cli);
734 goto nt_error;
737 if (cli_is_error(cli)) {
738 nt_status = cli_nt_error(cli);
739 if (NT_STATUS_IS_OK(nt_status)) {
740 nt_status = NT_STATUS_UNSUCCESSFUL;
742 goto nt_error;
745 cli_set_session_key(cli, session_key_krb5);
747 if (cli_simple_set_signing(
748 cli, session_key_krb5, data_blob_null)) {
750 /* 'resign' the last message, so we get the right sequence numbers
751 for checking the first reply from the server */
752 cli_calculate_sign_mac(cli, cli->outbuf);
754 if (!cli_check_sign_mac(cli, cli->inbuf)) {
755 nt_status = NT_STATUS_ACCESS_DENIED;
756 goto nt_error;
760 data_blob_free(&negTokenTarg);
761 data_blob_free(&session_key_krb5);
763 return ADS_ERROR_NT(NT_STATUS_OK);
765 nt_error:
766 data_blob_free(&negTokenTarg);
767 data_blob_free(&session_key_krb5);
768 cli->vuid = 0;
769 return ADS_ERROR_NT(nt_status);
771 #endif /* HAVE_KRB5 */
774 /****************************************************************************
775 Do a spnego/NTLMSSP encrypted session setup.
776 ****************************************************************************/
778 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
779 const char *pass, const char *domain)
781 struct ntlmssp_state *ntlmssp_state;
782 NTSTATUS nt_status;
783 int turn = 1;
784 DATA_BLOB msg1;
785 DATA_BLOB blob = data_blob_null;
786 DATA_BLOB blob_in = data_blob_null;
787 DATA_BLOB blob_out = data_blob_null;
789 cli_temp_set_signing(cli);
791 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
792 return nt_status;
794 ntlmssp_want_feature(ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
796 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
797 return nt_status;
799 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
800 return nt_status;
802 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
803 return nt_status;
806 do {
807 nt_status = ntlmssp_update(ntlmssp_state,
808 blob_in, &blob_out);
809 data_blob_free(&blob_in);
810 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(nt_status)) {
811 if (turn == 1) {
812 /* and wrap it in a SPNEGO wrapper */
813 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
814 } else {
815 /* wrap it in SPNEGO */
816 msg1 = spnego_gen_auth(blob_out);
819 /* now send that blob on its way */
820 if (!cli_session_setup_blob_send(cli, msg1)) {
821 DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
822 nt_status = NT_STATUS_UNSUCCESSFUL;
823 } else {
824 blob = cli_session_setup_blob_receive(cli);
826 nt_status = cli_nt_error(cli);
827 if (cli_is_error(cli) && NT_STATUS_IS_OK(nt_status)) {
828 if (cli->smb_rw_error == SMB_READ_BAD_SIG) {
829 nt_status = NT_STATUS_ACCESS_DENIED;
830 } else {
831 nt_status = NT_STATUS_UNSUCCESSFUL;
835 data_blob_free(&msg1);
838 if (!blob.length) {
839 if (NT_STATUS_IS_OK(nt_status)) {
840 nt_status = NT_STATUS_UNSUCCESSFUL;
842 } else if ((turn == 1) &&
843 NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
844 DATA_BLOB tmp_blob = data_blob_null;
845 /* the server might give us back two challenges */
846 if (!spnego_parse_challenge(blob, &blob_in,
847 &tmp_blob)) {
848 DEBUG(3,("Failed to parse challenges\n"));
849 nt_status = NT_STATUS_INVALID_PARAMETER;
851 data_blob_free(&tmp_blob);
852 } else {
853 if (!spnego_parse_auth_response(blob, nt_status, OID_NTLMSSP,
854 &blob_in)) {
855 DEBUG(3,("Failed to parse auth response\n"));
856 if (NT_STATUS_IS_OK(nt_status)
857 || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED))
858 nt_status = NT_STATUS_INVALID_PARAMETER;
861 data_blob_free(&blob);
862 data_blob_free(&blob_out);
863 turn++;
864 } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
866 data_blob_free(&blob_in);
868 if (NT_STATUS_IS_OK(nt_status)) {
870 fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
871 cli_set_session_key(cli, ntlmssp_state->session_key);
873 if (cli_simple_set_signing(
874 cli, ntlmssp_state->session_key, data_blob_null)) {
876 /* 'resign' the last message, so we get the right sequence numbers
877 for checking the first reply from the server */
878 cli_calculate_sign_mac(cli, cli->outbuf);
880 if (!cli_check_sign_mac(cli, cli->inbuf)) {
881 nt_status = NT_STATUS_ACCESS_DENIED;
886 /* we have a reference conter on ntlmssp_state, if we are signing
887 then the state will be kept by the signing engine */
889 ntlmssp_end(&ntlmssp_state);
891 if (!NT_STATUS_IS_OK(nt_status)) {
892 cli->vuid = 0;
894 return nt_status;
897 /****************************************************************************
898 Do a spnego encrypted session setup.
900 user_domain: The shortname of the domain the user/machine is a member of.
901 dest_realm: The realm we're connecting to, if NULL we use our default realm.
902 ****************************************************************************/
904 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
905 const char *pass, const char *user_domain,
906 const char * dest_realm)
908 char *principal = NULL;
909 char *OIDs[ASN1_MAX_OIDS];
910 int i;
911 DATA_BLOB blob;
912 const char *p = NULL;
913 char *account = NULL;
914 NTSTATUS status;
916 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
918 /* the server might not even do spnego */
919 if (cli->secblob.length <= 16) {
920 DEBUG(3,("server didn't supply a full spnego negprot\n"));
921 goto ntlmssp;
924 #if 0
925 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
926 #endif
928 /* there is 16 bytes of GUID before the real spnego packet starts */
929 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
931 /* The server sent us the first part of the SPNEGO exchange in the
932 * negprot reply. It is WRONG to depend on the principal sent in the
933 * negprot reply, but right now we do it. If we don't receive one,
934 * we try to best guess, then fall back to NTLM. */
935 if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
936 data_blob_free(&blob);
937 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
939 data_blob_free(&blob);
941 /* make sure the server understands kerberos */
942 for (i=0;OIDs[i];i++) {
943 DEBUG(3,("got OID=%s\n", OIDs[i]));
944 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
945 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
946 cli->got_kerberos_mechanism = True;
948 talloc_free(OIDs[i]);
951 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
953 status = cli_set_username(cli, user);
954 if (!NT_STATUS_IS_OK(status)) {
955 return ADS_ERROR_NT(status);
958 #ifdef HAVE_KRB5
959 /* If password is set we reauthenticate to kerberos server
960 * and do not store results */
962 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
963 ADS_STATUS rc;
965 if (pass && *pass) {
966 int ret;
968 use_in_memory_ccache();
969 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
971 if (ret){
972 TALLOC_FREE(principal);
973 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
974 if (cli->fallback_after_kerberos)
975 goto ntlmssp;
976 return ADS_ERROR_KRB5(ret);
980 /* If we get a bad principal, try to guess it if
981 we have a valid host NetBIOS name.
983 if (strequal(principal, ADS_IGNORE_PRINCIPAL)) {
984 TALLOC_FREE(principal);
987 if (principal == NULL &&
988 !is_ipaddress(cli->desthost) &&
989 !strequal(STAR_SMBSERVER,
990 cli->desthost)) {
991 char *realm = NULL;
992 char *machine = NULL;
993 char *host = NULL;
994 DEBUG(3,("cli_session_setup_spnego: got a "
995 "bad server principal, trying to guess ...\n"));
997 host = strchr_m(cli->desthost, '.');
998 if (host) {
999 machine = SMB_STRNDUP(cli->desthost,
1000 host - cli->desthost);
1001 } else {
1002 machine = SMB_STRDUP(cli->desthost);
1004 if (machine == NULL) {
1005 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1008 if (dest_realm) {
1009 realm = SMB_STRDUP(dest_realm);
1010 strupper_m(realm);
1011 } else {
1012 realm = kerberos_get_default_realm_from_ccache();
1014 if (realm && *realm) {
1015 principal = talloc_asprintf(NULL, "%s$@%s",
1016 machine, realm);
1017 if (!principal) {
1018 SAFE_FREE(machine);
1019 SAFE_FREE(realm);
1020 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1022 DEBUG(3,("cli_session_setup_spnego: guessed "
1023 "server principal=%s\n",
1024 principal ? principal : "<null>"));
1026 SAFE_FREE(machine);
1027 SAFE_FREE(realm);
1030 if (principal) {
1031 rc = cli_session_setup_kerberos(cli, principal,
1032 dest_realm);
1033 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1034 TALLOC_FREE(principal);
1035 return rc;
1039 #endif
1041 TALLOC_FREE(principal);
1043 ntlmssp:
1045 account = talloc_strdup(talloc_tos(), user);
1046 if (!account) {
1047 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1050 /* when falling back to ntlmssp while authenticating with a machine
1051 * account strip off the realm - gd */
1053 if ((p = strchr_m(user, '@')) != NULL) {
1054 account[PTR_DIFF(p,user)] = '\0';
1057 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1060 /****************************************************************************
1061 Send a session setup. The username and workgroup is in UNIX character
1062 format and must be converted to DOS codepage format before sending. If the
1063 password is in plaintext, the same should be done.
1064 ****************************************************************************/
1066 NTSTATUS cli_session_setup(struct cli_state *cli,
1067 const char *user,
1068 const char *pass, int passlen,
1069 const char *ntpass, int ntpasslen,
1070 const char *workgroup)
1072 char *p;
1073 fstring user2;
1075 if (user) {
1076 fstrcpy(user2, user);
1077 } else {
1078 user2[0] ='\0';
1081 if (!workgroup) {
1082 workgroup = "";
1085 /* allow for workgroups as part of the username */
1086 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1087 (p=strchr_m(user2,*lp_winbind_separator()))) {
1088 *p = 0;
1089 user = p+1;
1090 workgroup = user2;
1093 if (cli->protocol < PROTOCOL_LANMAN1) {
1094 return NT_STATUS_OK;
1097 /* now work out what sort of session setup we are going to
1098 do. I have split this into separate functions to make the
1099 flow a bit easier to understand (tridge) */
1101 /* if its an older server then we have to use the older request format */
1103 if (cli->protocol < PROTOCOL_NT1) {
1104 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1105 DEBUG(1, ("Server requested LM password but 'client lanman auth'"
1106 " is disabled\n"));
1107 return NT_STATUS_ACCESS_DENIED;
1110 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1111 !lp_client_plaintext_auth() && (*pass)) {
1112 DEBUG(1, ("Server requested plaintext password but "
1113 "'client plaintext auth' is disabled\n"));
1114 return NT_STATUS_ACCESS_DENIED;
1117 return cli_session_setup_lanman2(cli, user, pass, passlen,
1118 workgroup);
1121 /* if no user is supplied then we have to do an anonymous connection.
1122 passwords are ignored */
1124 if (!user || !*user)
1125 return cli_session_setup_guest(cli);
1127 /* if the server is share level then send a plaintext null
1128 password at this point. The password is sent in the tree
1129 connect */
1131 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
1132 return cli_session_setup_plaintext(cli, user, "", workgroup);
1134 /* if the server doesn't support encryption then we have to use
1135 plaintext. The second password is ignored */
1137 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1138 if (!lp_client_plaintext_auth() && (*pass)) {
1139 DEBUG(1, ("Server requested plaintext password but "
1140 "'client plaintext auth' is disabled\n"));
1141 return NT_STATUS_ACCESS_DENIED;
1143 return cli_session_setup_plaintext(cli, user, pass, workgroup);
1146 /* if the server supports extended security then use SPNEGO */
1148 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
1149 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
1150 workgroup, NULL);
1151 if (!ADS_ERR_OK(status)) {
1152 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1153 return ads_ntstatus(status);
1155 } else {
1156 NTSTATUS status;
1158 /* otherwise do a NT1 style session setup */
1159 status = cli_session_setup_nt1(cli, user, pass, passlen,
1160 ntpass, ntpasslen, workgroup);
1161 if (!NT_STATUS_IS_OK(status)) {
1162 DEBUG(3,("cli_session_setup: NT1 session setup "
1163 "failed: %s\n", nt_errstr(status)));
1164 return status;
1168 if (strstr(cli->server_type, "Samba")) {
1169 cli->is_samba = True;
1172 return NT_STATUS_OK;
1175 /****************************************************************************
1176 Send a uloggoff.
1177 *****************************************************************************/
1179 bool cli_ulogoff(struct cli_state *cli)
1181 memset(cli->outbuf,'\0',smb_size);
1182 cli_set_message(cli->outbuf,2,0,True);
1183 SCVAL(cli->outbuf,smb_com,SMBulogoffX);
1184 cli_setup_packet(cli);
1185 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1186 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1188 cli_send_smb(cli);
1189 if (!cli_receive_smb(cli))
1190 return False;
1192 if (cli_is_error(cli)) {
1193 return False;
1196 cli->cnum = -1;
1197 return True;
1200 /****************************************************************************
1201 Send a tconX.
1202 ****************************************************************************/
1204 struct async_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
1205 struct event_context *ev,
1206 struct cli_state *cli,
1207 const char *share, const char *dev,
1208 const char *pass, int passlen)
1210 fstring pword;
1211 char *tmp = NULL;
1212 struct async_req *result;
1213 uint16_t vwv[4];
1214 uint8_t *bytes;
1216 fstrcpy(cli->share, share);
1218 /* in user level security don't send a password now */
1219 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1220 passlen = 1;
1221 pass = "";
1222 } else if (pass == NULL) {
1223 DEBUG(1, ("Server not using user level security and no "
1224 "password supplied.\n"));
1225 goto access_denied;
1228 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1229 *pass && passlen != 24) {
1230 if (!lp_client_lanman_auth()) {
1231 DEBUG(1, ("Server requested LANMAN password "
1232 "(share-level security) but "
1233 "'client lanman auth' is disabled\n"));
1234 goto access_denied;
1238 * Non-encrypted passwords - convert to DOS codepage before
1239 * encryption.
1241 passlen = 24;
1242 SMBencrypt(pass, cli->secblob.data, (uchar *)pword);
1243 } else {
1244 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1245 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1246 == 0) {
1247 if (!lp_client_plaintext_auth() && (*pass)) {
1248 DEBUG(1, ("Server requested plaintext "
1249 "password but 'client plaintext "
1250 "auth' is disabled\n"));
1251 goto access_denied;
1255 * Non-encrypted passwords - convert to DOS codepage
1256 * before using.
1258 passlen = clistr_push(cli, pword, pass, sizeof(pword),
1259 STR_TERMINATE);
1260 if (passlen == -1) {
1261 DEBUG(1, ("clistr_push(pword) failed\n"));
1262 goto access_denied;
1264 } else {
1265 if (passlen) {
1266 memcpy(pword, pass, passlen);
1271 SCVAL(vwv+0, 0, 0xFF);
1272 SCVAL(vwv+0, 1, 0);
1273 SSVAL(vwv+1, 0, 0);
1274 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
1275 SSVAL(vwv+3, 0, passlen);
1277 if (passlen) {
1278 bytes = (uint8_t *)talloc_memdup(talloc_tos(), pword, passlen);
1279 } else {
1280 bytes = talloc_array(talloc_tos(), uint8_t, 0);
1284 * Add the sharename
1286 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1287 cli->desthost, share);
1288 if (tmp == NULL) {
1289 TALLOC_FREE(bytes);
1290 return NULL;
1292 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
1293 NULL);
1294 TALLOC_FREE(tmp);
1297 * Add the devicetype
1299 tmp = talloc_strdup_upper(talloc_tos(), dev);
1300 if (tmp == NULL) {
1301 TALLOC_FREE(bytes);
1302 return NULL;
1304 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
1305 TALLOC_FREE(tmp);
1307 if (bytes == NULL) {
1308 return NULL;
1311 result = cli_request_send(mem_ctx, ev, cli, SMBtconX, 0,
1312 4, vwv, 0, talloc_get_size(bytes), bytes);
1313 TALLOC_FREE(bytes);
1314 return result;
1316 access_denied:
1318 struct cli_request *state;
1319 if (!async_req_setup(mem_ctx, &result, &state,
1320 struct cli_request)) {
1321 goto fail;
1323 if (async_post_ntstatus(result, ev, NT_STATUS_ACCESS_DENIED)) {
1324 return result;
1327 fail:
1328 TALLOC_FREE(result);
1329 return NULL;
1332 NTSTATUS cli_tcon_andx_recv(struct async_req *req)
1334 struct cli_request *cli_req = talloc_get_type_abort(
1335 req->private_data, struct cli_request);
1336 struct cli_state *cli = cli_req->cli;
1337 uint8_t wct;
1338 uint16_t *vwv;
1339 uint16_t num_bytes;
1340 uint8_t *bytes;
1341 NTSTATUS status;
1343 if (async_req_is_nterror(req, &status)) {
1344 return status;
1347 status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
1348 if (!NT_STATUS_IS_OK(status)) {
1349 return status;
1352 clistr_pull(cli_req->inbuf, cli->dev, bytes, sizeof(fstring),
1353 num_bytes, STR_TERMINATE|STR_ASCII);
1355 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
1356 /* almost certainly win95 - enable bug fixes */
1357 cli->win95 = True;
1361 * Make sure that we have the optional support 16-bit field. WCT > 2.
1362 * Avoids issues when connecting to Win9x boxes sharing files
1365 cli->dfsroot = false;
1367 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
1368 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
1371 cli->cnum = SVAL(cli_req->inbuf,smb_tid);
1372 return NT_STATUS_OK;
1375 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
1376 const char *dev, const char *pass, int passlen)
1378 TALLOC_CTX *frame = talloc_stackframe();
1379 struct event_context *ev;
1380 struct async_req *req;
1381 NTSTATUS status;
1383 if (cli->fd_event != NULL) {
1385 * Can't use sync call while an async call is in flight
1387 status = NT_STATUS_INVALID_PARAMETER;
1388 goto fail;
1391 ev = event_context_init(frame);
1392 if (ev == NULL) {
1393 status = NT_STATUS_NO_MEMORY;
1394 goto fail;
1397 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
1398 if (req == NULL) {
1399 status = NT_STATUS_NO_MEMORY;
1400 goto fail;
1403 while (req->state < ASYNC_REQ_DONE) {
1404 event_loop_once(ev);
1407 status = cli_tcon_andx_recv(req);
1408 fail:
1409 TALLOC_FREE(frame);
1410 return status;
1413 /****************************************************************************
1414 Send a tree disconnect.
1415 ****************************************************************************/
1417 bool cli_tdis(struct cli_state *cli)
1419 memset(cli->outbuf,'\0',smb_size);
1420 cli_set_message(cli->outbuf,0,0,True);
1421 SCVAL(cli->outbuf,smb_com,SMBtdis);
1422 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1423 cli_setup_packet(cli);
1425 cli_send_smb(cli);
1426 if (!cli_receive_smb(cli))
1427 return False;
1429 if (cli_is_error(cli)) {
1430 return False;
1433 cli->cnum = -1;
1434 return True;
1437 /****************************************************************************
1438 Send a negprot command.
1439 ****************************************************************************/
1441 void cli_negprot_sendsync(struct cli_state *cli)
1443 char *p;
1444 int numprots;
1446 if (cli->protocol < PROTOCOL_NT1)
1447 cli->use_spnego = False;
1449 memset(cli->outbuf,'\0',smb_size);
1451 /* setup the protocol strings */
1452 cli_set_message(cli->outbuf,0,0,True);
1454 p = smb_buf(cli->outbuf);
1455 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1456 if (prots[numprots].prot > cli->protocol) {
1457 break;
1459 *p++ = 2;
1460 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1463 SCVAL(cli->outbuf,smb_com,SMBnegprot);
1464 cli_setup_bcc(cli, p);
1465 cli_setup_packet(cli);
1467 SCVAL(smb_buf(cli->outbuf),0,2);
1469 cli_send_smb(cli);
1472 /****************************************************************************
1473 Send a negprot command.
1474 ****************************************************************************/
1476 struct async_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
1477 struct event_context *ev,
1478 struct cli_state *cli)
1480 struct async_req *result;
1481 uint8_t *bytes = NULL;
1482 int numprots;
1484 if (cli->protocol < PROTOCOL_NT1)
1485 cli->use_spnego = False;
1487 /* setup the protocol strings */
1488 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1489 uint8_t c = 2;
1490 if (prots[numprots].prot > cli->protocol) {
1491 break;
1493 bytes = (uint8_t *)talloc_append_blob(
1494 talloc_tos(), bytes, data_blob_const(&c, sizeof(c)));
1495 if (bytes == NULL) {
1496 return NULL;
1498 bytes = smb_bytes_push_str(bytes, false,
1499 prots[numprots].name,
1500 strlen(prots[numprots].name)+1,
1501 NULL);
1502 if (bytes == NULL) {
1503 return NULL;
1507 result = cli_request_send(mem_ctx, ev, cli, SMBnegprot, 0, 0, NULL, 0,
1508 talloc_get_size(bytes), bytes);
1509 TALLOC_FREE(bytes);
1510 return result;
1513 NTSTATUS cli_negprot_recv(struct async_req *req)
1515 struct cli_request *cli_req = talloc_get_type_abort(
1516 req->private_data, struct cli_request);
1517 struct cli_state *cli = cli_req->cli;
1518 uint8_t wct;
1519 uint16_t *vwv;
1520 uint16_t num_bytes;
1521 uint8_t *bytes;
1522 NTSTATUS status;
1523 uint16_t protnum;
1525 if (async_req_is_nterror(req, &status)) {
1526 return status;
1529 status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
1530 if (!NT_STATUS_IS_OK(status)) {
1531 return status;
1534 protnum = SVAL(vwv, 0);
1536 if ((protnum >= ARRAY_SIZE(prots))
1537 || (prots[protnum].prot > cli_req->cli->protocol)) {
1538 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1541 cli->protocol = prots[protnum].prot;
1543 if ((cli->protocol < PROTOCOL_NT1) && cli->sign_info.mandatory_signing) {
1544 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1545 return NT_STATUS_ACCESS_DENIED;
1548 if (cli->protocol >= PROTOCOL_NT1) {
1549 struct timespec ts;
1550 /* NT protocol */
1551 cli->sec_mode = CVAL(vwv + 1, 0);
1552 cli->max_mux = SVAL(vwv + 1, 1);
1553 cli->max_xmit = IVAL(vwv + 3, 1);
1554 cli->sesskey = IVAL(vwv + 7, 1);
1555 cli->serverzone = SVALS(vwv + 15, 1);
1556 cli->serverzone *= 60;
1557 /* this time arrives in real GMT */
1558 ts = interpret_long_date(((char *)(vwv+11))+1);
1559 cli->servertime = ts.tv_sec;
1560 cli->secblob = data_blob(bytes, num_bytes);
1561 cli->capabilities = IVAL(vwv + 9, 1);
1562 if (cli->capabilities & CAP_RAW_MODE) {
1563 cli->readbraw_supported = True;
1564 cli->writebraw_supported = True;
1566 /* work out if they sent us a workgroup */
1567 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1568 smb_buflen(cli->inbuf) > 8) {
1569 clistr_pull(cli->inbuf, cli->server_domain,
1570 bytes+8, sizeof(cli->server_domain),
1571 num_bytes-8,
1572 STR_UNICODE|STR_NOALIGN);
1576 * As signing is slow we only turn it on if either the client or
1577 * the server require it. JRA.
1580 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
1581 /* Fail if server says signing is mandatory and we don't want to support it. */
1582 if (!cli->sign_info.allow_smb_signing) {
1583 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1584 return NT_STATUS_ACCESS_DENIED;
1586 cli->sign_info.negotiated_smb_signing = True;
1587 cli->sign_info.mandatory_signing = True;
1588 } else if (cli->sign_info.mandatory_signing && cli->sign_info.allow_smb_signing) {
1589 /* Fail if client says signing is mandatory and the server doesn't support it. */
1590 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
1591 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1592 return NT_STATUS_ACCESS_DENIED;
1594 cli->sign_info.negotiated_smb_signing = True;
1595 cli->sign_info.mandatory_signing = True;
1596 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
1597 cli->sign_info.negotiated_smb_signing = True;
1600 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
1601 SAFE_FREE(cli->outbuf);
1602 SAFE_FREE(cli->inbuf);
1603 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1604 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1605 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
1608 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1609 cli->use_spnego = False;
1610 cli->sec_mode = SVAL(vwv + 1, 0);
1611 cli->max_xmit = SVAL(vwv + 2, 0);
1612 cli->max_mux = SVAL(vwv + 3, 0);
1613 cli->sesskey = IVAL(vwv + 6, 0);
1614 cli->serverzone = SVALS(vwv + 10, 0);
1615 cli->serverzone *= 60;
1616 /* this time is converted to GMT by make_unix_date */
1617 cli->servertime = cli_make_unix_date(
1618 cli, (char *)(vwv + 8));
1619 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
1620 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
1621 cli->secblob = data_blob(bytes, num_bytes);
1622 } else {
1623 /* the old core protocol */
1624 cli->use_spnego = False;
1625 cli->sec_mode = 0;
1626 cli->serverzone = get_time_zone(time(NULL));
1629 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1631 /* a way to force ascii SMB */
1632 if (getenv("CLI_FORCE_ASCII"))
1633 cli->capabilities &= ~CAP_UNICODE;
1635 return NT_STATUS_OK;
1638 NTSTATUS cli_negprot(struct cli_state *cli)
1640 TALLOC_CTX *frame = talloc_stackframe();
1641 struct event_context *ev;
1642 struct async_req *req;
1643 NTSTATUS status = NT_STATUS_NO_MEMORY;
1645 if (cli->fd_event != NULL) {
1647 * Can't use sync call while an async call is in flight
1649 cli_set_error(cli, NT_STATUS_INVALID_PARAMETER);
1650 goto fail;
1653 ev = event_context_init(frame);
1654 if (ev == NULL) {
1655 goto fail;
1658 req = cli_negprot_send(frame, ev, cli);
1659 if (req == NULL) {
1660 goto fail;
1663 while (req->state < ASYNC_REQ_DONE) {
1664 event_loop_once(ev);
1667 status = cli_negprot_recv(req);
1668 fail:
1669 TALLOC_FREE(frame);
1670 return status;
1673 /****************************************************************************
1674 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1675 ****************************************************************************/
1677 bool cli_session_request(struct cli_state *cli,
1678 struct nmb_name *calling, struct nmb_name *called)
1680 char *p;
1681 int len = 4;
1682 char *tmp;
1684 /* 445 doesn't have session request */
1685 if (cli->port == 445)
1686 return True;
1688 memcpy(&(cli->calling), calling, sizeof(*calling));
1689 memcpy(&(cli->called ), called , sizeof(*called ));
1691 /* put in the destination name */
1693 tmp = name_mangle(talloc_tos(), cli->called.name,
1694 cli->called.name_type);
1695 if (tmp == NULL) {
1696 return false;
1699 p = cli->outbuf+len;
1700 memcpy(p, tmp, name_len(tmp));
1701 len += name_len(tmp);
1702 TALLOC_FREE(tmp);
1704 /* and my name */
1706 tmp = name_mangle(talloc_tos(), cli->calling.name,
1707 cli->calling.name_type);
1708 if (tmp == NULL) {
1709 return false;
1712 p = cli->outbuf+len;
1713 memcpy(p, tmp, name_len(tmp));
1714 len += name_len(tmp);
1715 TALLOC_FREE(tmp);
1717 /* send a session request (RFC 1002) */
1718 /* setup the packet length
1719 * Remove four bytes from the length count, since the length
1720 * field in the NBT Session Service header counts the number
1721 * of bytes which follow. The cli_send_smb() function knows
1722 * about this and accounts for those four bytes.
1723 * CRH.
1725 len -= 4;
1726 _smb_setlen(cli->outbuf,len);
1727 SCVAL(cli->outbuf,0,0x81);
1729 cli_send_smb(cli);
1730 DEBUG(5,("Sent session request\n"));
1732 if (!cli_receive_smb(cli))
1733 return False;
1735 if (CVAL(cli->inbuf,0) == 0x84) {
1736 /* C. Hoch 9/14/95 Start */
1737 /* For information, here is the response structure.
1738 * We do the byte-twiddling to for portability.
1739 struct RetargetResponse{
1740 unsigned char type;
1741 unsigned char flags;
1742 int16 length;
1743 int32 ip_addr;
1744 int16 port;
1747 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1748 struct in_addr dest_ip;
1749 NTSTATUS status;
1751 /* SESSION RETARGET */
1752 putip((char *)&dest_ip,cli->inbuf+4);
1753 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
1755 status = open_socket_out(&cli->dest_ss, port,
1756 LONG_CONNECT_TIMEOUT, &cli->fd);
1757 if (!NT_STATUS_IS_OK(status)) {
1758 return False;
1761 DEBUG(3,("Retargeted\n"));
1763 set_socket_options(cli->fd, lp_socket_options());
1765 /* Try again */
1767 static int depth;
1768 bool ret;
1769 if (depth > 4) {
1770 DEBUG(0,("Retarget recursion - failing\n"));
1771 return False;
1773 depth++;
1774 ret = cli_session_request(cli, calling, called);
1775 depth--;
1776 return ret;
1778 } /* C. Hoch 9/14/95 End */
1780 if (CVAL(cli->inbuf,0) != 0x82) {
1781 /* This is the wrong place to put the error... JRA. */
1782 cli->rap_error = CVAL(cli->inbuf,4);
1783 return False;
1785 return(True);
1788 struct fd_struct {
1789 int fd;
1792 static void smb_sock_connected(struct tevent_req *req)
1794 struct fd_struct *pfd = tevent_req_callback_data(
1795 req, struct fd_struct);
1796 int fd;
1797 NTSTATUS status;
1799 status = open_socket_out_defer_recv(req, &fd);
1800 if (NT_STATUS_IS_OK(status)) {
1801 pfd->fd = fd;
1805 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
1806 uint16_t *port, int timeout, int *pfd)
1808 struct event_context *ev;
1809 struct tevent_req *r139, *r445;
1810 struct fd_struct *fd139, *fd445;
1811 NTSTATUS status = NT_STATUS_NO_MEMORY;
1813 if (*port != 0) {
1814 return open_socket_out(pss, *port, timeout, pfd);
1817 ev = event_context_init(talloc_tos());
1818 if (ev == NULL) {
1819 return NT_STATUS_NO_MEMORY;
1822 fd139 = talloc(ev, struct fd_struct);
1823 if (fd139 == NULL) {
1824 goto done;
1826 fd139->fd = -1;
1828 fd445 = talloc(ev, struct fd_struct);
1829 if (fd445 == NULL) {
1830 goto done;
1832 fd445->fd = -1;
1834 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
1835 pss, 445, timeout);
1836 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
1837 pss, 139, timeout);
1838 if ((r445 == NULL) || (r139 == NULL)) {
1839 goto done;
1841 tevent_req_set_callback(r445, smb_sock_connected, fd445);
1842 tevent_req_set_callback(r139, smb_sock_connected, fd139);
1844 while ((fd445->fd == -1) && (fd139->fd == -1)
1845 && (tevent_req_is_in_progress(r139)
1846 || tevent_req_is_in_progress(r445))) {
1847 event_loop_once(ev);
1850 if ((fd139->fd != -1) && (fd445->fd != -1)) {
1851 close(fd139->fd);
1852 fd139->fd = -1;
1855 if (fd445->fd != -1) {
1856 *port = 445;
1857 *pfd = fd445->fd;
1858 status = NT_STATUS_OK;
1859 goto done;
1861 if (fd139->fd != -1) {
1862 *port = 139;
1863 *pfd = fd139->fd;
1864 status = NT_STATUS_OK;
1865 goto done;
1868 status = open_socket_out_defer_recv(r445, &fd445->fd);
1869 done:
1870 TALLOC_FREE(ev);
1871 return status;
1874 /****************************************************************************
1875 Open the client sockets.
1876 ****************************************************************************/
1878 NTSTATUS cli_connect(struct cli_state *cli,
1879 const char *host,
1880 struct sockaddr_storage *dest_ss)
1883 int name_type = 0x20;
1884 TALLOC_CTX *frame = talloc_stackframe();
1885 unsigned int num_addrs = 0;
1886 unsigned int i = 0;
1887 struct sockaddr_storage *ss_arr = NULL;
1888 char *p = NULL;
1890 /* reasonable default hostname */
1891 if (!host) {
1892 host = STAR_SMBSERVER;
1895 fstrcpy(cli->desthost, host);
1897 /* allow hostnames of the form NAME#xx and do a netbios lookup */
1898 if ((p = strchr(cli->desthost, '#'))) {
1899 name_type = strtol(p+1, NULL, 16);
1900 *p = 0;
1903 if (!dest_ss || is_zero_addr((struct sockaddr *)dest_ss)) {
1904 NTSTATUS status =resolve_name_list(frame,
1905 cli->desthost,
1906 name_type,
1907 &ss_arr,
1908 &num_addrs);
1909 if (!NT_STATUS_IS_OK(status)) {
1910 TALLOC_FREE(frame);
1911 return NT_STATUS_BAD_NETWORK_NAME;
1913 } else {
1914 num_addrs = 1;
1915 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
1916 if (!ss_arr) {
1917 TALLOC_FREE(frame);
1918 return NT_STATUS_NO_MEMORY;
1920 *ss_arr = *dest_ss;
1923 for (i = 0; i < num_addrs; i++) {
1924 cli->dest_ss = ss_arr[i];
1925 if (getenv("LIBSMB_PROG")) {
1926 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
1927 } else {
1928 uint16_t port = cli->port;
1929 NTSTATUS status;
1930 status = open_smb_socket(&cli->dest_ss, &port,
1931 cli->timeout, &cli->fd);
1932 if (NT_STATUS_IS_OK(status)) {
1933 cli->port = port;
1936 if (cli->fd == -1) {
1937 char addr[INET6_ADDRSTRLEN];
1938 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
1939 DEBUG(2,("Error connecting to %s (%s)\n",
1940 dest_ss?addr:host,strerror(errno)));
1941 } else {
1942 /* Exit from loop on first connection. */
1943 break;
1947 if (cli->fd == -1) {
1948 TALLOC_FREE(frame);
1949 return map_nt_error_from_unix(errno);
1952 if (dest_ss) {
1953 *dest_ss = cli->dest_ss;
1956 set_socket_options(cli->fd, lp_socket_options());
1958 TALLOC_FREE(frame);
1959 return NT_STATUS_OK;
1963 establishes a connection to after the negprot.
1964 @param output_cli A fully initialised cli structure, non-null only on success
1965 @param dest_host The netbios name of the remote host
1966 @param dest_ss (optional) The the destination IP, NULL for name based lookup
1967 @param port (optional) The destination port (0 for default)
1968 @param retry bool. Did this connection fail with a retryable error ?
1971 NTSTATUS cli_start_connection(struct cli_state **output_cli,
1972 const char *my_name,
1973 const char *dest_host,
1974 struct sockaddr_storage *dest_ss, int port,
1975 int signing_state, int flags,
1976 bool *retry)
1978 NTSTATUS nt_status;
1979 struct nmb_name calling;
1980 struct nmb_name called;
1981 struct cli_state *cli;
1982 struct sockaddr_storage ss;
1984 if (retry)
1985 *retry = False;
1987 if (!my_name)
1988 my_name = global_myname();
1990 if (!(cli = cli_initialise_ex(signing_state))) {
1991 return NT_STATUS_NO_MEMORY;
1994 make_nmb_name(&calling, my_name, 0x0);
1995 make_nmb_name(&called , dest_host, 0x20);
1997 cli_set_port(cli, port);
1998 cli_set_timeout(cli, 10000); /* 10 seconds. */
2000 if (dest_ss) {
2001 ss = *dest_ss;
2002 } else {
2003 zero_sockaddr(&ss);
2006 again:
2008 DEBUG(3,("Connecting to host=%s\n", dest_host));
2010 nt_status = cli_connect(cli, dest_host, &ss);
2011 if (!NT_STATUS_IS_OK(nt_status)) {
2012 char addr[INET6_ADDRSTRLEN];
2013 print_sockaddr(addr, sizeof(addr), &ss);
2014 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
2015 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
2016 cli_shutdown(cli);
2017 return nt_status;
2020 if (retry)
2021 *retry = True;
2023 if (!cli_session_request(cli, &calling, &called)) {
2024 char *p;
2025 DEBUG(1,("session request to %s failed (%s)\n",
2026 called.name, cli_errstr(cli)));
2027 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
2028 *p = 0;
2029 goto again;
2031 if (strcmp(called.name, STAR_SMBSERVER)) {
2032 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
2033 goto again;
2035 return NT_STATUS_BAD_NETWORK_NAME;
2038 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
2039 cli->use_spnego = False;
2040 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
2041 cli->use_kerberos = True;
2043 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
2044 cli->use_kerberos) {
2045 cli->fallback_after_kerberos = true;
2048 nt_status = cli_negprot(cli);
2049 if (!NT_STATUS_IS_OK(nt_status)) {
2050 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2051 cli_shutdown(cli);
2052 return nt_status;
2055 *output_cli = cli;
2056 return NT_STATUS_OK;
2061 establishes a connection right up to doing tconX, password specified.
2062 @param output_cli A fully initialised cli structure, non-null only on success
2063 @param dest_host The netbios name of the remote host
2064 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2065 @param port (optional) The destination port (0 for default)
2066 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2067 @param service_type The 'type' of serivice.
2068 @param user Username, unix string
2069 @param domain User's domain
2070 @param password User's password, unencrypted unix string.
2071 @param retry bool. Did this connection fail with a retryable error ?
2074 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2075 const char *my_name,
2076 const char *dest_host,
2077 struct sockaddr_storage *dest_ss, int port,
2078 const char *service, const char *service_type,
2079 const char *user, const char *domain,
2080 const char *password, int flags,
2081 int signing_state,
2082 bool *retry)
2084 NTSTATUS nt_status;
2085 struct cli_state *cli = NULL;
2086 int pw_len = password ? strlen(password)+1 : 0;
2088 *output_cli = NULL;
2090 if (password == NULL) {
2091 password = "";
2094 nt_status = cli_start_connection(&cli, my_name, dest_host,
2095 dest_ss, port, signing_state,
2096 flags, retry);
2098 if (!NT_STATUS_IS_OK(nt_status)) {
2099 return nt_status;
2102 nt_status = cli_session_setup(cli, user, password, pw_len, password,
2103 pw_len, domain);
2104 if (!NT_STATUS_IS_OK(nt_status)) {
2106 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2107 DEBUG(1,("failed session setup with %s\n",
2108 nt_errstr(nt_status)));
2109 cli_shutdown(cli);
2110 return nt_status;
2113 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2114 if (!NT_STATUS_IS_OK(nt_status)) {
2115 DEBUG(1,("anonymous failed session setup with %s\n",
2116 nt_errstr(nt_status)));
2117 cli_shutdown(cli);
2118 return nt_status;
2122 if (service) {
2123 nt_status = cli_tcon_andx(cli, service, service_type, password,
2124 pw_len);
2125 if (!NT_STATUS_IS_OK(nt_status)) {
2126 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2127 cli_shutdown(cli);
2128 if (NT_STATUS_IS_OK(nt_status)) {
2129 nt_status = NT_STATUS_UNSUCCESSFUL;
2131 return nt_status;
2135 nt_status = cli_init_creds(cli, user, domain, password);
2136 if (!NT_STATUS_IS_OK(nt_status)) {
2137 cli_shutdown(cli);
2138 return nt_status;
2141 *output_cli = cli;
2142 return NT_STATUS_OK;
2145 /****************************************************************************
2146 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2147 ****************************************************************************/
2149 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
2150 struct sockaddr_storage *pdest_ss)
2152 struct nmb_name calling, called;
2154 make_nmb_name(&calling, srchost, 0x0);
2157 * If the called name is an IP address
2158 * then use *SMBSERVER immediately.
2161 if(is_ipaddress(desthost)) {
2162 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
2163 } else {
2164 make_nmb_name(&called, desthost, 0x20);
2167 if (!cli_session_request(*ppcli, &calling, &called)) {
2168 NTSTATUS status;
2169 struct nmb_name smbservername;
2171 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
2174 * If the name wasn't *SMBSERVER then
2175 * try with *SMBSERVER if the first name fails.
2178 if (nmb_name_equal(&called, &smbservername)) {
2181 * The name used was *SMBSERVER, don't bother with another name.
2184 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2185 with error %s.\n", desthost, cli_errstr(*ppcli) ));
2186 return False;
2189 /* Try again... */
2190 cli_shutdown(*ppcli);
2192 *ppcli = cli_initialise();
2193 if (!*ppcli) {
2194 /* Out of memory... */
2195 return False;
2198 status = cli_connect(*ppcli, desthost, pdest_ss);
2199 if (!NT_STATUS_IS_OK(status) ||
2200 !cli_session_request(*ppcli, &calling, &smbservername)) {
2201 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2202 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
2203 return False;
2207 return True;
2210 /****************************************************************************
2211 Send an old style tcon.
2212 ****************************************************************************/
2213 NTSTATUS cli_raw_tcon(struct cli_state *cli,
2214 const char *service, const char *pass, const char *dev,
2215 uint16 *max_xmit, uint16 *tid)
2217 char *p;
2219 if (!lp_client_plaintext_auth() && (*pass)) {
2220 DEBUG(1, ("Server requested plaintext password but 'client "
2221 "plaintext auth' is disabled\n"));
2222 return NT_STATUS_ACCESS_DENIED;
2225 memset(cli->outbuf,'\0',smb_size);
2226 memset(cli->inbuf,'\0',smb_size);
2228 cli_set_message(cli->outbuf, 0, 0, True);
2229 SCVAL(cli->outbuf,smb_com,SMBtcon);
2230 cli_setup_packet(cli);
2232 p = smb_buf(cli->outbuf);
2233 *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
2234 *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
2235 *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
2237 cli_setup_bcc(cli, p);
2239 cli_send_smb(cli);
2240 if (!cli_receive_smb(cli)) {
2241 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2244 if (cli_is_error(cli)) {
2245 return cli_nt_error(cli);
2248 *max_xmit = SVAL(cli->inbuf, smb_vwv0);
2249 *tid = SVAL(cli->inbuf, smb_vwv1);
2251 return NT_STATUS_OK;
2254 /* Return a cli_state pointing at the IPC$ share for the given server */
2256 struct cli_state *get_ipc_connect(char *server,
2257 struct sockaddr_storage *server_ss,
2258 const struct user_auth_info *user_info)
2260 struct cli_state *cli;
2261 NTSTATUS nt_status;
2262 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2264 if (user_info->use_kerberos) {
2265 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2268 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
2269 user_info->username ? user_info->username : "",
2270 lp_workgroup(),
2271 user_info->password ? user_info->password : "",
2272 flags,
2273 Undefined, NULL);
2275 if (NT_STATUS_IS_OK(nt_status)) {
2276 return cli;
2277 } else if (is_ipaddress(server)) {
2278 /* windows 9* needs a correct NMB name for connections */
2279 fstring remote_name;
2281 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2282 cli = get_ipc_connect(remote_name, server_ss, user_info);
2283 if (cli)
2284 return cli;
2287 return NULL;
2291 * Given the IP address of a master browser on the network, return its
2292 * workgroup and connect to it.
2294 * This function is provided to allow additional processing beyond what
2295 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2296 * browsers and obtain each master browsers' list of domains (in case the
2297 * first master browser is recently on the network and has not yet
2298 * synchronized with other master browsers and therefore does not yet have the
2299 * entire network browse list)
2302 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2303 struct ip_service *mb_ip,
2304 const struct user_auth_info *user_info,
2305 char **pp_workgroup_out)
2307 char addr[INET6_ADDRSTRLEN];
2308 fstring name;
2309 struct cli_state *cli;
2310 struct sockaddr_storage server_ss;
2312 *pp_workgroup_out = NULL;
2314 print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2315 DEBUG(99, ("Looking up name of master browser %s\n",
2316 addr));
2319 * Do a name status query to find out the name of the master browser.
2320 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2321 * master browser will not respond to a wildcard query (or, at least,
2322 * an NT4 server acting as the domain master browser will not).
2324 * We might be able to use ONLY the query on MSBROWSE, but that's not
2325 * yet been tested with all Windows versions, so until it is, leave
2326 * the original wildcard query as the first choice and fall back to
2327 * MSBROWSE if the wildcard query fails.
2329 if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2330 !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2332 DEBUG(99, ("Could not retrieve name status for %s\n",
2333 addr));
2334 return NULL;
2337 if (!find_master_ip(name, &server_ss)) {
2338 DEBUG(99, ("Could not find master ip for %s\n", name));
2339 return NULL;
2342 *pp_workgroup_out = talloc_strdup(ctx, name);
2344 DEBUG(4, ("found master browser %s, %s\n", name, addr));
2346 print_sockaddr(addr, sizeof(addr), &server_ss);
2347 cli = get_ipc_connect(addr, &server_ss, user_info);
2349 return cli;
2353 * Return the IP address and workgroup of a master browser on the network, and
2354 * connect to it.
2357 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2358 const struct user_auth_info *user_info,
2359 char **pp_workgroup_out)
2361 struct ip_service *ip_list;
2362 struct cli_state *cli;
2363 int i, count;
2365 *pp_workgroup_out = NULL;
2367 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2369 /* Go looking for workgroups by broadcasting on the local network */
2371 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2372 &count))) {
2373 DEBUG(99, ("No master browsers responded\n"));
2374 return False;
2377 for (i = 0; i < count; i++) {
2378 char addr[INET6_ADDRSTRLEN];
2379 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2380 DEBUG(99, ("Found master browser %s\n", addr));
2382 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2383 user_info, pp_workgroup_out);
2384 if (cli)
2385 return(cli);
2388 return NULL;