s3 OneFS: Add an atomic sendfile implementation
[Samba/fernandojvsilva.git] / source3 / libsmb / cliconnect.c
blobdabfc398ced293703dff0bc0f4fd9d85a616b4cd
1 /*
2 Unix SMB/CIFS implementation.
3 client connect/disconnect routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Andrew Bartlett 2001-2003
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
23 static const struct {
24 int prot;
25 const char name[24];
26 } prots[10] = {
27 {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
28 {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
29 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
30 {PROTOCOL_LANMAN1, "LANMAN1.0"},
31 {PROTOCOL_LANMAN2, "LM1.2X002"},
32 {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
33 {PROTOCOL_LANMAN2, "LANMAN2.1"},
34 {PROTOCOL_LANMAN2, "Samba"},
35 {PROTOCOL_NT1, "NT LANMAN 1.0"},
36 {PROTOCOL_NT1, "NT LM 0.12"},
39 #define STAR_SMBSERVER "*SMBSERVER"
41 /**
42 * Set the user session key for a connection
43 * @param cli The cli structure to add it too
44 * @param session_key The session key used. (A copy of this is taken for the cli struct)
48 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
50 cli->user_session_key = data_blob(session_key.data, session_key.length);
53 /****************************************************************************
54 Do an old lanman2 style session setup.
55 ****************************************************************************/
57 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
58 const char *user,
59 const char *pass, size_t passlen,
60 const char *workgroup)
62 DATA_BLOB session_key = data_blob_null;
63 DATA_BLOB lm_response = data_blob_null;
64 fstring pword;
65 char *p;
67 if (passlen > sizeof(pword)-1) {
68 return NT_STATUS_INVALID_PARAMETER;
71 /* LANMAN servers predate NT status codes and Unicode and ignore those
72 smb flags so we must disable the corresponding default capabilities
73 that would otherwise cause the Unicode and NT Status flags to be
74 set (and even returned by the server) */
76 cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
78 /* if in share level security then don't send a password now */
79 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
80 passlen = 0;
82 if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
83 /* Encrypted mode needed, and non encrypted password supplied. */
84 lm_response = data_blob(NULL, 24);
85 if (!SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data)) {
86 DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n"));
87 return NT_STATUS_ACCESS_DENIED;
89 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
90 /* Encrypted mode needed, and encrypted password supplied. */
91 lm_response = data_blob(pass, passlen);
92 } else if (passlen > 0) {
93 /* Plaintext mode needed, assume plaintext supplied. */
94 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
95 lm_response = data_blob(pass, passlen);
98 /* send a session setup command */
99 memset(cli->outbuf,'\0',smb_size);
100 cli_set_message(cli->outbuf,10, 0, True);
101 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
102 cli_setup_packet(cli);
104 SCVAL(cli->outbuf,smb_vwv0,0xFF);
105 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
106 SSVAL(cli->outbuf,smb_vwv3,2);
107 SSVAL(cli->outbuf,smb_vwv4,1);
108 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
109 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
111 p = smb_buf(cli->outbuf);
112 memcpy(p,lm_response.data,lm_response.length);
113 p += lm_response.length;
114 p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
115 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
116 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
117 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
118 cli_setup_bcc(cli, p);
120 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
121 return cli_nt_error(cli);
124 show_msg(cli->inbuf);
126 if (cli_is_error(cli)) {
127 return cli_nt_error(cli);
130 /* use the returned vuid from now on */
131 cli->vuid = SVAL(cli->inbuf,smb_uid);
132 fstrcpy(cli->user_name, user);
134 if (session_key.data) {
135 /* Have plaintext orginal */
136 cli_set_session_key(cli, session_key);
139 return NT_STATUS_OK;
142 /****************************************************************************
143 Work out suitable capabilities to offer the server.
144 ****************************************************************************/
146 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
148 uint32 capabilities = CAP_NT_SMBS;
150 if (!cli->force_dos_errors)
151 capabilities |= CAP_STATUS32;
153 if (cli->use_level_II_oplocks)
154 capabilities |= CAP_LEVEL_II_OPLOCKS;
156 capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
157 return capabilities;
160 /****************************************************************************
161 Do a NT1 guest session setup.
162 ****************************************************************************/
164 struct async_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
165 struct event_context *ev,
166 struct cli_state *cli)
168 struct async_req *result;
169 uint16_t vwv[13];
170 uint8_t *bytes;
172 SCVAL(vwv+0, 0, 0xFF);
173 SCVAL(vwv+0, 1, 0);
174 SSVAL(vwv+1, 0, 0);
175 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
176 SSVAL(vwv+3, 0, 2);
177 SSVAL(vwv+4, 0, cli->pid);
178 SIVAL(vwv+5, 0, cli->sesskey);
179 SSVAL(vwv+7, 0, 0);
180 SSVAL(vwv+8, 0, 0);
181 SSVAL(vwv+9, 0, 0);
182 SSVAL(vwv+10, 0, 0);
183 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
185 bytes = talloc_array(talloc_tos(), uint8_t, 0);
187 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
188 NULL);
189 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
190 NULL);
191 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
192 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
194 if (bytes == NULL) {
195 return NULL;
198 result = cli_request_send(mem_ctx, ev, cli, SMBsesssetupX, 0,
199 13, vwv, 0, talloc_get_size(bytes), bytes);
200 TALLOC_FREE(bytes);
201 return result;
204 NTSTATUS cli_session_setup_guest_recv(struct async_req *req)
206 struct cli_request *cli_req = talloc_get_type_abort(
207 req->private_data, struct cli_request);
208 struct cli_state *cli = cli_req->cli;
209 uint8_t wct;
210 uint16_t *vwv;
211 uint16_t num_bytes;
212 uint8_t *bytes;
213 uint8_t *p;
214 NTSTATUS status;
216 if (async_req_is_nterror(req, &status)) {
217 return status;
220 status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
221 if (!NT_STATUS_IS_OK(status)) {
222 return status;
225 p = bytes;
227 cli->vuid = SVAL(cli_req->inbuf, smb_uid);
229 p += clistr_pull(cli_req->inbuf, cli->server_os, (char *)p,
230 sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE);
231 p += clistr_pull(cli_req->inbuf, cli->server_type, (char *)p,
232 sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE);
233 p += clistr_pull(cli_req->inbuf, cli->server_domain, (char *)p,
234 sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE);
236 if (strstr(cli->server_type, "Samba")) {
237 cli->is_samba = True;
240 fstrcpy(cli->user_name, "");
242 return NT_STATUS_OK;
245 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
247 TALLOC_CTX *frame = talloc_stackframe();
248 struct event_context *ev;
249 struct async_req *req;
250 NTSTATUS status;
252 if (cli->fd_event != NULL) {
254 * Can't use sync call while an async call is in flight
256 status = NT_STATUS_INVALID_PARAMETER;
257 goto fail;
260 ev = event_context_init(frame);
261 if (ev == NULL) {
262 status = NT_STATUS_NO_MEMORY;
263 goto fail;
266 req = cli_session_setup_guest_send(frame, ev, cli);
267 if (req == NULL) {
268 status = NT_STATUS_NO_MEMORY;
269 goto fail;
272 while (req->state < ASYNC_REQ_DONE) {
273 event_loop_once(ev);
276 status = cli_session_setup_guest_recv(req);
277 fail:
278 TALLOC_FREE(frame);
279 return status;
282 /****************************************************************************
283 Do a NT1 plaintext session setup.
284 ****************************************************************************/
286 static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
287 const char *user, const char *pass,
288 const char *workgroup)
290 uint32 capabilities = cli_session_setup_capabilities(cli);
291 char *p;
292 fstring lanman;
294 fstr_sprintf( lanman, "Samba %s", samba_version_string());
296 memset(cli->outbuf, '\0', smb_size);
297 cli_set_message(cli->outbuf,13,0,True);
298 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
299 cli_setup_packet(cli);
301 SCVAL(cli->outbuf,smb_vwv0,0xFF);
302 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
303 SSVAL(cli->outbuf,smb_vwv3,2);
304 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
305 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
306 SSVAL(cli->outbuf,smb_vwv8,0);
307 SIVAL(cli->outbuf,smb_vwv11,capabilities);
308 p = smb_buf(cli->outbuf);
310 /* check wether to send the ASCII or UNICODE version of the password */
312 if ( (capabilities & CAP_UNICODE) == 0 ) {
313 p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
314 SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
316 else {
317 /* For ucs2 passwords clistr_push calls ucs2_align, which causes
318 * the space taken by the unicode password to be one byte too
319 * long (as we're on an odd byte boundary here). Reduce the
320 * count by 1 to cope with this. Fixes smbclient against NetApp
321 * servers which can't cope. Fix from
322 * bryan.kolodziej@allenlund.com in bug #3840.
324 p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
325 SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))-1);
328 p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
329 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
330 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
331 p += clistr_push(cli, p, lanman, -1, STR_TERMINATE);
332 cli_setup_bcc(cli, p);
334 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
335 return cli_nt_error(cli);
338 show_msg(cli->inbuf);
340 if (cli_is_error(cli)) {
341 return cli_nt_error(cli);
344 cli->vuid = SVAL(cli->inbuf,smb_uid);
345 p = smb_buf(cli->inbuf);
346 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
347 -1, STR_TERMINATE);
348 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
349 -1, STR_TERMINATE);
350 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
351 -1, STR_TERMINATE);
352 fstrcpy(cli->user_name, user);
354 if (strstr(cli->server_type, "Samba")) {
355 cli->is_samba = True;
358 return NT_STATUS_OK;
361 /****************************************************************************
362 do a NT1 NTLM/LM encrypted session setup - for when extended security
363 is not negotiated.
364 @param cli client state to create do session setup on
365 @param user username
366 @param pass *either* cleartext password (passlen !=24) or LM response.
367 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
368 @param workgroup The user's domain.
369 ****************************************************************************/
371 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
372 const char *pass, size_t passlen,
373 const char *ntpass, size_t ntpasslen,
374 const char *workgroup)
376 uint32 capabilities = cli_session_setup_capabilities(cli);
377 DATA_BLOB lm_response = data_blob_null;
378 DATA_BLOB nt_response = data_blob_null;
379 DATA_BLOB session_key = data_blob_null;
380 NTSTATUS result;
381 char *p;
383 if (passlen == 0) {
384 /* do nothing - guest login */
385 } else if (passlen != 24) {
386 if (lp_client_ntlmv2_auth()) {
387 DATA_BLOB server_chal;
388 DATA_BLOB names_blob;
389 server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8));
391 /* note that the 'workgroup' here is a best guess - we don't know
392 the server's domain at this point. The 'server name' is also
393 dodgy...
395 names_blob = NTLMv2_generate_names_blob(cli->called.name, workgroup);
397 if (!SMBNTLMv2encrypt(user, workgroup, pass, &server_chal,
398 &names_blob,
399 &lm_response, &nt_response, &session_key)) {
400 data_blob_free(&names_blob);
401 data_blob_free(&server_chal);
402 return NT_STATUS_ACCESS_DENIED;
404 data_blob_free(&names_blob);
405 data_blob_free(&server_chal);
407 } else {
408 uchar nt_hash[16];
409 E_md4hash(pass, nt_hash);
411 #ifdef LANMAN_ONLY
412 nt_response = data_blob_null;
413 #else
414 nt_response = data_blob(NULL, 24);
415 SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
416 #endif
417 /* non encrypted password supplied. Ignore ntpass. */
418 if (lp_client_lanman_auth()) {
419 lm_response = data_blob(NULL, 24);
420 if (!SMBencrypt(pass,cli->secblob.data, lm_response.data)) {
421 /* Oops, the LM response is invalid, just put
422 the NT response there instead */
423 data_blob_free(&lm_response);
424 lm_response = data_blob(nt_response.data, nt_response.length);
426 } else {
427 /* LM disabled, place NT# in LM field instead */
428 lm_response = data_blob(nt_response.data, nt_response.length);
431 session_key = data_blob(NULL, 16);
432 #ifdef LANMAN_ONLY
433 E_deshash(pass, session_key.data);
434 memset(&session_key.data[8], '\0', 8);
435 #else
436 SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
437 #endif
439 #ifdef LANMAN_ONLY
440 cli_simple_set_signing(cli, session_key, lm_response);
441 #else
442 cli_simple_set_signing(cli, session_key, nt_response);
443 #endif
444 } else {
445 /* pre-encrypted password supplied. Only used for
446 security=server, can't do
447 signing because we don't have original key */
449 lm_response = data_blob(pass, passlen);
450 nt_response = data_blob(ntpass, ntpasslen);
453 /* send a session setup command */
454 memset(cli->outbuf,'\0',smb_size);
456 cli_set_message(cli->outbuf,13,0,True);
457 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
458 cli_setup_packet(cli);
460 SCVAL(cli->outbuf,smb_vwv0,0xFF);
461 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
462 SSVAL(cli->outbuf,smb_vwv3,2);
463 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
464 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
465 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
466 SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
467 SIVAL(cli->outbuf,smb_vwv11,capabilities);
468 p = smb_buf(cli->outbuf);
469 if (lm_response.length) {
470 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
472 if (nt_response.length) {
473 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
475 p += clistr_push(cli, p, user, -1, STR_TERMINATE);
477 /* Upper case here might help some NTLMv2 implementations */
478 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
479 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
480 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
481 cli_setup_bcc(cli, p);
483 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
484 result = cli_nt_error(cli);
485 goto end;
488 /* show_msg(cli->inbuf); */
490 if (cli_is_error(cli)) {
491 result = cli_nt_error(cli);
492 goto end;
495 /* use the returned vuid from now on */
496 cli->vuid = SVAL(cli->inbuf,smb_uid);
498 p = smb_buf(cli->inbuf);
499 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
500 -1, STR_TERMINATE);
501 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
502 -1, STR_TERMINATE);
503 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
504 -1, STR_TERMINATE);
506 if (strstr(cli->server_type, "Samba")) {
507 cli->is_samba = True;
510 fstrcpy(cli->user_name, user);
512 if (session_key.data) {
513 /* Have plaintext orginal */
514 cli_set_session_key(cli, session_key);
517 result = NT_STATUS_OK;
518 end:
519 data_blob_free(&lm_response);
520 data_blob_free(&nt_response);
521 data_blob_free(&session_key);
522 return result;
525 /****************************************************************************
526 Send a extended security session setup blob
527 ****************************************************************************/
529 static bool cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob)
531 uint32 capabilities = cli_session_setup_capabilities(cli);
532 char *p;
534 capabilities |= CAP_EXTENDED_SECURITY;
536 /* send a session setup command */
537 memset(cli->outbuf,'\0',smb_size);
539 cli_set_message(cli->outbuf,12,0,True);
540 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
542 cli_setup_packet(cli);
544 SCVAL(cli->outbuf,smb_vwv0,0xFF);
545 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
546 SSVAL(cli->outbuf,smb_vwv3,2);
547 SSVAL(cli->outbuf,smb_vwv4,1);
548 SIVAL(cli->outbuf,smb_vwv5,0);
549 SSVAL(cli->outbuf,smb_vwv7,blob.length);
550 SIVAL(cli->outbuf,smb_vwv10,capabilities);
551 p = smb_buf(cli->outbuf);
552 memcpy(p, blob.data, blob.length);
553 p += blob.length;
554 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
555 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
556 cli_setup_bcc(cli, p);
557 return cli_send_smb(cli);
560 /****************************************************************************
561 Send a extended security session setup blob, returning a reply blob.
562 ****************************************************************************/
564 static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli)
566 DATA_BLOB blob2 = data_blob_null;
567 char *p;
568 size_t len;
570 if (!cli_receive_smb(cli))
571 return blob2;
573 show_msg(cli->inbuf);
575 if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli),
576 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
577 return blob2;
580 /* use the returned vuid from now on */
581 cli->vuid = SVAL(cli->inbuf,smb_uid);
583 p = smb_buf(cli->inbuf);
585 blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3));
587 p += blob2.length;
588 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
589 -1, STR_TERMINATE);
591 /* w2k with kerberos doesn't properly null terminate this field */
592 len = smb_bufrem(cli->inbuf, p);
593 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
594 len, 0);
596 return blob2;
599 #ifdef HAVE_KRB5
600 /****************************************************************************
601 Send a extended security session setup blob, returning a reply blob.
602 ****************************************************************************/
604 /* The following is calculated from :
605 * (smb_size-4) = 35
606 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
607 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
608 * end of packet.
611 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
613 static bool cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
615 int32 remaining = blob.length;
616 int32 cur = 0;
617 DATA_BLOB send_blob = data_blob_null;
618 int32 max_blob_size = 0;
619 DATA_BLOB receive_blob = data_blob_null;
621 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
622 DEBUG(0,("cli_session_setup_blob: cli->max_xmit too small "
623 "(was %u, need minimum %u)\n",
624 (unsigned int)cli->max_xmit,
625 BASE_SESSSETUP_BLOB_PACKET_SIZE));
626 cli_set_nt_error(cli, NT_STATUS_INVALID_PARAMETER);
627 return False;
630 max_blob_size = cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE;
632 while ( remaining > 0) {
633 if (remaining >= max_blob_size) {
634 send_blob.length = max_blob_size;
635 remaining -= max_blob_size;
636 } else {
637 send_blob.length = remaining;
638 remaining = 0;
641 send_blob.data = &blob.data[cur];
642 cur += send_blob.length;
644 DEBUG(10, ("cli_session_setup_blob: Remaining (%u) sending (%u) current (%u)\n",
645 (unsigned int)remaining,
646 (unsigned int)send_blob.length,
647 (unsigned int)cur ));
649 if (!cli_session_setup_blob_send(cli, send_blob)) {
650 DEBUG(0, ("cli_session_setup_blob: send failed\n"));
651 return False;
654 receive_blob = cli_session_setup_blob_receive(cli);
655 data_blob_free(&receive_blob);
657 if (cli_is_error(cli) &&
658 !NT_STATUS_EQUAL( cli_get_nt_error(cli),
659 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
660 DEBUG(0, ("cli_session_setup_blob: receive failed "
661 "(%s)\n", nt_errstr(cli_get_nt_error(cli))));
662 cli->vuid = 0;
663 return False;
667 return True;
670 /****************************************************************************
671 Use in-memory credentials cache
672 ****************************************************************************/
674 static void use_in_memory_ccache(void) {
675 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
678 /****************************************************************************
679 Do a spnego/kerberos encrypted session setup.
680 ****************************************************************************/
682 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
684 DATA_BLOB negTokenTarg;
685 DATA_BLOB session_key_krb5;
686 NTSTATUS nt_status;
687 int rc;
689 cli_temp_set_signing(cli);
691 DEBUG(2,("Doing kerberos session setup\n"));
693 /* generate the encapsulated kerberos5 ticket */
694 rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5, 0, NULL);
696 if (rc) {
697 DEBUG(1, ("cli_session_setup_kerberos: spnego_gen_negTokenTarg failed: %s\n",
698 error_message(rc)));
699 return ADS_ERROR_KRB5(rc);
702 #if 0
703 file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
704 #endif
706 if (!cli_session_setup_blob(cli, negTokenTarg)) {
707 nt_status = cli_nt_error(cli);
708 goto nt_error;
711 if (cli_is_error(cli)) {
712 nt_status = cli_nt_error(cli);
713 if (NT_STATUS_IS_OK(nt_status)) {
714 nt_status = NT_STATUS_UNSUCCESSFUL;
716 goto nt_error;
719 cli_set_session_key(cli, session_key_krb5);
721 if (cli_simple_set_signing(
722 cli, session_key_krb5, data_blob_null)) {
724 /* 'resign' the last message, so we get the right sequence numbers
725 for checking the first reply from the server */
726 cli_calculate_sign_mac(cli, cli->outbuf);
728 if (!cli_check_sign_mac(cli, cli->inbuf)) {
729 nt_status = NT_STATUS_ACCESS_DENIED;
730 goto nt_error;
734 data_blob_free(&negTokenTarg);
735 data_blob_free(&session_key_krb5);
737 return ADS_ERROR_NT(NT_STATUS_OK);
739 nt_error:
740 data_blob_free(&negTokenTarg);
741 data_blob_free(&session_key_krb5);
742 cli->vuid = 0;
743 return ADS_ERROR_NT(nt_status);
745 #endif /* HAVE_KRB5 */
748 /****************************************************************************
749 Do a spnego/NTLMSSP encrypted session setup.
750 ****************************************************************************/
752 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
753 const char *pass, const char *domain)
755 struct ntlmssp_state *ntlmssp_state;
756 NTSTATUS nt_status;
757 int turn = 1;
758 DATA_BLOB msg1;
759 DATA_BLOB blob = data_blob_null;
760 DATA_BLOB blob_in = data_blob_null;
761 DATA_BLOB blob_out = data_blob_null;
763 cli_temp_set_signing(cli);
765 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
766 return nt_status;
768 ntlmssp_want_feature(ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
770 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
771 return nt_status;
773 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
774 return nt_status;
776 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
777 return nt_status;
780 do {
781 nt_status = ntlmssp_update(ntlmssp_state,
782 blob_in, &blob_out);
783 data_blob_free(&blob_in);
784 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(nt_status)) {
785 if (turn == 1) {
786 /* and wrap it in a SPNEGO wrapper */
787 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
788 } else {
789 /* wrap it in SPNEGO */
790 msg1 = spnego_gen_auth(blob_out);
793 /* now send that blob on its way */
794 if (!cli_session_setup_blob_send(cli, msg1)) {
795 DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
796 nt_status = NT_STATUS_UNSUCCESSFUL;
797 } else {
798 blob = cli_session_setup_blob_receive(cli);
800 nt_status = cli_nt_error(cli);
801 if (cli_is_error(cli) && NT_STATUS_IS_OK(nt_status)) {
802 if (cli->smb_rw_error == SMB_READ_BAD_SIG) {
803 nt_status = NT_STATUS_ACCESS_DENIED;
804 } else {
805 nt_status = NT_STATUS_UNSUCCESSFUL;
809 data_blob_free(&msg1);
812 if (!blob.length) {
813 if (NT_STATUS_IS_OK(nt_status)) {
814 nt_status = NT_STATUS_UNSUCCESSFUL;
816 } else if ((turn == 1) &&
817 NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
818 DATA_BLOB tmp_blob = data_blob_null;
819 /* the server might give us back two challenges */
820 if (!spnego_parse_challenge(blob, &blob_in,
821 &tmp_blob)) {
822 DEBUG(3,("Failed to parse challenges\n"));
823 nt_status = NT_STATUS_INVALID_PARAMETER;
825 data_blob_free(&tmp_blob);
826 } else {
827 if (!spnego_parse_auth_response(blob, nt_status, OID_NTLMSSP,
828 &blob_in)) {
829 DEBUG(3,("Failed to parse auth response\n"));
830 if (NT_STATUS_IS_OK(nt_status)
831 || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED))
832 nt_status = NT_STATUS_INVALID_PARAMETER;
835 data_blob_free(&blob);
836 data_blob_free(&blob_out);
837 turn++;
838 } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
840 data_blob_free(&blob_in);
842 if (NT_STATUS_IS_OK(nt_status)) {
844 fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
845 cli_set_session_key(cli, ntlmssp_state->session_key);
847 if (cli_simple_set_signing(
848 cli, ntlmssp_state->session_key, data_blob_null)) {
850 /* 'resign' the last message, so we get the right sequence numbers
851 for checking the first reply from the server */
852 cli_calculate_sign_mac(cli, cli->outbuf);
854 if (!cli_check_sign_mac(cli, cli->inbuf)) {
855 nt_status = NT_STATUS_ACCESS_DENIED;
860 /* we have a reference conter on ntlmssp_state, if we are signing
861 then the state will be kept by the signing engine */
863 ntlmssp_end(&ntlmssp_state);
865 if (!NT_STATUS_IS_OK(nt_status)) {
866 cli->vuid = 0;
868 return nt_status;
871 /****************************************************************************
872 Do a spnego encrypted session setup.
874 user_domain: The shortname of the domain the user/machine is a member of.
875 dest_realm: The realm we're connecting to, if NULL we use our default realm.
876 ****************************************************************************/
878 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
879 const char *pass, const char *user_domain,
880 const char * dest_realm)
882 char *principal = NULL;
883 char *OIDs[ASN1_MAX_OIDS];
884 int i;
885 DATA_BLOB blob;
886 const char *p = NULL;
887 char *account = NULL;
889 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
891 /* the server might not even do spnego */
892 if (cli->secblob.length <= 16) {
893 DEBUG(3,("server didn't supply a full spnego negprot\n"));
894 goto ntlmssp;
897 #if 0
898 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
899 #endif
901 /* there is 16 bytes of GUID before the real spnego packet starts */
902 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
904 /* The server sent us the first part of the SPNEGO exchange in the
905 * negprot reply. It is WRONG to depend on the principal sent in the
906 * negprot reply, but right now we do it. If we don't receive one,
907 * we try to best guess, then fall back to NTLM. */
908 if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
909 data_blob_free(&blob);
910 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
912 data_blob_free(&blob);
914 /* make sure the server understands kerberos */
915 for (i=0;OIDs[i];i++) {
916 DEBUG(3,("got OID=%s\n", OIDs[i]));
917 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
918 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
919 cli->got_kerberos_mechanism = True;
921 talloc_free(OIDs[i]);
924 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
926 fstrcpy(cli->user_name, user);
928 #ifdef HAVE_KRB5
929 /* If password is set we reauthenticate to kerberos server
930 * and do not store results */
932 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
933 ADS_STATUS rc;
935 if (pass && *pass) {
936 int ret;
938 use_in_memory_ccache();
939 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
941 if (ret){
942 TALLOC_FREE(principal);
943 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
944 if (cli->fallback_after_kerberos)
945 goto ntlmssp;
946 return ADS_ERROR_KRB5(ret);
950 /* If we get a bad principal, try to guess it if
951 we have a valid host NetBIOS name.
953 if (strequal(principal, ADS_IGNORE_PRINCIPAL)) {
954 TALLOC_FREE(principal);
957 if (principal == NULL &&
958 !is_ipaddress(cli->desthost) &&
959 !strequal(STAR_SMBSERVER,
960 cli->desthost)) {
961 char *realm = NULL;
962 char *machine = NULL;
963 char *host = NULL;
964 DEBUG(3,("cli_session_setup_spnego: got a "
965 "bad server principal, trying to guess ...\n"));
967 host = strchr_m(cli->desthost, '.');
968 if (host) {
969 machine = SMB_STRNDUP(cli->desthost,
970 host - cli->desthost);
971 } else {
972 machine = SMB_STRDUP(cli->desthost);
974 if (machine == NULL) {
975 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
978 if (dest_realm) {
979 realm = SMB_STRDUP(dest_realm);
980 strupper_m(realm);
981 } else {
982 realm = kerberos_get_default_realm_from_ccache();
984 if (realm && *realm) {
985 principal = talloc_asprintf(NULL, "%s$@%s",
986 machine, realm);
987 if (!principal) {
988 SAFE_FREE(machine);
989 SAFE_FREE(realm);
990 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
992 DEBUG(3,("cli_session_setup_spnego: guessed "
993 "server principal=%s\n",
994 principal ? principal : "<null>"));
996 SAFE_FREE(machine);
997 SAFE_FREE(realm);
1000 if (principal) {
1001 rc = cli_session_setup_kerberos(cli, principal,
1002 dest_realm);
1003 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1004 TALLOC_FREE(principal);
1005 return rc;
1009 #endif
1011 TALLOC_FREE(principal);
1013 ntlmssp:
1015 account = talloc_strdup(talloc_tos(), user);
1016 if (!account) {
1017 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1020 /* when falling back to ntlmssp while authenticating with a machine
1021 * account strip off the realm - gd */
1023 if ((p = strchr_m(user, '@')) != NULL) {
1024 account[PTR_DIFF(p,user)] = '\0';
1027 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1030 /****************************************************************************
1031 Send a session setup. The username and workgroup is in UNIX character
1032 format and must be converted to DOS codepage format before sending. If the
1033 password is in plaintext, the same should be done.
1034 ****************************************************************************/
1036 NTSTATUS cli_session_setup(struct cli_state *cli,
1037 const char *user,
1038 const char *pass, int passlen,
1039 const char *ntpass, int ntpasslen,
1040 const char *workgroup)
1042 char *p;
1043 fstring user2;
1045 if (user) {
1046 fstrcpy(user2, user);
1047 } else {
1048 user2[0] ='\0';
1051 if (!workgroup) {
1052 workgroup = "";
1055 /* allow for workgroups as part of the username */
1056 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1057 (p=strchr_m(user2,*lp_winbind_separator()))) {
1058 *p = 0;
1059 user = p+1;
1060 workgroup = user2;
1063 if (cli->protocol < PROTOCOL_LANMAN1) {
1064 return NT_STATUS_OK;
1067 /* now work out what sort of session setup we are going to
1068 do. I have split this into separate functions to make the
1069 flow a bit easier to understand (tridge) */
1071 /* if its an older server then we have to use the older request format */
1073 if (cli->protocol < PROTOCOL_NT1) {
1074 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1075 DEBUG(1, ("Server requested LM password but 'client lanman auth'"
1076 " is disabled\n"));
1077 return NT_STATUS_ACCESS_DENIED;
1080 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1081 !lp_client_plaintext_auth() && (*pass)) {
1082 DEBUG(1, ("Server requested plaintext password but "
1083 "'client plaintext auth' is disabled\n"));
1084 return NT_STATUS_ACCESS_DENIED;
1087 return cli_session_setup_lanman2(cli, user, pass, passlen,
1088 workgroup);
1091 /* if no user is supplied then we have to do an anonymous connection.
1092 passwords are ignored */
1094 if (!user || !*user)
1095 return cli_session_setup_guest(cli);
1097 /* if the server is share level then send a plaintext null
1098 password at this point. The password is sent in the tree
1099 connect */
1101 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
1102 return cli_session_setup_plaintext(cli, user, "", workgroup);
1104 /* if the server doesn't support encryption then we have to use
1105 plaintext. The second password is ignored */
1107 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1108 if (!lp_client_plaintext_auth() && (*pass)) {
1109 DEBUG(1, ("Server requested plaintext password but "
1110 "'client plaintext auth' is disabled\n"));
1111 return NT_STATUS_ACCESS_DENIED;
1113 return cli_session_setup_plaintext(cli, user, pass, workgroup);
1116 /* if the server supports extended security then use SPNEGO */
1118 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
1119 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
1120 workgroup, NULL);
1121 if (!ADS_ERR_OK(status)) {
1122 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1123 return ads_ntstatus(status);
1125 } else {
1126 NTSTATUS status;
1128 /* otherwise do a NT1 style session setup */
1129 status = cli_session_setup_nt1(cli, user, pass, passlen,
1130 ntpass, ntpasslen, workgroup);
1131 if (!NT_STATUS_IS_OK(status)) {
1132 DEBUG(3,("cli_session_setup: NT1 session setup "
1133 "failed: %s\n", nt_errstr(status)));
1134 return status;
1138 if (strstr(cli->server_type, "Samba")) {
1139 cli->is_samba = True;
1142 return NT_STATUS_OK;
1145 /****************************************************************************
1146 Send a uloggoff.
1147 *****************************************************************************/
1149 bool cli_ulogoff(struct cli_state *cli)
1151 memset(cli->outbuf,'\0',smb_size);
1152 cli_set_message(cli->outbuf,2,0,True);
1153 SCVAL(cli->outbuf,smb_com,SMBulogoffX);
1154 cli_setup_packet(cli);
1155 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1156 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1158 cli_send_smb(cli);
1159 if (!cli_receive_smb(cli))
1160 return False;
1162 if (cli_is_error(cli)) {
1163 return False;
1166 cli->cnum = -1;
1167 return True;
1170 /****************************************************************************
1171 Send a tconX.
1172 ****************************************************************************/
1174 struct async_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
1175 struct event_context *ev,
1176 struct cli_state *cli,
1177 const char *share, const char *dev,
1178 const char *pass, int passlen)
1180 fstring pword;
1181 char *tmp = NULL;
1182 struct async_req *result;
1183 uint16_t vwv[4];
1184 uint8_t *bytes;
1186 fstrcpy(cli->share, share);
1188 /* in user level security don't send a password now */
1189 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1190 passlen = 1;
1191 pass = "";
1192 } else if (pass == NULL) {
1193 DEBUG(1, ("Server not using user level security and no "
1194 "password supplied.\n"));
1195 goto access_denied;
1198 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1199 *pass && passlen != 24) {
1200 if (!lp_client_lanman_auth()) {
1201 DEBUG(1, ("Server requested LANMAN password "
1202 "(share-level security) but "
1203 "'client lanman auth' is disabled\n"));
1204 goto access_denied;
1208 * Non-encrypted passwords - convert to DOS codepage before
1209 * encryption.
1211 passlen = 24;
1212 SMBencrypt(pass, cli->secblob.data, (uchar *)pword);
1213 } else {
1214 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1215 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1216 == 0) {
1217 if (!lp_client_plaintext_auth() && (*pass)) {
1218 DEBUG(1, ("Server requested plaintext "
1219 "password but 'client plaintext "
1220 "auth' is disabled\n"));
1221 goto access_denied;
1225 * Non-encrypted passwords - convert to DOS codepage
1226 * before using.
1228 passlen = clistr_push(cli, pword, pass, sizeof(pword),
1229 STR_TERMINATE);
1230 if (passlen == -1) {
1231 DEBUG(1, ("clistr_push(pword) failed\n"));
1232 goto access_denied;
1234 } else {
1235 if (passlen) {
1236 memcpy(pword, pass, passlen);
1241 SCVAL(vwv+0, 0, 0xFF);
1242 SCVAL(vwv+0, 1, 0);
1243 SSVAL(vwv+1, 0, 0);
1244 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
1245 SSVAL(vwv+3, 0, passlen);
1247 if (passlen) {
1248 bytes = (uint8_t *)talloc_memdup(talloc_tos(), pword, passlen);
1249 } else {
1250 bytes = talloc_array(talloc_tos(), uint8_t, 0);
1254 * Add the sharename
1256 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1257 cli->desthost, share);
1258 if (tmp == NULL) {
1259 TALLOC_FREE(bytes);
1260 return NULL;
1262 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
1263 NULL);
1264 TALLOC_FREE(tmp);
1267 * Add the devicetype
1269 tmp = talloc_strdup_upper(talloc_tos(), dev);
1270 if (tmp == NULL) {
1271 TALLOC_FREE(bytes);
1272 return NULL;
1274 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
1275 TALLOC_FREE(tmp);
1277 if (bytes == NULL) {
1278 return NULL;
1281 result = cli_request_send(mem_ctx, ev, cli, SMBtconX, 0,
1282 4, vwv, 0, talloc_get_size(bytes), bytes);
1283 TALLOC_FREE(bytes);
1284 return result;
1286 access_denied:
1287 result = async_req_new(mem_ctx);
1288 if (async_post_ntstatus(result, ev, NT_STATUS_ACCESS_DENIED)) {
1289 return result;
1291 TALLOC_FREE(result);
1292 return NULL;
1295 NTSTATUS cli_tcon_andx_recv(struct async_req *req)
1297 struct cli_request *cli_req = talloc_get_type_abort(
1298 req->private_data, struct cli_request);
1299 struct cli_state *cli = cli_req->cli;
1300 uint8_t wct;
1301 uint16_t *vwv;
1302 uint16_t num_bytes;
1303 uint8_t *bytes;
1304 NTSTATUS status;
1306 if (async_req_is_nterror(req, &status)) {
1307 return status;
1310 status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
1311 if (!NT_STATUS_IS_OK(status)) {
1312 return status;
1315 clistr_pull(cli_req->inbuf, cli->dev, bytes, sizeof(fstring),
1316 num_bytes, STR_TERMINATE|STR_ASCII);
1318 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
1319 /* almost certainly win95 - enable bug fixes */
1320 cli->win95 = True;
1324 * Make sure that we have the optional support 16-bit field. WCT > 2.
1325 * Avoids issues when connecting to Win9x boxes sharing files
1328 cli->dfsroot = false;
1330 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
1331 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
1334 cli->cnum = SVAL(cli_req->inbuf,smb_tid);
1335 return NT_STATUS_OK;
1338 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
1339 const char *dev, const char *pass, int passlen)
1341 TALLOC_CTX *frame = talloc_stackframe();
1342 struct event_context *ev;
1343 struct async_req *req;
1344 NTSTATUS status;
1346 if (cli->fd_event != NULL) {
1348 * Can't use sync call while an async call is in flight
1350 status = NT_STATUS_INVALID_PARAMETER;
1351 goto fail;
1354 ev = event_context_init(frame);
1355 if (ev == NULL) {
1356 status = NT_STATUS_NO_MEMORY;
1357 goto fail;
1360 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
1361 if (req == NULL) {
1362 status = NT_STATUS_NO_MEMORY;
1363 goto fail;
1366 while (req->state < ASYNC_REQ_DONE) {
1367 event_loop_once(ev);
1370 status = cli_tcon_andx_recv(req);
1371 fail:
1372 TALLOC_FREE(frame);
1373 return status;
1376 /****************************************************************************
1377 Send a tree disconnect.
1378 ****************************************************************************/
1380 bool cli_tdis(struct cli_state *cli)
1382 memset(cli->outbuf,'\0',smb_size);
1383 cli_set_message(cli->outbuf,0,0,True);
1384 SCVAL(cli->outbuf,smb_com,SMBtdis);
1385 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1386 cli_setup_packet(cli);
1388 cli_send_smb(cli);
1389 if (!cli_receive_smb(cli))
1390 return False;
1392 if (cli_is_error(cli)) {
1393 return False;
1396 cli->cnum = -1;
1397 return True;
1400 /****************************************************************************
1401 Send a negprot command.
1402 ****************************************************************************/
1404 void cli_negprot_sendsync(struct cli_state *cli)
1406 char *p;
1407 int numprots;
1409 if (cli->protocol < PROTOCOL_NT1)
1410 cli->use_spnego = False;
1412 memset(cli->outbuf,'\0',smb_size);
1414 /* setup the protocol strings */
1415 cli_set_message(cli->outbuf,0,0,True);
1417 p = smb_buf(cli->outbuf);
1418 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1419 if (prots[numprots].prot > cli->protocol) {
1420 break;
1422 *p++ = 2;
1423 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1426 SCVAL(cli->outbuf,smb_com,SMBnegprot);
1427 cli_setup_bcc(cli, p);
1428 cli_setup_packet(cli);
1430 SCVAL(smb_buf(cli->outbuf),0,2);
1432 cli_send_smb(cli);
1435 /****************************************************************************
1436 Send a negprot command.
1437 ****************************************************************************/
1439 struct async_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
1440 struct event_context *ev,
1441 struct cli_state *cli)
1443 struct async_req *result;
1444 uint8_t *bytes = NULL;
1445 int numprots;
1447 if (cli->protocol < PROTOCOL_NT1)
1448 cli->use_spnego = False;
1450 /* setup the protocol strings */
1451 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1452 uint8_t c = 2;
1453 if (prots[numprots].prot > cli->protocol) {
1454 break;
1456 bytes = (uint8_t *)talloc_append_blob(
1457 talloc_tos(), bytes, data_blob_const(&c, sizeof(c)));
1458 if (bytes == NULL) {
1459 return NULL;
1461 bytes = smb_bytes_push_str(bytes, false,
1462 prots[numprots].name,
1463 strlen(prots[numprots].name)+1,
1464 NULL);
1465 if (bytes == NULL) {
1466 return NULL;
1470 result = cli_request_send(mem_ctx, ev, cli, SMBnegprot, 0, 0, NULL, 0,
1471 talloc_get_size(bytes), bytes);
1472 TALLOC_FREE(bytes);
1473 return result;
1476 NTSTATUS cli_negprot_recv(struct async_req *req)
1478 struct cli_request *cli_req = talloc_get_type_abort(
1479 req->private_data, struct cli_request);
1480 struct cli_state *cli = cli_req->cli;
1481 uint8_t wct;
1482 uint16_t *vwv;
1483 uint16_t num_bytes;
1484 uint8_t *bytes;
1485 NTSTATUS status;
1486 uint16_t protnum;
1488 if (async_req_is_nterror(req, &status)) {
1489 return status;
1492 status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
1493 if (!NT_STATUS_IS_OK(status)) {
1494 return status;
1497 protnum = SVAL(vwv, 0);
1499 if ((protnum >= ARRAY_SIZE(prots))
1500 || (prots[protnum].prot > cli_req->cli->protocol)) {
1501 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1504 cli->protocol = prots[protnum].prot;
1506 if ((cli->protocol < PROTOCOL_NT1) && cli->sign_info.mandatory_signing) {
1507 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1508 return NT_STATUS_ACCESS_DENIED;
1511 if (cli->protocol >= PROTOCOL_NT1) {
1512 struct timespec ts;
1513 /* NT protocol */
1514 cli->sec_mode = CVAL(vwv + 1, 0);
1515 cli->max_mux = SVAL(vwv + 1, 1);
1516 cli->max_xmit = IVAL(vwv + 3, 1);
1517 cli->sesskey = IVAL(vwv + 7, 1);
1518 cli->serverzone = SVALS(vwv + 15, 1);
1519 cli->serverzone *= 60;
1520 /* this time arrives in real GMT */
1521 ts = interpret_long_date(((char *)(vwv+11))+1);
1522 cli->servertime = ts.tv_sec;
1523 cli->secblob = data_blob(bytes, num_bytes);
1524 cli->capabilities = IVAL(vwv + 9, 1);
1525 if (cli->capabilities & CAP_RAW_MODE) {
1526 cli->readbraw_supported = True;
1527 cli->writebraw_supported = True;
1529 /* work out if they sent us a workgroup */
1530 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1531 smb_buflen(cli->inbuf) > 8) {
1532 clistr_pull(cli->inbuf, cli->server_domain,
1533 bytes+8, sizeof(cli->server_domain),
1534 num_bytes-8,
1535 STR_UNICODE|STR_NOALIGN);
1539 * As signing is slow we only turn it on if either the client or
1540 * the server require it. JRA.
1543 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
1544 /* Fail if server says signing is mandatory and we don't want to support it. */
1545 if (!cli->sign_info.allow_smb_signing) {
1546 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1547 return NT_STATUS_ACCESS_DENIED;
1549 cli->sign_info.negotiated_smb_signing = True;
1550 cli->sign_info.mandatory_signing = True;
1551 } else if (cli->sign_info.mandatory_signing && cli->sign_info.allow_smb_signing) {
1552 /* Fail if client says signing is mandatory and the server doesn't support it. */
1553 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
1554 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1555 return NT_STATUS_ACCESS_DENIED;
1557 cli->sign_info.negotiated_smb_signing = True;
1558 cli->sign_info.mandatory_signing = True;
1559 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
1560 cli->sign_info.negotiated_smb_signing = True;
1563 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
1564 SAFE_FREE(cli->outbuf);
1565 SAFE_FREE(cli->inbuf);
1566 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1567 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1568 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
1571 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1572 cli->use_spnego = False;
1573 cli->sec_mode = SVAL(vwv + 1, 0);
1574 cli->max_xmit = SVAL(vwv + 2, 0);
1575 cli->max_mux = SVAL(vwv + 3, 0);
1576 cli->sesskey = IVAL(vwv + 6, 0);
1577 cli->serverzone = SVALS(vwv + 10, 0);
1578 cli->serverzone *= 60;
1579 /* this time is converted to GMT by make_unix_date */
1580 cli->servertime = cli_make_unix_date(
1581 cli, (char *)(vwv + 8));
1582 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
1583 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
1584 cli->secblob = data_blob(bytes, num_bytes);
1585 } else {
1586 /* the old core protocol */
1587 cli->use_spnego = False;
1588 cli->sec_mode = 0;
1589 cli->serverzone = get_time_zone(time(NULL));
1592 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1594 /* a way to force ascii SMB */
1595 if (getenv("CLI_FORCE_ASCII"))
1596 cli->capabilities &= ~CAP_UNICODE;
1598 return NT_STATUS_OK;
1601 NTSTATUS cli_negprot(struct cli_state *cli)
1603 TALLOC_CTX *frame = talloc_stackframe();
1604 struct event_context *ev;
1605 struct async_req *req;
1606 NTSTATUS status = NT_STATUS_NO_MEMORY;
1608 if (cli->fd_event != NULL) {
1610 * Can't use sync call while an async call is in flight
1612 cli_set_error(cli, NT_STATUS_INVALID_PARAMETER);
1613 goto fail;
1616 ev = event_context_init(frame);
1617 if (ev == NULL) {
1618 goto fail;
1621 req = cli_negprot_send(frame, ev, cli);
1622 if (req == NULL) {
1623 goto fail;
1626 while (req->state < ASYNC_REQ_DONE) {
1627 event_loop_once(ev);
1630 status = cli_negprot_recv(req);
1631 fail:
1632 TALLOC_FREE(frame);
1633 return status;
1636 /****************************************************************************
1637 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1638 ****************************************************************************/
1640 bool cli_session_request(struct cli_state *cli,
1641 struct nmb_name *calling, struct nmb_name *called)
1643 char *p;
1644 int len = 4;
1646 /* 445 doesn't have session request */
1647 if (cli->port == 445)
1648 return True;
1650 memcpy(&(cli->calling), calling, sizeof(*calling));
1651 memcpy(&(cli->called ), called , sizeof(*called ));
1653 /* put in the destination name */
1654 p = cli->outbuf+len;
1655 name_mangle(cli->called .name, p, cli->called .name_type);
1656 len += name_len(p);
1658 /* and my name */
1659 p = cli->outbuf+len;
1660 name_mangle(cli->calling.name, p, cli->calling.name_type);
1661 len += name_len(p);
1663 /* send a session request (RFC 1002) */
1664 /* setup the packet length
1665 * Remove four bytes from the length count, since the length
1666 * field in the NBT Session Service header counts the number
1667 * of bytes which follow. The cli_send_smb() function knows
1668 * about this and accounts for those four bytes.
1669 * CRH.
1671 len -= 4;
1672 _smb_setlen(cli->outbuf,len);
1673 SCVAL(cli->outbuf,0,0x81);
1675 cli_send_smb(cli);
1676 DEBUG(5,("Sent session request\n"));
1678 if (!cli_receive_smb(cli))
1679 return False;
1681 if (CVAL(cli->inbuf,0) == 0x84) {
1682 /* C. Hoch 9/14/95 Start */
1683 /* For information, here is the response structure.
1684 * We do the byte-twiddling to for portability.
1685 struct RetargetResponse{
1686 unsigned char type;
1687 unsigned char flags;
1688 int16 length;
1689 int32 ip_addr;
1690 int16 port;
1693 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1694 struct in_addr dest_ip;
1695 NTSTATUS status;
1697 /* SESSION RETARGET */
1698 putip((char *)&dest_ip,cli->inbuf+4);
1699 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
1701 status = open_socket_out(&cli->dest_ss, port,
1702 LONG_CONNECT_TIMEOUT, &cli->fd);
1703 if (!NT_STATUS_IS_OK(status)) {
1704 return False;
1707 DEBUG(3,("Retargeted\n"));
1709 set_socket_options(cli->fd, lp_socket_options());
1711 /* Try again */
1713 static int depth;
1714 bool ret;
1715 if (depth > 4) {
1716 DEBUG(0,("Retarget recursion - failing\n"));
1717 return False;
1719 depth++;
1720 ret = cli_session_request(cli, calling, called);
1721 depth--;
1722 return ret;
1724 } /* C. Hoch 9/14/95 End */
1726 if (CVAL(cli->inbuf,0) != 0x82) {
1727 /* This is the wrong place to put the error... JRA. */
1728 cli->rap_error = CVAL(cli->inbuf,4);
1729 return False;
1731 return(True);
1734 static void smb_sock_connected(struct async_req *req)
1736 int *pfd = (int *)req->async.priv;
1737 int fd;
1738 NTSTATUS status;
1740 status = open_socket_out_defer_recv(req, &fd);
1741 if (NT_STATUS_IS_OK(status)) {
1742 *pfd = fd;
1746 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
1747 uint16_t *port, int timeout, int *pfd)
1749 struct event_context *ev;
1750 struct async_req *r139, *r445;
1751 int fd139 = -1;
1752 int fd445 = -1;
1753 NTSTATUS status;
1755 if (*port != 0) {
1756 return open_socket_out(pss, *port, timeout, pfd);
1759 ev = event_context_init(talloc_tos());
1760 if (ev == NULL) {
1761 return NT_STATUS_NO_MEMORY;
1764 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
1765 pss, 445, timeout);
1766 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
1767 pss, 139, timeout);
1768 if ((r445 == NULL) || (r139 == NULL)) {
1769 status = NT_STATUS_NO_MEMORY;
1770 goto done;
1772 r445->async.fn = smb_sock_connected;
1773 r445->async.priv = &fd445;
1774 r139->async.fn = smb_sock_connected;
1775 r139->async.priv = &fd139;
1777 while ((fd139 == -1) && (r139->state < ASYNC_REQ_DONE)
1778 && (fd445 == -1) && (r445->state < ASYNC_REQ_DONE)) {
1779 event_loop_once(ev);
1782 if ((fd139 != -1) && (fd445 != -1)) {
1783 close(fd139);
1784 fd139 = -1;
1787 if (fd445 != -1) {
1788 *port = 445;
1789 *pfd = fd445;
1790 status = NT_STATUS_OK;
1791 goto done;
1793 if (fd139 != -1) {
1794 *port = 139;
1795 *pfd = fd139;
1796 status = NT_STATUS_OK;
1797 goto done;
1800 status = open_socket_out_defer_recv(r445, &fd445);
1801 done:
1802 TALLOC_FREE(ev);
1803 return status;
1806 /****************************************************************************
1807 Open the client sockets.
1808 ****************************************************************************/
1810 NTSTATUS cli_connect(struct cli_state *cli,
1811 const char *host,
1812 struct sockaddr_storage *dest_ss)
1815 int name_type = 0x20;
1816 TALLOC_CTX *frame = talloc_stackframe();
1817 unsigned int num_addrs = 0;
1818 unsigned int i = 0;
1819 struct sockaddr_storage *ss_arr = NULL;
1820 char *p = NULL;
1822 /* reasonable default hostname */
1823 if (!host) {
1824 host = STAR_SMBSERVER;
1827 fstrcpy(cli->desthost, host);
1829 /* allow hostnames of the form NAME#xx and do a netbios lookup */
1830 if ((p = strchr(cli->desthost, '#'))) {
1831 name_type = strtol(p+1, NULL, 16);
1832 *p = 0;
1835 if (!dest_ss || is_zero_addr((struct sockaddr *)dest_ss)) {
1836 NTSTATUS status =resolve_name_list(frame,
1837 cli->desthost,
1838 name_type,
1839 &ss_arr,
1840 &num_addrs);
1841 if (!NT_STATUS_IS_OK(status)) {
1842 TALLOC_FREE(frame);
1843 return NT_STATUS_BAD_NETWORK_NAME;
1845 } else {
1846 num_addrs = 1;
1847 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
1848 if (!ss_arr) {
1849 TALLOC_FREE(frame);
1850 return NT_STATUS_NO_MEMORY;
1852 *ss_arr = *dest_ss;
1855 for (i = 0; i < num_addrs; i++) {
1856 cli->dest_ss = ss_arr[i];
1857 if (getenv("LIBSMB_PROG")) {
1858 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
1859 } else {
1860 uint16_t port = cli->port;
1861 NTSTATUS status;
1862 status = open_smb_socket(&cli->dest_ss, &port,
1863 cli->timeout, &cli->fd);
1864 if (NT_STATUS_IS_OK(status)) {
1865 cli->port = port;
1868 if (cli->fd == -1) {
1869 char addr[INET6_ADDRSTRLEN];
1870 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
1871 DEBUG(2,("Error connecting to %s (%s)\n",
1872 dest_ss?addr:host,strerror(errno)));
1873 } else {
1874 /* Exit from loop on first connection. */
1875 break;
1879 if (cli->fd == -1) {
1880 TALLOC_FREE(frame);
1881 return map_nt_error_from_unix(errno);
1884 if (dest_ss) {
1885 *dest_ss = cli->dest_ss;
1888 set_socket_options(cli->fd, lp_socket_options());
1890 TALLOC_FREE(frame);
1891 return NT_STATUS_OK;
1895 establishes a connection to after the negprot.
1896 @param output_cli A fully initialised cli structure, non-null only on success
1897 @param dest_host The netbios name of the remote host
1898 @param dest_ss (optional) The the destination IP, NULL for name based lookup
1899 @param port (optional) The destination port (0 for default)
1900 @param retry bool. Did this connection fail with a retryable error ?
1903 NTSTATUS cli_start_connection(struct cli_state **output_cli,
1904 const char *my_name,
1905 const char *dest_host,
1906 struct sockaddr_storage *dest_ss, int port,
1907 int signing_state, int flags,
1908 bool *retry)
1910 NTSTATUS nt_status;
1911 struct nmb_name calling;
1912 struct nmb_name called;
1913 struct cli_state *cli;
1914 struct sockaddr_storage ss;
1916 if (retry)
1917 *retry = False;
1919 if (!my_name)
1920 my_name = global_myname();
1922 if (!(cli = cli_initialise())) {
1923 return NT_STATUS_NO_MEMORY;
1926 make_nmb_name(&calling, my_name, 0x0);
1927 make_nmb_name(&called , dest_host, 0x20);
1929 cli_set_port(cli, port);
1930 cli_set_timeout(cli, 10000); /* 10 seconds. */
1932 if (dest_ss) {
1933 ss = *dest_ss;
1934 } else {
1935 zero_sockaddr(&ss);
1938 again:
1940 DEBUG(3,("Connecting to host=%s\n", dest_host));
1942 nt_status = cli_connect(cli, dest_host, &ss);
1943 if (!NT_STATUS_IS_OK(nt_status)) {
1944 char addr[INET6_ADDRSTRLEN];
1945 print_sockaddr(addr, sizeof(addr), &ss);
1946 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
1947 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
1948 cli_shutdown(cli);
1949 return nt_status;
1952 if (retry)
1953 *retry = True;
1955 if (!cli_session_request(cli, &calling, &called)) {
1956 char *p;
1957 DEBUG(1,("session request to %s failed (%s)\n",
1958 called.name, cli_errstr(cli)));
1959 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
1960 *p = 0;
1961 goto again;
1963 if (strcmp(called.name, STAR_SMBSERVER)) {
1964 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
1965 goto again;
1967 return NT_STATUS_BAD_NETWORK_NAME;
1970 cli_setup_signing_state(cli, signing_state);
1972 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
1973 cli->use_spnego = False;
1974 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
1975 cli->use_kerberos = True;
1977 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
1978 cli->use_kerberos) {
1979 cli->fallback_after_kerberos = true;
1982 nt_status = cli_negprot(cli);
1983 if (!NT_STATUS_IS_OK(nt_status)) {
1984 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
1985 cli_shutdown(cli);
1986 return nt_status;
1989 *output_cli = cli;
1990 return NT_STATUS_OK;
1995 establishes a connection right up to doing tconX, password specified.
1996 @param output_cli A fully initialised cli structure, non-null only on success
1997 @param dest_host The netbios name of the remote host
1998 @param dest_ip (optional) The the destination IP, NULL for name based lookup
1999 @param port (optional) The destination port (0 for default)
2000 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2001 @param service_type The 'type' of serivice.
2002 @param user Username, unix string
2003 @param domain User's domain
2004 @param password User's password, unencrypted unix string.
2005 @param retry bool. Did this connection fail with a retryable error ?
2008 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2009 const char *my_name,
2010 const char *dest_host,
2011 struct sockaddr_storage *dest_ss, int port,
2012 const char *service, const char *service_type,
2013 const char *user, const char *domain,
2014 const char *password, int flags,
2015 int signing_state,
2016 bool *retry)
2018 NTSTATUS nt_status;
2019 struct cli_state *cli = NULL;
2020 int pw_len = password ? strlen(password)+1 : 0;
2022 *output_cli = NULL;
2024 if (password == NULL) {
2025 password = "";
2028 nt_status = cli_start_connection(&cli, my_name, dest_host,
2029 dest_ss, port, signing_state,
2030 flags, retry);
2032 if (!NT_STATUS_IS_OK(nt_status)) {
2033 return nt_status;
2036 nt_status = cli_session_setup(cli, user, password, pw_len, password,
2037 pw_len, domain);
2038 if (!NT_STATUS_IS_OK(nt_status)) {
2040 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2041 DEBUG(1,("failed session setup with %s\n",
2042 nt_errstr(nt_status)));
2043 cli_shutdown(cli);
2044 return nt_status;
2047 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2048 if (!NT_STATUS_IS_OK(nt_status)) {
2049 DEBUG(1,("anonymous failed session setup with %s\n",
2050 nt_errstr(nt_status)));
2051 cli_shutdown(cli);
2052 return nt_status;
2056 if (service) {
2057 nt_status = cli_tcon_andx(cli, service, service_type, password,
2058 pw_len);
2059 if (!NT_STATUS_IS_OK(nt_status)) {
2060 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2061 cli_shutdown(cli);
2062 if (NT_STATUS_IS_OK(nt_status)) {
2063 nt_status = NT_STATUS_UNSUCCESSFUL;
2065 return nt_status;
2069 cli_init_creds(cli, user, domain, password);
2071 *output_cli = cli;
2072 return NT_STATUS_OK;
2075 /****************************************************************************
2076 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2077 ****************************************************************************/
2079 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
2080 struct sockaddr_storage *pdest_ss)
2082 struct nmb_name calling, called;
2084 make_nmb_name(&calling, srchost, 0x0);
2087 * If the called name is an IP address
2088 * then use *SMBSERVER immediately.
2091 if(is_ipaddress(desthost)) {
2092 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
2093 } else {
2094 make_nmb_name(&called, desthost, 0x20);
2097 if (!cli_session_request(*ppcli, &calling, &called)) {
2098 NTSTATUS status;
2099 struct nmb_name smbservername;
2101 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
2104 * If the name wasn't *SMBSERVER then
2105 * try with *SMBSERVER if the first name fails.
2108 if (nmb_name_equal(&called, &smbservername)) {
2111 * The name used was *SMBSERVER, don't bother with another name.
2114 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2115 with error %s.\n", desthost, cli_errstr(*ppcli) ));
2116 return False;
2119 /* Try again... */
2120 cli_shutdown(*ppcli);
2122 *ppcli = cli_initialise();
2123 if (!*ppcli) {
2124 /* Out of memory... */
2125 return False;
2128 status = cli_connect(*ppcli, desthost, pdest_ss);
2129 if (!NT_STATUS_IS_OK(status) ||
2130 !cli_session_request(*ppcli, &calling, &smbservername)) {
2131 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2132 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
2133 return False;
2137 return True;
2140 /****************************************************************************
2141 Send an old style tcon.
2142 ****************************************************************************/
2143 NTSTATUS cli_raw_tcon(struct cli_state *cli,
2144 const char *service, const char *pass, const char *dev,
2145 uint16 *max_xmit, uint16 *tid)
2147 char *p;
2149 if (!lp_client_plaintext_auth() && (*pass)) {
2150 DEBUG(1, ("Server requested plaintext password but 'client "
2151 "plaintext auth' is disabled\n"));
2152 return NT_STATUS_ACCESS_DENIED;
2155 memset(cli->outbuf,'\0',smb_size);
2156 memset(cli->inbuf,'\0',smb_size);
2158 cli_set_message(cli->outbuf, 0, 0, True);
2159 SCVAL(cli->outbuf,smb_com,SMBtcon);
2160 cli_setup_packet(cli);
2162 p = smb_buf(cli->outbuf);
2163 *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
2164 *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
2165 *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
2167 cli_setup_bcc(cli, p);
2169 cli_send_smb(cli);
2170 if (!cli_receive_smb(cli)) {
2171 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2174 if (cli_is_error(cli)) {
2175 return cli_nt_error(cli);
2178 *max_xmit = SVAL(cli->inbuf, smb_vwv0);
2179 *tid = SVAL(cli->inbuf, smb_vwv1);
2181 return NT_STATUS_OK;
2184 /* Return a cli_state pointing at the IPC$ share for the given server */
2186 struct cli_state *get_ipc_connect(char *server,
2187 struct sockaddr_storage *server_ss,
2188 const struct user_auth_info *user_info)
2190 struct cli_state *cli;
2191 NTSTATUS nt_status;
2192 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2194 if (user_info->use_kerberos) {
2195 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2198 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
2199 user_info->username ? user_info->username : "",
2200 lp_workgroup(),
2201 user_info->password ? user_info->password : "",
2202 flags,
2203 Undefined, NULL);
2205 if (NT_STATUS_IS_OK(nt_status)) {
2206 return cli;
2207 } else if (is_ipaddress(server)) {
2208 /* windows 9* needs a correct NMB name for connections */
2209 fstring remote_name;
2211 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2212 cli = get_ipc_connect(remote_name, server_ss, user_info);
2213 if (cli)
2214 return cli;
2217 return NULL;
2221 * Given the IP address of a master browser on the network, return its
2222 * workgroup and connect to it.
2224 * This function is provided to allow additional processing beyond what
2225 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2226 * browsers and obtain each master browsers' list of domains (in case the
2227 * first master browser is recently on the network and has not yet
2228 * synchronized with other master browsers and therefore does not yet have the
2229 * entire network browse list)
2232 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2233 struct ip_service *mb_ip,
2234 const struct user_auth_info *user_info,
2235 char **pp_workgroup_out)
2237 char addr[INET6_ADDRSTRLEN];
2238 fstring name;
2239 struct cli_state *cli;
2240 struct sockaddr_storage server_ss;
2242 *pp_workgroup_out = NULL;
2244 print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2245 DEBUG(99, ("Looking up name of master browser %s\n",
2246 addr));
2249 * Do a name status query to find out the name of the master browser.
2250 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2251 * master browser will not respond to a wildcard query (or, at least,
2252 * an NT4 server acting as the domain master browser will not).
2254 * We might be able to use ONLY the query on MSBROWSE, but that's not
2255 * yet been tested with all Windows versions, so until it is, leave
2256 * the original wildcard query as the first choice and fall back to
2257 * MSBROWSE if the wildcard query fails.
2259 if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2260 !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2262 DEBUG(99, ("Could not retrieve name status for %s\n",
2263 addr));
2264 return NULL;
2267 if (!find_master_ip(name, &server_ss)) {
2268 DEBUG(99, ("Could not find master ip for %s\n", name));
2269 return NULL;
2272 *pp_workgroup_out = talloc_strdup(ctx, name);
2274 DEBUG(4, ("found master browser %s, %s\n", name, addr));
2276 print_sockaddr(addr, sizeof(addr), &server_ss);
2277 cli = get_ipc_connect(addr, &server_ss, user_info);
2279 return cli;
2283 * Return the IP address and workgroup of a master browser on the network, and
2284 * connect to it.
2287 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2288 const struct user_auth_info *user_info,
2289 char **pp_workgroup_out)
2291 struct ip_service *ip_list;
2292 struct cli_state *cli;
2293 int i, count;
2295 *pp_workgroup_out = NULL;
2297 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2299 /* Go looking for workgroups by broadcasting on the local network */
2301 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2302 &count))) {
2303 DEBUG(99, ("No master browsers responded\n"));
2304 return False;
2307 for (i = 0; i < count; i++) {
2308 char addr[INET6_ADDRSTRLEN];
2309 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2310 DEBUG(99, ("Found master browser %s\n", addr));
2312 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2313 user_info, pp_workgroup_out);
2314 if (cli)
2315 return(cli);
2318 return NULL;