s3:docs: remove documentation of "idmap read only" which was removed.
[Samba.git] / source3 / libsmb / cliconnect.c
blob564cf8b3c7b7c96eb6aabf5cd030c4ade4957dba
1 /*
2 Unix SMB/CIFS implementation.
3 client connect/disconnect routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Andrew Bartlett 2001-2003
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "popt_common.h"
23 #include "../libcli/auth/libcli_auth.h"
24 #include "../libcli/auth/spnego.h"
25 #include "smb_krb5.h"
26 #include "../libcli/auth/ntlmssp.h"
27 #include "libads/kerberos_proto.h"
28 #include "krb5_env.h"
29 #include "async_smb.h"
31 static const struct {
32 int prot;
33 const char name[24];
34 } prots[10] = {
35 {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
36 {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
37 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
38 {PROTOCOL_LANMAN1, "LANMAN1.0"},
39 {PROTOCOL_LANMAN2, "LM1.2X002"},
40 {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
41 {PROTOCOL_LANMAN2, "LANMAN2.1"},
42 {PROTOCOL_LANMAN2, "Samba"},
43 {PROTOCOL_NT1, "NT LANMAN 1.0"},
44 {PROTOCOL_NT1, "NT LM 0.12"},
47 #define STAR_SMBSERVER "*SMBSERVER"
49 /**
50 * Set the user session key for a connection
51 * @param cli The cli structure to add it too
52 * @param session_key The session key used. (A copy of this is taken for the cli struct)
56 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
58 cli->user_session_key = data_blob(session_key.data, session_key.length);
61 /****************************************************************************
62 Do an old lanman2 style session setup.
63 ****************************************************************************/
65 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
66 const char *user,
67 const char *pass, size_t passlen,
68 const char *workgroup)
70 DATA_BLOB session_key = data_blob_null;
71 DATA_BLOB lm_response = data_blob_null;
72 NTSTATUS status;
73 fstring pword;
74 char *p;
76 if (passlen > sizeof(pword)-1) {
77 return NT_STATUS_INVALID_PARAMETER;
80 /* LANMAN servers predate NT status codes and Unicode and ignore those
81 smb flags so we must disable the corresponding default capabilities
82 that would otherwise cause the Unicode and NT Status flags to be
83 set (and even returned by the server) */
85 cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
87 /* if in share level security then don't send a password now */
88 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
89 passlen = 0;
91 if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
92 /* Encrypted mode needed, and non encrypted password supplied. */
93 lm_response = data_blob(NULL, 24);
94 if (!SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data)) {
95 DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n"));
96 return NT_STATUS_ACCESS_DENIED;
98 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
99 /* Encrypted mode needed, and encrypted password supplied. */
100 lm_response = data_blob(pass, passlen);
101 } else if (passlen > 0) {
102 /* Plaintext mode needed, assume plaintext supplied. */
103 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
104 lm_response = data_blob(pass, passlen);
107 /* send a session setup command */
108 memset(cli->outbuf,'\0',smb_size);
109 cli_set_message(cli->outbuf,10, 0, True);
110 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
111 cli_setup_packet(cli);
113 SCVAL(cli->outbuf,smb_vwv0,0xFF);
114 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
115 SSVAL(cli->outbuf,smb_vwv3,2);
116 SSVAL(cli->outbuf,smb_vwv4,1);
117 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
118 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
120 p = smb_buf(cli->outbuf);
121 memcpy(p,lm_response.data,lm_response.length);
122 p += lm_response.length;
123 p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
124 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
125 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
126 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
127 cli_setup_bcc(cli, p);
129 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
130 return cli_nt_error(cli);
133 show_msg(cli->inbuf);
135 if (cli_is_error(cli)) {
136 return cli_nt_error(cli);
139 /* use the returned vuid from now on */
140 cli->vuid = SVAL(cli->inbuf,smb_uid);
141 status = cli_set_username(cli, user);
142 if (!NT_STATUS_IS_OK(status)) {
143 return status;
146 if (session_key.data) {
147 /* Have plaintext orginal */
148 cli_set_session_key(cli, session_key);
151 return NT_STATUS_OK;
154 /****************************************************************************
155 Work out suitable capabilities to offer the server.
156 ****************************************************************************/
158 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
160 uint32 capabilities = CAP_NT_SMBS;
162 if (!cli->force_dos_errors)
163 capabilities |= CAP_STATUS32;
165 if (cli->use_level_II_oplocks)
166 capabilities |= CAP_LEVEL_II_OPLOCKS;
168 capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
169 return capabilities;
172 /****************************************************************************
173 Do a NT1 guest session setup.
174 ****************************************************************************/
176 struct cli_session_setup_guest_state {
177 struct cli_state *cli;
178 uint16_t vwv[16];
179 struct iovec bytes;
182 static void cli_session_setup_guest_done(struct tevent_req *subreq);
184 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
185 struct event_context *ev,
186 struct cli_state *cli,
187 struct tevent_req **psmbreq)
189 struct tevent_req *req, *subreq;
190 struct cli_session_setup_guest_state *state;
191 uint16_t *vwv;
192 uint8_t *bytes;
194 req = tevent_req_create(mem_ctx, &state,
195 struct cli_session_setup_guest_state);
196 if (req == NULL) {
197 return NULL;
199 state->cli = cli;
200 vwv = state->vwv;
202 SCVAL(vwv+0, 0, 0xFF);
203 SCVAL(vwv+0, 1, 0);
204 SSVAL(vwv+1, 0, 0);
205 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
206 SSVAL(vwv+3, 0, 2);
207 SSVAL(vwv+4, 0, cli->pid);
208 SIVAL(vwv+5, 0, cli->sesskey);
209 SSVAL(vwv+7, 0, 0);
210 SSVAL(vwv+8, 0, 0);
211 SSVAL(vwv+9, 0, 0);
212 SSVAL(vwv+10, 0, 0);
213 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
215 bytes = talloc_array(state, uint8_t, 0);
217 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
218 NULL);
219 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
220 NULL);
221 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
222 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
224 if (bytes == NULL) {
225 TALLOC_FREE(req);
226 return NULL;
229 state->bytes.iov_base = (void *)bytes;
230 state->bytes.iov_len = talloc_get_size(bytes);
232 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
233 1, &state->bytes);
234 if (subreq == NULL) {
235 TALLOC_FREE(req);
236 return NULL;
238 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
239 *psmbreq = subreq;
240 return req;
243 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
244 struct event_context *ev,
245 struct cli_state *cli)
247 struct tevent_req *req, *subreq;
248 NTSTATUS status;
250 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
251 if (req == NULL) {
252 return NULL;
255 status = cli_smb_req_send(subreq);
256 if (NT_STATUS_IS_OK(status)) {
257 tevent_req_nterror(req, status);
258 return tevent_req_post(req, ev);
260 return req;
263 static void cli_session_setup_guest_done(struct tevent_req *subreq)
265 struct tevent_req *req = tevent_req_callback_data(
266 subreq, struct tevent_req);
267 struct cli_session_setup_guest_state *state = tevent_req_data(
268 req, struct cli_session_setup_guest_state);
269 struct cli_state *cli = state->cli;
270 uint32_t num_bytes;
271 uint8_t *in;
272 char *inbuf;
273 uint8_t *bytes;
274 uint8_t *p;
275 NTSTATUS status;
277 status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
278 &num_bytes, &bytes);
279 TALLOC_FREE(subreq);
280 if (!NT_STATUS_IS_OK(status)) {
281 tevent_req_nterror(req, status);
282 return;
285 inbuf = (char *)in;
286 p = bytes;
288 cli->vuid = SVAL(inbuf, smb_uid);
290 p += clistr_pull(inbuf, cli->server_os, (char *)p, sizeof(fstring),
291 bytes+num_bytes-p, STR_TERMINATE);
292 p += clistr_pull(inbuf, cli->server_type, (char *)p, sizeof(fstring),
293 bytes+num_bytes-p, STR_TERMINATE);
294 p += clistr_pull(inbuf, cli->server_domain, (char *)p, sizeof(fstring),
295 bytes+num_bytes-p, STR_TERMINATE);
297 if (strstr(cli->server_type, "Samba")) {
298 cli->is_samba = True;
301 status = cli_set_username(cli, "");
302 if (!NT_STATUS_IS_OK(status)) {
303 tevent_req_nterror(req, status);
304 return;
306 tevent_req_done(req);
309 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
311 return tevent_req_simple_recv_ntstatus(req);
314 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
316 TALLOC_CTX *frame = talloc_stackframe();
317 struct event_context *ev;
318 struct tevent_req *req;
319 NTSTATUS status = NT_STATUS_OK;
321 if (cli_has_async_calls(cli)) {
323 * Can't use sync call while an async call is in flight
325 status = NT_STATUS_INVALID_PARAMETER;
326 goto fail;
329 ev = event_context_init(frame);
330 if (ev == NULL) {
331 status = NT_STATUS_NO_MEMORY;
332 goto fail;
335 req = cli_session_setup_guest_send(frame, ev, cli);
336 if (req == NULL) {
337 status = NT_STATUS_NO_MEMORY;
338 goto fail;
341 if (!tevent_req_poll(req, ev)) {
342 status = map_nt_error_from_unix(errno);
343 goto fail;
346 status = cli_session_setup_guest_recv(req);
347 fail:
348 TALLOC_FREE(frame);
349 if (!NT_STATUS_IS_OK(status)) {
350 cli_set_error(cli, status);
352 return status;
355 /****************************************************************************
356 Do a NT1 plaintext session setup.
357 ****************************************************************************/
359 static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
360 const char *user, const char *pass,
361 const char *workgroup)
363 uint32 capabilities = cli_session_setup_capabilities(cli);
364 char *p;
365 NTSTATUS status;
366 fstring lanman;
368 fstr_sprintf( lanman, "Samba %s", samba_version_string());
370 memset(cli->outbuf, '\0', smb_size);
371 cli_set_message(cli->outbuf,13,0,True);
372 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
373 cli_setup_packet(cli);
375 SCVAL(cli->outbuf,smb_vwv0,0xFF);
376 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
377 SSVAL(cli->outbuf,smb_vwv3,2);
378 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
379 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
380 SSVAL(cli->outbuf,smb_vwv8,0);
381 SIVAL(cli->outbuf,smb_vwv11,capabilities);
382 p = smb_buf(cli->outbuf);
384 /* check wether to send the ASCII or UNICODE version of the password */
386 if ( (capabilities & CAP_UNICODE) == 0 ) {
387 p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
388 SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
390 else {
391 /* For ucs2 passwords clistr_push calls ucs2_align, which causes
392 * the space taken by the unicode password to be one byte too
393 * long (as we're on an odd byte boundary here). Reduce the
394 * count by 1 to cope with this. Fixes smbclient against NetApp
395 * servers which can't cope. Fix from
396 * bryan.kolodziej@allenlund.com in bug #3840.
398 p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
399 SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))-1);
402 p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
403 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
404 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
405 p += clistr_push(cli, p, lanman, -1, STR_TERMINATE);
406 cli_setup_bcc(cli, p);
408 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
409 return cli_nt_error(cli);
412 show_msg(cli->inbuf);
414 if (cli_is_error(cli)) {
415 return cli_nt_error(cli);
418 cli->vuid = SVAL(cli->inbuf,smb_uid);
419 p = smb_buf(cli->inbuf);
420 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
421 -1, STR_TERMINATE);
422 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
423 -1, STR_TERMINATE);
424 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
425 -1, STR_TERMINATE);
426 status = cli_set_username(cli, user);
427 if (!NT_STATUS_IS_OK(status)) {
428 return status;
430 if (strstr(cli->server_type, "Samba")) {
431 cli->is_samba = True;
434 return NT_STATUS_OK;
437 /****************************************************************************
438 do a NT1 NTLM/LM encrypted session setup - for when extended security
439 is not negotiated.
440 @param cli client state to create do session setup on
441 @param user username
442 @param pass *either* cleartext password (passlen !=24) or LM response.
443 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
444 @param workgroup The user's domain.
445 ****************************************************************************/
447 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
448 const char *pass, size_t passlen,
449 const char *ntpass, size_t ntpasslen,
450 const char *workgroup)
452 uint32 capabilities = cli_session_setup_capabilities(cli);
453 DATA_BLOB lm_response = data_blob_null;
454 DATA_BLOB nt_response = data_blob_null;
455 DATA_BLOB session_key = data_blob_null;
456 NTSTATUS result;
457 char *p;
458 bool ok;
460 if (passlen == 0) {
461 /* do nothing - guest login */
462 } else if (passlen != 24) {
463 if (lp_client_ntlmv2_auth()) {
464 DATA_BLOB server_chal;
465 DATA_BLOB names_blob;
466 server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8));
468 /* note that the 'workgroup' here is a best guess - we don't know
469 the server's domain at this point. The 'server name' is also
470 dodgy...
472 names_blob = NTLMv2_generate_names_blob(NULL, cli->called.name, workgroup);
474 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass, &server_chal,
475 &names_blob,
476 &lm_response, &nt_response, NULL, &session_key)) {
477 data_blob_free(&names_blob);
478 data_blob_free(&server_chal);
479 return NT_STATUS_ACCESS_DENIED;
481 data_blob_free(&names_blob);
482 data_blob_free(&server_chal);
484 } else {
485 uchar nt_hash[16];
486 E_md4hash(pass, nt_hash);
488 #ifdef LANMAN_ONLY
489 nt_response = data_blob_null;
490 #else
491 nt_response = data_blob(NULL, 24);
492 SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
493 #endif
494 /* non encrypted password supplied. Ignore ntpass. */
495 if (lp_client_lanman_auth()) {
496 lm_response = data_blob(NULL, 24);
497 if (!SMBencrypt(pass,cli->secblob.data, lm_response.data)) {
498 /* Oops, the LM response is invalid, just put
499 the NT response there instead */
500 data_blob_free(&lm_response);
501 lm_response = data_blob(nt_response.data, nt_response.length);
503 } else {
504 /* LM disabled, place NT# in LM field instead */
505 lm_response = data_blob(nt_response.data, nt_response.length);
508 session_key = data_blob(NULL, 16);
509 #ifdef LANMAN_ONLY
510 E_deshash(pass, session_key.data);
511 memset(&session_key.data[8], '\0', 8);
512 #else
513 SMBsesskeygen_ntv1(nt_hash, session_key.data);
514 #endif
516 cli_temp_set_signing(cli);
517 } else {
518 /* pre-encrypted password supplied. Only used for
519 security=server, can't do
520 signing because we don't have original key */
522 lm_response = data_blob(pass, passlen);
523 nt_response = data_blob(ntpass, ntpasslen);
526 /* send a session setup command */
527 memset(cli->outbuf,'\0',smb_size);
529 cli_set_message(cli->outbuf,13,0,True);
530 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
531 cli_setup_packet(cli);
533 SCVAL(cli->outbuf,smb_vwv0,0xFF);
534 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
535 SSVAL(cli->outbuf,smb_vwv3,2);
536 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
537 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
538 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
539 SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
540 SIVAL(cli->outbuf,smb_vwv11,capabilities);
541 p = smb_buf(cli->outbuf);
542 if (lm_response.length) {
543 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
545 if (nt_response.length) {
546 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
548 p += clistr_push(cli, p, user, -1, STR_TERMINATE);
550 /* Upper case here might help some NTLMv2 implementations */
551 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
552 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
553 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
554 cli_setup_bcc(cli, p);
556 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
557 result = cli_nt_error(cli);
558 goto end;
561 /* show_msg(cli->inbuf); */
563 if (cli_is_error(cli)) {
564 result = cli_nt_error(cli);
565 goto end;
568 #ifdef LANMAN_ONLY
569 ok = cli_simple_set_signing(cli, session_key, lm_response);
570 #else
571 ok = cli_simple_set_signing(cli, session_key, nt_response);
572 #endif
573 if (ok) {
574 if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
575 result = NT_STATUS_ACCESS_DENIED;
576 goto end;
580 /* use the returned vuid from now on */
581 cli->vuid = SVAL(cli->inbuf,smb_uid);
583 p = smb_buf(cli->inbuf);
584 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
585 -1, STR_TERMINATE);
586 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
587 -1, STR_TERMINATE);
588 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
589 -1, STR_TERMINATE);
591 if (strstr(cli->server_type, "Samba")) {
592 cli->is_samba = True;
595 result = cli_set_username(cli, user);
596 if (!NT_STATUS_IS_OK(result)) {
597 goto end;
600 if (session_key.data) {
601 /* Have plaintext orginal */
602 cli_set_session_key(cli, session_key);
605 result = NT_STATUS_OK;
606 end:
607 data_blob_free(&lm_response);
608 data_blob_free(&nt_response);
609 data_blob_free(&session_key);
610 return result;
613 /* The following is calculated from :
614 * (smb_size-4) = 35
615 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
616 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
617 * end of packet.
620 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
622 struct cli_sesssetup_blob_state {
623 struct tevent_context *ev;
624 struct cli_state *cli;
625 DATA_BLOB blob;
626 uint16_t max_blob_size;
627 uint16_t vwv[12];
628 uint8_t *buf;
630 NTSTATUS status;
631 char *inbuf;
632 DATA_BLOB ret_blob;
635 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
636 struct tevent_req **psubreq);
637 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
639 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
640 struct tevent_context *ev,
641 struct cli_state *cli,
642 DATA_BLOB blob)
644 struct tevent_req *req, *subreq;
645 struct cli_sesssetup_blob_state *state;
647 req = tevent_req_create(mem_ctx, &state,
648 struct cli_sesssetup_blob_state);
649 if (req == NULL) {
650 return NULL;
652 state->ev = ev;
653 state->blob = blob;
654 state->cli = cli;
656 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
657 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
658 "(was %u, need minimum %u)\n",
659 (unsigned int)cli->max_xmit,
660 BASE_SESSSETUP_BLOB_PACKET_SIZE));
661 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
662 return tevent_req_post(req, ev);
664 state->max_blob_size =
665 MIN(cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE, 0xFFFF);
667 if (!cli_sesssetup_blob_next(state, &subreq)) {
668 tevent_req_nomem(NULL, req);
669 return tevent_req_post(req, ev);
671 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
672 return req;
675 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
676 struct tevent_req **psubreq)
678 struct tevent_req *subreq;
679 uint16_t thistime;
681 SCVAL(state->vwv+0, 0, 0xFF);
682 SCVAL(state->vwv+0, 1, 0);
683 SSVAL(state->vwv+1, 0, 0);
684 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
685 SSVAL(state->vwv+3, 0, 2);
686 SSVAL(state->vwv+4, 0, 1);
687 SIVAL(state->vwv+5, 0, 0);
689 thistime = MIN(state->blob.length, state->max_blob_size);
690 SSVAL(state->vwv+7, 0, thistime);
692 SSVAL(state->vwv+8, 0, 0);
693 SSVAL(state->vwv+9, 0, 0);
694 SIVAL(state->vwv+10, 0,
695 cli_session_setup_capabilities(state->cli)
696 | CAP_EXTENDED_SECURITY);
698 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
699 thistime);
700 if (state->buf == NULL) {
701 return false;
703 state->blob.data += thistime;
704 state->blob.length -= thistime;
706 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
707 "Unix", 5, NULL);
708 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
709 "Samba", 6, NULL);
710 if (state->buf == NULL) {
711 return false;
713 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
714 12, state->vwv,
715 talloc_get_size(state->buf), state->buf);
716 if (subreq == NULL) {
717 return false;
719 *psubreq = subreq;
720 return true;
723 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
725 struct tevent_req *req = tevent_req_callback_data(
726 subreq, struct tevent_req);
727 struct cli_sesssetup_blob_state *state = tevent_req_data(
728 req, struct cli_sesssetup_blob_state);
729 struct cli_state *cli = state->cli;
730 uint8_t wct;
731 uint16_t *vwv;
732 uint32_t num_bytes;
733 uint8_t *bytes;
734 NTSTATUS status;
735 uint8_t *p;
736 uint16_t blob_length;
737 uint8_t *inbuf;
739 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
740 &num_bytes, &bytes);
741 TALLOC_FREE(subreq);
742 if (!NT_STATUS_IS_OK(status)
743 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
744 tevent_req_nterror(req, status);
745 return;
748 state->status = status;
749 TALLOC_FREE(state->buf);
751 state->inbuf = (char *)inbuf;
752 cli->vuid = SVAL(state->inbuf, smb_uid);
754 blob_length = SVAL(vwv+3, 0);
755 if (blob_length > num_bytes) {
756 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
757 return;
759 state->ret_blob = data_blob_const(bytes, blob_length);
761 p = bytes + blob_length;
763 p += clistr_pull(state->inbuf, cli->server_os,
764 (char *)p, sizeof(fstring),
765 bytes+num_bytes-p, STR_TERMINATE);
766 p += clistr_pull(state->inbuf, cli->server_type,
767 (char *)p, sizeof(fstring),
768 bytes+num_bytes-p, STR_TERMINATE);
769 p += clistr_pull(state->inbuf, cli->server_domain,
770 (char *)p, sizeof(fstring),
771 bytes+num_bytes-p, STR_TERMINATE);
773 if (strstr(cli->server_type, "Samba")) {
774 cli->is_samba = True;
777 if (state->blob.length != 0) {
779 * More to send
781 if (!cli_sesssetup_blob_next(state, &subreq)) {
782 tevent_req_nomem(NULL, req);
783 return;
785 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
786 return;
788 tevent_req_done(req);
791 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
792 TALLOC_CTX *mem_ctx,
793 DATA_BLOB *pblob,
794 char **pinbuf)
796 struct cli_sesssetup_blob_state *state = tevent_req_data(
797 req, struct cli_sesssetup_blob_state);
798 NTSTATUS status;
799 char *inbuf;
801 if (tevent_req_is_nterror(req, &status)) {
802 state->cli->vuid = 0;
803 return status;
806 inbuf = talloc_move(mem_ctx, &state->inbuf);
807 if (pblob != NULL) {
808 *pblob = state->ret_blob;
810 if (pinbuf != NULL) {
811 *pinbuf = inbuf;
813 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
814 return state->status;
817 #ifdef HAVE_KRB5
819 /****************************************************************************
820 Use in-memory credentials cache
821 ****************************************************************************/
823 static void use_in_memory_ccache(void) {
824 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
827 /****************************************************************************
828 Do a spnego/kerberos encrypted session setup.
829 ****************************************************************************/
831 struct cli_session_setup_kerberos_state {
832 struct cli_state *cli;
833 DATA_BLOB negTokenTarg;
834 DATA_BLOB session_key_krb5;
835 ADS_STATUS ads_status;
838 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
840 static struct tevent_req *cli_session_setup_kerberos_send(
841 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
842 const char *principal, const char *workgroup)
844 struct tevent_req *req, *subreq;
845 struct cli_session_setup_kerberos_state *state;
846 int rc;
848 DEBUG(2,("Doing kerberos session setup\n"));
850 req = tevent_req_create(mem_ctx, &state,
851 struct cli_session_setup_kerberos_state);
852 if (req == NULL) {
853 return NULL;
855 state->cli = cli;
856 state->ads_status = ADS_SUCCESS;
858 cli_temp_set_signing(cli);
861 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
862 * we have to acquire a ticket. To be fixed later :-)
864 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
865 &state->session_key_krb5, 0, NULL);
866 if (rc) {
867 DEBUG(1, ("cli_session_setup_kerberos: "
868 "spnego_gen_krb5_negTokenInit failed: %s\n",
869 error_message(rc)));
870 state->ads_status = ADS_ERROR_KRB5(rc);
871 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
872 return tevent_req_post(req, ev);
875 #if 0
876 file_save("negTokenTarg.dat", state->negTokenTarg.data,
877 state->negTokenTarg.length);
878 #endif
880 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
881 if (tevent_req_nomem(subreq, req)) {
882 return tevent_req_post(req, ev);
884 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
885 return req;
888 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
890 struct tevent_req *req = tevent_req_callback_data(
891 subreq, struct tevent_req);
892 struct cli_session_setup_kerberos_state *state = tevent_req_data(
893 req, struct cli_session_setup_kerberos_state);
894 char *inbuf = NULL;
895 NTSTATUS status;
897 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), NULL, &inbuf);
898 if (!NT_STATUS_IS_OK(status)) {
899 TALLOC_FREE(subreq);
900 tevent_req_nterror(req, status);
901 return;
904 cli_set_session_key(state->cli, state->session_key_krb5);
906 if (cli_simple_set_signing(state->cli, state->session_key_krb5,
907 data_blob_null)
908 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
909 TALLOC_FREE(subreq);
910 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
911 return;
913 TALLOC_FREE(subreq);
914 tevent_req_done(req);
917 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
919 struct cli_session_setup_kerberos_state *state = tevent_req_data(
920 req, struct cli_session_setup_kerberos_state);
921 NTSTATUS status;
923 if (tevent_req_is_nterror(req, &status)) {
924 return ADS_ERROR_NT(status);
926 return state->ads_status;
929 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
930 const char *principal,
931 const char *workgroup)
933 struct tevent_context *ev;
934 struct tevent_req *req;
935 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
937 if (cli_has_async_calls(cli)) {
938 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
940 ev = tevent_context_init(talloc_tos());
941 if (ev == NULL) {
942 goto fail;
944 req = cli_session_setup_kerberos_send(ev, ev, cli, principal,
945 workgroup);
946 if (req == NULL) {
947 goto fail;
949 if (!tevent_req_poll(req, ev)) {
950 status = ADS_ERROR_SYSTEM(errno);
951 goto fail;
953 status = cli_session_setup_kerberos_recv(req);
954 fail:
955 TALLOC_FREE(ev);
956 return status;
958 #endif /* HAVE_KRB5 */
960 /****************************************************************************
961 Do a spnego/NTLMSSP encrypted session setup.
962 ****************************************************************************/
964 struct cli_session_setup_ntlmssp_state {
965 struct tevent_context *ev;
966 struct cli_state *cli;
967 struct ntlmssp_state *ntlmssp_state;
968 int turn;
969 DATA_BLOB blob_out;
972 static int cli_session_setup_ntlmssp_state_destructor(
973 struct cli_session_setup_ntlmssp_state *state)
975 if (state->ntlmssp_state != NULL) {
976 TALLOC_FREE(state->ntlmssp_state);
978 return 0;
981 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
983 static struct tevent_req *cli_session_setup_ntlmssp_send(
984 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
985 const char *user, const char *pass, const char *domain)
987 struct tevent_req *req, *subreq;
988 struct cli_session_setup_ntlmssp_state *state;
989 NTSTATUS status;
990 DATA_BLOB blob_out;
991 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
993 req = tevent_req_create(mem_ctx, &state,
994 struct cli_session_setup_ntlmssp_state);
995 if (req == NULL) {
996 return NULL;
998 state->ev = ev;
999 state->cli = cli;
1000 state->turn = 1;
1002 state->ntlmssp_state = NULL;
1003 talloc_set_destructor(
1004 state, cli_session_setup_ntlmssp_state_destructor);
1006 cli_temp_set_signing(cli);
1008 status = ntlmssp_client_start(state,
1009 global_myname(),
1010 lp_workgroup(),
1011 lp_client_ntlmv2_auth(),
1012 &state->ntlmssp_state);
1013 if (!NT_STATUS_IS_OK(status)) {
1014 goto fail;
1016 ntlmssp_want_feature(state->ntlmssp_state,
1017 NTLMSSP_FEATURE_SESSION_KEY);
1018 if (cli->use_ccache) {
1019 ntlmssp_want_feature(state->ntlmssp_state,
1020 NTLMSSP_FEATURE_CCACHE);
1022 status = ntlmssp_set_username(state->ntlmssp_state, user);
1023 if (!NT_STATUS_IS_OK(status)) {
1024 goto fail;
1026 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1027 if (!NT_STATUS_IS_OK(status)) {
1028 goto fail;
1030 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1031 if (!NT_STATUS_IS_OK(status)) {
1032 goto fail;
1034 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1035 &blob_out);
1036 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1037 goto fail;
1040 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1041 data_blob_free(&blob_out);
1043 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1044 if (tevent_req_nomem(subreq, req)) {
1045 return tevent_req_post(req, ev);
1047 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1048 return req;
1049 fail:
1050 tevent_req_nterror(req, status);
1051 return tevent_req_post(req, ev);
1054 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1056 struct tevent_req *req = tevent_req_callback_data(
1057 subreq, struct tevent_req);
1058 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1059 req, struct cli_session_setup_ntlmssp_state);
1060 DATA_BLOB blob_in, msg_in, blob_out;
1061 char *inbuf = NULL;
1062 bool parse_ret;
1063 NTSTATUS status;
1065 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1066 &inbuf);
1067 TALLOC_FREE(subreq);
1068 data_blob_free(&state->blob_out);
1070 if (NT_STATUS_IS_OK(status)) {
1071 if (state->cli->server_domain[0] == '\0') {
1072 fstrcpy(state->cli->server_domain,
1073 state->ntlmssp_state->server.netbios_domain);
1075 cli_set_session_key(
1076 state->cli, state->ntlmssp_state->session_key);
1078 if (cli_simple_set_signing(
1079 state->cli, state->ntlmssp_state->session_key,
1080 data_blob_null)
1081 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1082 TALLOC_FREE(subreq);
1083 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1084 return;
1086 TALLOC_FREE(subreq);
1087 TALLOC_FREE(state->ntlmssp_state);
1088 tevent_req_done(req);
1089 return;
1091 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1092 tevent_req_nterror(req, status);
1093 return;
1096 if (blob_in.length == 0) {
1097 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1098 return;
1101 if ((state->turn == 1)
1102 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1103 DATA_BLOB tmp_blob = data_blob_null;
1104 /* the server might give us back two challenges */
1105 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1106 &tmp_blob);
1107 data_blob_free(&tmp_blob);
1108 } else {
1109 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1110 OID_NTLMSSP, &msg_in);
1112 state->turn += 1;
1114 if (!parse_ret) {
1115 DEBUG(3,("Failed to parse auth response\n"));
1116 if (NT_STATUS_IS_OK(status)
1117 || NT_STATUS_EQUAL(status,
1118 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1119 tevent_req_nterror(
1120 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1121 return;
1125 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1127 if (!NT_STATUS_IS_OK(status)
1128 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1129 TALLOC_FREE(subreq);
1130 TALLOC_FREE(state->ntlmssp_state);
1131 tevent_req_nterror(req, status);
1132 return;
1135 state->blob_out = spnego_gen_auth(state, blob_out);
1136 TALLOC_FREE(subreq);
1137 if (tevent_req_nomem(state->blob_out.data, req)) {
1138 return;
1141 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1142 state->blob_out);
1143 if (tevent_req_nomem(subreq, req)) {
1144 return;
1146 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1149 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1151 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1152 req, struct cli_session_setup_ntlmssp_state);
1153 NTSTATUS status;
1155 if (tevent_req_is_nterror(req, &status)) {
1156 state->cli->vuid = 0;
1157 return status;
1159 return NT_STATUS_OK;
1162 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1163 const char *user,
1164 const char *pass,
1165 const char *domain)
1167 struct tevent_context *ev;
1168 struct tevent_req *req;
1169 NTSTATUS status = NT_STATUS_NO_MEMORY;
1171 if (cli_has_async_calls(cli)) {
1172 return NT_STATUS_INVALID_PARAMETER;
1174 ev = tevent_context_init(talloc_tos());
1175 if (ev == NULL) {
1176 goto fail;
1178 req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1179 if (req == NULL) {
1180 goto fail;
1182 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1183 goto fail;
1185 status = cli_session_setup_ntlmssp_recv(req);
1186 fail:
1187 TALLOC_FREE(ev);
1188 if (!NT_STATUS_IS_OK(status)) {
1189 cli_set_error(cli, status);
1191 return status;
1194 /****************************************************************************
1195 Do a spnego encrypted session setup.
1197 user_domain: The shortname of the domain the user/machine is a member of.
1198 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1199 ****************************************************************************/
1201 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
1202 const char *pass, const char *user_domain,
1203 const char * dest_realm)
1205 char *principal = NULL;
1206 char *OIDs[ASN1_MAX_OIDS];
1207 int i;
1208 DATA_BLOB blob;
1209 const char *p = NULL;
1210 char *account = NULL;
1211 NTSTATUS status;
1213 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
1215 /* the server might not even do spnego */
1216 if (cli->secblob.length <= 16) {
1217 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1218 goto ntlmssp;
1221 #if 0
1222 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1223 #endif
1225 /* there is 16 bytes of GUID before the real spnego packet starts */
1226 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1228 /* The server sent us the first part of the SPNEGO exchange in the
1229 * negprot reply. It is WRONG to depend on the principal sent in the
1230 * negprot reply, but right now we do it. If we don't receive one,
1231 * we try to best guess, then fall back to NTLM. */
1232 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1233 OIDs[0] == NULL) {
1234 data_blob_free(&blob);
1235 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1237 data_blob_free(&blob);
1239 /* make sure the server understands kerberos */
1240 for (i=0;OIDs[i];i++) {
1241 if (i == 0)
1242 DEBUG(3,("got OID=%s\n", OIDs[i]));
1243 else
1244 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1245 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1246 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1247 cli->got_kerberos_mechanism = True;
1249 talloc_free(OIDs[i]);
1252 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1254 status = cli_set_username(cli, user);
1255 if (!NT_STATUS_IS_OK(status)) {
1256 TALLOC_FREE(principal);
1257 return ADS_ERROR_NT(status);
1260 #ifdef HAVE_KRB5
1261 /* If password is set we reauthenticate to kerberos server
1262 * and do not store results */
1264 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1265 ADS_STATUS rc;
1267 if (pass && *pass) {
1268 int ret;
1270 use_in_memory_ccache();
1271 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1273 if (ret){
1274 TALLOC_FREE(principal);
1275 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1276 if (cli->fallback_after_kerberos)
1277 goto ntlmssp;
1278 return ADS_ERROR_KRB5(ret);
1282 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1284 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1285 TALLOC_FREE(principal);
1288 if (principal == NULL &&
1289 !is_ipaddress(cli->desthost) &&
1290 !strequal(STAR_SMBSERVER,
1291 cli->desthost)) {
1292 char *realm = NULL;
1293 char *host = NULL;
1294 DEBUG(3,("cli_session_setup_spnego: using target "
1295 "hostname not SPNEGO principal\n"));
1297 host = strchr_m(cli->desthost, '.');
1298 if (dest_realm) {
1299 realm = SMB_STRDUP(dest_realm);
1300 strupper_m(realm);
1301 } else {
1302 if (host) {
1303 /* DNS name. */
1304 realm = kerberos_get_realm_from_hostname(cli->desthost);
1305 } else {
1306 /* NetBIOS name - use our realm. */
1307 realm = kerberos_get_default_realm_from_ccache();
1311 if (realm && *realm) {
1312 principal = talloc_asprintf(talloc_tos(),
1313 "cifs/%s@%s",
1314 cli->desthost,
1315 realm);
1316 if (!principal) {
1317 SAFE_FREE(realm);
1318 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1320 DEBUG(3,("cli_session_setup_spnego: guessed "
1321 "server principal=%s\n",
1322 principal ? principal : "<null>"));
1324 SAFE_FREE(realm);
1327 if (principal) {
1328 rc = cli_session_setup_kerberos(cli, principal,
1329 dest_realm);
1330 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1331 TALLOC_FREE(principal);
1332 return rc;
1336 #endif
1338 TALLOC_FREE(principal);
1340 ntlmssp:
1342 account = talloc_strdup(talloc_tos(), user);
1343 if (!account) {
1344 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1347 /* when falling back to ntlmssp while authenticating with a machine
1348 * account strip off the realm - gd */
1350 if ((p = strchr_m(user, '@')) != NULL) {
1351 account[PTR_DIFF(p,user)] = '\0';
1354 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1357 /****************************************************************************
1358 Send a session setup. The username and workgroup is in UNIX character
1359 format and must be converted to DOS codepage format before sending. If the
1360 password is in plaintext, the same should be done.
1361 ****************************************************************************/
1363 NTSTATUS cli_session_setup(struct cli_state *cli,
1364 const char *user,
1365 const char *pass, int passlen,
1366 const char *ntpass, int ntpasslen,
1367 const char *workgroup)
1369 char *p;
1370 fstring user2;
1372 if (user) {
1373 fstrcpy(user2, user);
1374 } else {
1375 user2[0] ='\0';
1378 if (!workgroup) {
1379 workgroup = "";
1382 /* allow for workgroups as part of the username */
1383 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1384 (p=strchr_m(user2,*lp_winbind_separator()))) {
1385 *p = 0;
1386 user = p+1;
1387 workgroup = user2;
1390 if (cli->protocol < PROTOCOL_LANMAN1) {
1391 return NT_STATUS_OK;
1394 /* now work out what sort of session setup we are going to
1395 do. I have split this into separate functions to make the
1396 flow a bit easier to understand (tridge) */
1398 /* if its an older server then we have to use the older request format */
1400 if (cli->protocol < PROTOCOL_NT1) {
1401 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1402 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
1403 " or 'client ntlmv2 auth = yes'\n"));
1404 return NT_STATUS_ACCESS_DENIED;
1407 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1408 !lp_client_plaintext_auth() && (*pass)) {
1409 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
1410 " or 'client ntlmv2 auth = yes'\n"));
1411 return NT_STATUS_ACCESS_DENIED;
1414 return cli_session_setup_lanman2(cli, user, pass, passlen,
1415 workgroup);
1418 /* if no user is supplied then we have to do an anonymous connection.
1419 passwords are ignored */
1421 if (!user || !*user)
1422 return cli_session_setup_guest(cli);
1424 /* if the server is share level then send a plaintext null
1425 password at this point. The password is sent in the tree
1426 connect */
1428 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
1429 return cli_session_setup_plaintext(cli, user, "", workgroup);
1431 /* if the server doesn't support encryption then we have to use
1432 plaintext. The second password is ignored */
1434 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1435 if (!lp_client_plaintext_auth() && (*pass)) {
1436 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
1437 " or 'client ntlmv2 auth = yes'\n"));
1438 return NT_STATUS_ACCESS_DENIED;
1440 return cli_session_setup_plaintext(cli, user, pass, workgroup);
1443 /* if the server supports extended security then use SPNEGO */
1445 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
1446 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
1447 workgroup, NULL);
1448 if (!ADS_ERR_OK(status)) {
1449 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1450 return ads_ntstatus(status);
1452 } else {
1453 NTSTATUS status;
1455 /* otherwise do a NT1 style session setup */
1456 status = cli_session_setup_nt1(cli, user, pass, passlen,
1457 ntpass, ntpasslen, workgroup);
1458 if (!NT_STATUS_IS_OK(status)) {
1459 DEBUG(3,("cli_session_setup: NT1 session setup "
1460 "failed: %s\n", nt_errstr(status)));
1461 return status;
1465 if (strstr(cli->server_type, "Samba")) {
1466 cli->is_samba = True;
1469 return NT_STATUS_OK;
1472 /****************************************************************************
1473 Send a uloggoff.
1474 *****************************************************************************/
1476 struct cli_ulogoff_state {
1477 struct cli_state *cli;
1478 uint16_t vwv[3];
1481 static void cli_ulogoff_done(struct tevent_req *subreq);
1483 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1484 struct tevent_context *ev,
1485 struct cli_state *cli)
1487 struct tevent_req *req, *subreq;
1488 struct cli_ulogoff_state *state;
1490 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1491 if (req == NULL) {
1492 return NULL;
1494 state->cli = cli;
1496 SCVAL(state->vwv+0, 0, 0xFF);
1497 SCVAL(state->vwv+1, 0, 0);
1498 SSVAL(state->vwv+2, 0, 0);
1500 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
1501 0, NULL);
1502 if (tevent_req_nomem(subreq, req)) {
1503 return tevent_req_post(req, ev);
1505 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1506 return req;
1509 static void cli_ulogoff_done(struct tevent_req *subreq)
1511 struct tevent_req *req = tevent_req_callback_data(
1512 subreq, struct tevent_req);
1513 struct cli_ulogoff_state *state = tevent_req_data(
1514 req, struct cli_ulogoff_state);
1515 NTSTATUS status;
1517 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1518 if (!NT_STATUS_IS_OK(status)) {
1519 tevent_req_nterror(req, status);
1520 return;
1522 state->cli->vuid = -1;
1523 tevent_req_done(req);
1526 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1528 return tevent_req_simple_recv_ntstatus(req);
1531 NTSTATUS cli_ulogoff(struct cli_state *cli)
1533 struct tevent_context *ev;
1534 struct tevent_req *req;
1535 NTSTATUS status = NT_STATUS_NO_MEMORY;
1537 if (cli_has_async_calls(cli)) {
1538 return NT_STATUS_INVALID_PARAMETER;
1540 ev = tevent_context_init(talloc_tos());
1541 if (ev == NULL) {
1542 goto fail;
1544 req = cli_ulogoff_send(ev, ev, cli);
1545 if (req == NULL) {
1546 goto fail;
1548 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1549 goto fail;
1551 status = cli_ulogoff_recv(req);
1552 fail:
1553 TALLOC_FREE(ev);
1554 if (!NT_STATUS_IS_OK(status)) {
1555 cli_set_error(cli, status);
1557 return status;
1560 /****************************************************************************
1561 Send a tconX.
1562 ****************************************************************************/
1564 struct cli_tcon_andx_state {
1565 struct cli_state *cli;
1566 uint16_t vwv[4];
1567 struct iovec bytes;
1570 static void cli_tcon_andx_done(struct tevent_req *subreq);
1572 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1573 struct event_context *ev,
1574 struct cli_state *cli,
1575 const char *share, const char *dev,
1576 const char *pass, int passlen,
1577 struct tevent_req **psmbreq)
1579 struct tevent_req *req, *subreq;
1580 struct cli_tcon_andx_state *state;
1581 fstring pword;
1582 uint16_t *vwv;
1583 char *tmp = NULL;
1584 uint8_t *bytes;
1586 *psmbreq = NULL;
1588 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1589 if (req == NULL) {
1590 return NULL;
1592 state->cli = cli;
1593 vwv = state->vwv;
1595 fstrcpy(cli->share, share);
1597 /* in user level security don't send a password now */
1598 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1599 passlen = 1;
1600 pass = "";
1601 } else if (pass == NULL) {
1602 DEBUG(1, ("Server not using user level security and no "
1603 "password supplied.\n"));
1604 goto access_denied;
1607 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1608 *pass && passlen != 24) {
1609 if (!lp_client_lanman_auth()) {
1610 DEBUG(1, ("Server requested LANMAN password "
1611 "(share-level security) but "
1612 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
1613 goto access_denied;
1617 * Non-encrypted passwords - convert to DOS codepage before
1618 * encryption.
1620 passlen = 24;
1621 SMBencrypt(pass, cli->secblob.data, (uchar *)pword);
1622 } else {
1623 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1624 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1625 == 0) {
1626 if (!lp_client_plaintext_auth() && (*pass)) {
1627 DEBUG(1, ("Server requested plaintext "
1628 "password but "
1629 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
1630 goto access_denied;
1634 * Non-encrypted passwords - convert to DOS codepage
1635 * before using.
1637 passlen = clistr_push(cli, pword, pass, sizeof(pword),
1638 STR_TERMINATE);
1639 if (passlen == -1) {
1640 DEBUG(1, ("clistr_push(pword) failed\n"));
1641 goto access_denied;
1643 } else {
1644 if (passlen) {
1645 memcpy(pword, pass, passlen);
1650 SCVAL(vwv+0, 0, 0xFF);
1651 SCVAL(vwv+0, 1, 0);
1652 SSVAL(vwv+1, 0, 0);
1653 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
1654 SSVAL(vwv+3, 0, passlen);
1656 if (passlen) {
1657 bytes = (uint8_t *)talloc_memdup(state, pword, passlen);
1658 } else {
1659 bytes = talloc_array(state, uint8_t, 0);
1663 * Add the sharename
1665 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1666 cli->desthost, share);
1667 if (tmp == NULL) {
1668 TALLOC_FREE(req);
1669 return NULL;
1671 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
1672 NULL);
1673 TALLOC_FREE(tmp);
1676 * Add the devicetype
1678 tmp = talloc_strdup_upper(talloc_tos(), dev);
1679 if (tmp == NULL) {
1680 TALLOC_FREE(req);
1681 return NULL;
1683 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
1684 TALLOC_FREE(tmp);
1686 if (bytes == NULL) {
1687 TALLOC_FREE(req);
1688 return NULL;
1691 state->bytes.iov_base = (void *)bytes;
1692 state->bytes.iov_len = talloc_get_size(bytes);
1694 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
1695 1, &state->bytes);
1696 if (subreq == NULL) {
1697 TALLOC_FREE(req);
1698 return NULL;
1700 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
1701 *psmbreq = subreq;
1702 return req;
1704 access_denied:
1705 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1706 return tevent_req_post(req, ev);
1709 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
1710 struct event_context *ev,
1711 struct cli_state *cli,
1712 const char *share, const char *dev,
1713 const char *pass, int passlen)
1715 struct tevent_req *req, *subreq;
1716 NTSTATUS status;
1718 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
1719 &subreq);
1720 if (req == NULL) {
1721 return NULL;
1723 if (subreq == NULL) {
1724 return req;
1726 status = cli_smb_req_send(subreq);
1727 if (!NT_STATUS_IS_OK(status)) {
1728 tevent_req_nterror(req, status);
1729 return tevent_req_post(req, ev);
1731 return req;
1734 static void cli_tcon_andx_done(struct tevent_req *subreq)
1736 struct tevent_req *req = tevent_req_callback_data(
1737 subreq, struct tevent_req);
1738 struct cli_tcon_andx_state *state = tevent_req_data(
1739 req, struct cli_tcon_andx_state);
1740 struct cli_state *cli = state->cli;
1741 uint8_t *in;
1742 char *inbuf;
1743 uint8_t wct;
1744 uint16_t *vwv;
1745 uint32_t num_bytes;
1746 uint8_t *bytes;
1747 NTSTATUS status;
1749 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
1750 &num_bytes, &bytes);
1751 TALLOC_FREE(subreq);
1752 if (!NT_STATUS_IS_OK(status)) {
1753 tevent_req_nterror(req, status);
1754 return;
1757 inbuf = (char *)in;
1759 clistr_pull(inbuf, cli->dev, bytes, sizeof(fstring), num_bytes,
1760 STR_TERMINATE|STR_ASCII);
1762 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
1763 /* almost certainly win95 - enable bug fixes */
1764 cli->win95 = True;
1768 * Make sure that we have the optional support 16-bit field. WCT > 2.
1769 * Avoids issues when connecting to Win9x boxes sharing files
1772 cli->dfsroot = false;
1774 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
1775 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
1778 cli->cnum = SVAL(inbuf,smb_tid);
1779 tevent_req_done(req);
1782 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
1784 return tevent_req_simple_recv_ntstatus(req);
1787 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
1788 const char *dev, const char *pass, int passlen)
1790 TALLOC_CTX *frame = talloc_stackframe();
1791 struct event_context *ev;
1792 struct tevent_req *req;
1793 NTSTATUS status = NT_STATUS_OK;
1795 if (cli_has_async_calls(cli)) {
1797 * Can't use sync call while an async call is in flight
1799 status = NT_STATUS_INVALID_PARAMETER;
1800 goto fail;
1803 ev = event_context_init(frame);
1804 if (ev == NULL) {
1805 status = NT_STATUS_NO_MEMORY;
1806 goto fail;
1809 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
1810 if (req == NULL) {
1811 status = NT_STATUS_NO_MEMORY;
1812 goto fail;
1815 if (!tevent_req_poll(req, ev)) {
1816 status = map_nt_error_from_unix(errno);
1817 goto fail;
1820 status = cli_tcon_andx_recv(req);
1821 fail:
1822 TALLOC_FREE(frame);
1823 if (!NT_STATUS_IS_OK(status)) {
1824 cli_set_error(cli, status);
1826 return status;
1829 /****************************************************************************
1830 Send a tree disconnect.
1831 ****************************************************************************/
1833 struct cli_tdis_state {
1834 struct cli_state *cli;
1837 static void cli_tdis_done(struct tevent_req *subreq);
1839 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
1840 struct tevent_context *ev,
1841 struct cli_state *cli)
1843 struct tevent_req *req, *subreq;
1844 struct cli_tdis_state *state;
1846 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
1847 if (req == NULL) {
1848 return NULL;
1850 state->cli = cli;
1852 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
1853 if (tevent_req_nomem(subreq, req)) {
1854 return tevent_req_post(req, ev);
1856 tevent_req_set_callback(subreq, cli_tdis_done, req);
1857 return req;
1860 static void cli_tdis_done(struct tevent_req *subreq)
1862 struct tevent_req *req = tevent_req_callback_data(
1863 subreq, struct tevent_req);
1864 struct cli_tdis_state *state = tevent_req_data(
1865 req, struct cli_tdis_state);
1866 NTSTATUS status;
1868 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1869 TALLOC_FREE(subreq);
1870 if (!NT_STATUS_IS_OK(status)) {
1871 tevent_req_nterror(req, status);
1872 return;
1874 state->cli->cnum = -1;
1875 tevent_req_done(req);
1878 NTSTATUS cli_tdis_recv(struct tevent_req *req)
1880 return tevent_req_simple_recv_ntstatus(req);
1883 NTSTATUS cli_tdis(struct cli_state *cli)
1885 struct tevent_context *ev;
1886 struct tevent_req *req;
1887 NTSTATUS status = NT_STATUS_NO_MEMORY;
1889 if (cli_has_async_calls(cli)) {
1890 return NT_STATUS_INVALID_PARAMETER;
1892 ev = tevent_context_init(talloc_tos());
1893 if (ev == NULL) {
1894 goto fail;
1896 req = cli_tdis_send(ev, ev, cli);
1897 if (req == NULL) {
1898 goto fail;
1900 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1901 goto fail;
1903 status = cli_tdis_recv(req);
1904 fail:
1905 TALLOC_FREE(ev);
1906 if (!NT_STATUS_IS_OK(status)) {
1907 cli_set_error(cli, status);
1909 return status;
1912 /****************************************************************************
1913 Send a negprot command.
1914 ****************************************************************************/
1916 void cli_negprot_sendsync(struct cli_state *cli)
1918 char *p;
1919 int numprots;
1921 if (cli->protocol < PROTOCOL_NT1)
1922 cli->use_spnego = False;
1924 memset(cli->outbuf,'\0',smb_size);
1926 /* setup the protocol strings */
1927 cli_set_message(cli->outbuf,0,0,True);
1929 p = smb_buf(cli->outbuf);
1930 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1931 if (prots[numprots].prot > cli->protocol) {
1932 break;
1934 *p++ = 2;
1935 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1938 SCVAL(cli->outbuf,smb_com,SMBnegprot);
1939 cli_setup_bcc(cli, p);
1940 cli_setup_packet(cli);
1942 SCVAL(smb_buf(cli->outbuf),0,2);
1944 cli_send_smb(cli);
1947 /****************************************************************************
1948 Send a negprot command.
1949 ****************************************************************************/
1951 struct cli_negprot_state {
1952 struct cli_state *cli;
1955 static void cli_negprot_done(struct tevent_req *subreq);
1957 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
1958 struct event_context *ev,
1959 struct cli_state *cli)
1961 struct tevent_req *req, *subreq;
1962 struct cli_negprot_state *state;
1963 uint8_t *bytes = NULL;
1964 int numprots;
1965 uint16_t cnum;
1967 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
1968 if (req == NULL) {
1969 return NULL;
1971 state->cli = cli;
1973 if (cli->protocol < PROTOCOL_NT1)
1974 cli->use_spnego = False;
1976 /* setup the protocol strings */
1977 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1978 uint8_t c = 2;
1979 if (prots[numprots].prot > cli->protocol) {
1980 break;
1982 bytes = (uint8_t *)talloc_append_blob(
1983 state, bytes, data_blob_const(&c, sizeof(c)));
1984 if (tevent_req_nomem(bytes, req)) {
1985 return tevent_req_post(req, ev);
1987 bytes = smb_bytes_push_str(bytes, false,
1988 prots[numprots].name,
1989 strlen(prots[numprots].name)+1,
1990 NULL);
1991 if (tevent_req_nomem(bytes, req)) {
1992 return tevent_req_post(req, ev);
1996 cnum = cli->cnum;
1998 cli->cnum = 0;
1999 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2000 talloc_get_size(bytes), bytes);
2001 cli->cnum = cnum;
2003 if (tevent_req_nomem(subreq, req)) {
2004 return tevent_req_post(req, ev);
2006 tevent_req_set_callback(subreq, cli_negprot_done, req);
2007 return req;
2010 static void cli_negprot_done(struct tevent_req *subreq)
2012 struct tevent_req *req = tevent_req_callback_data(
2013 subreq, struct tevent_req);
2014 struct cli_negprot_state *state = tevent_req_data(
2015 req, struct cli_negprot_state);
2016 struct cli_state *cli = state->cli;
2017 uint8_t wct;
2018 uint16_t *vwv;
2019 uint32_t num_bytes;
2020 uint8_t *bytes;
2021 NTSTATUS status;
2022 uint16_t protnum;
2023 uint8_t *inbuf;
2025 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
2026 &num_bytes, &bytes);
2027 TALLOC_FREE(subreq);
2028 if (!NT_STATUS_IS_OK(status)) {
2029 tevent_req_nterror(req, status);
2030 return;
2033 protnum = SVAL(vwv, 0);
2035 if ((protnum >= ARRAY_SIZE(prots))
2036 || (prots[protnum].prot > cli->protocol)) {
2037 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2038 return;
2041 cli->protocol = prots[protnum].prot;
2043 if ((cli->protocol < PROTOCOL_NT1) &&
2044 client_is_signing_mandatory(cli)) {
2045 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2046 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2047 return;
2050 if (cli->protocol >= PROTOCOL_NT1) {
2051 struct timespec ts;
2052 bool negotiated_smb_signing = false;
2054 /* NT protocol */
2055 cli->sec_mode = CVAL(vwv + 1, 0);
2056 cli->max_mux = SVAL(vwv + 1, 1);
2057 cli->max_xmit = IVAL(vwv + 3, 1);
2058 cli->sesskey = IVAL(vwv + 7, 1);
2059 cli->serverzone = SVALS(vwv + 15, 1);
2060 cli->serverzone *= 60;
2061 /* this time arrives in real GMT */
2062 ts = interpret_long_date(((char *)(vwv+11))+1);
2063 cli->servertime = ts.tv_sec;
2064 cli->secblob = data_blob(bytes, num_bytes);
2065 cli->capabilities = IVAL(vwv + 9, 1);
2066 if (cli->capabilities & CAP_RAW_MODE) {
2067 cli->readbraw_supported = True;
2068 cli->writebraw_supported = True;
2070 /* work out if they sent us a workgroup */
2071 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
2072 smb_buflen(cli->inbuf) > 8) {
2073 clistr_pull(cli->inbuf, cli->server_domain,
2074 bytes+8, sizeof(cli->server_domain),
2075 num_bytes-8,
2076 STR_UNICODE|STR_NOALIGN);
2080 * As signing is slow we only turn it on if either the client or
2081 * the server require it. JRA.
2084 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2085 /* Fail if server says signing is mandatory and we don't want to support it. */
2086 if (!client_is_signing_allowed(cli)) {
2087 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
2088 tevent_req_nterror(req,
2089 NT_STATUS_ACCESS_DENIED);
2090 return;
2092 negotiated_smb_signing = true;
2093 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
2094 /* Fail if client says signing is mandatory and the server doesn't support it. */
2095 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
2096 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
2097 tevent_req_nterror(req,
2098 NT_STATUS_ACCESS_DENIED);
2099 return;
2101 negotiated_smb_signing = true;
2102 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2103 negotiated_smb_signing = true;
2106 if (negotiated_smb_signing) {
2107 cli_set_signing_negotiated(cli);
2110 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
2111 SAFE_FREE(cli->outbuf);
2112 SAFE_FREE(cli->inbuf);
2113 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2114 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2115 if (!cli->outbuf || !cli->inbuf) {
2116 tevent_req_nterror(req,
2117 NT_STATUS_NO_MEMORY);
2118 return;
2120 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
2123 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2124 cli->use_spnego = False;
2125 cli->sec_mode = SVAL(vwv + 1, 0);
2126 cli->max_xmit = SVAL(vwv + 2, 0);
2127 cli->max_mux = SVAL(vwv + 3, 0);
2128 cli->sesskey = IVAL(vwv + 6, 0);
2129 cli->serverzone = SVALS(vwv + 10, 0);
2130 cli->serverzone *= 60;
2131 /* this time is converted to GMT by make_unix_date */
2132 cli->servertime = make_unix_date(
2133 (char *)(vwv + 8), cli->serverzone);
2134 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2135 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2136 cli->secblob = data_blob(bytes, num_bytes);
2137 } else {
2138 /* the old core protocol */
2139 cli->use_spnego = False;
2140 cli->sec_mode = 0;
2141 cli->serverzone = get_time_zone(time(NULL));
2144 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2146 /* a way to force ascii SMB */
2147 if (getenv("CLI_FORCE_ASCII"))
2148 cli->capabilities &= ~CAP_UNICODE;
2150 tevent_req_done(req);
2153 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2155 return tevent_req_simple_recv_ntstatus(req);
2158 NTSTATUS cli_negprot(struct cli_state *cli)
2160 TALLOC_CTX *frame = talloc_stackframe();
2161 struct event_context *ev;
2162 struct tevent_req *req;
2163 NTSTATUS status = NT_STATUS_OK;
2165 if (cli_has_async_calls(cli)) {
2167 * Can't use sync call while an async call is in flight
2169 status = NT_STATUS_INVALID_PARAMETER;
2170 goto fail;
2173 ev = event_context_init(frame);
2174 if (ev == NULL) {
2175 status = NT_STATUS_NO_MEMORY;
2176 goto fail;
2179 req = cli_negprot_send(frame, ev, cli);
2180 if (req == NULL) {
2181 status = NT_STATUS_NO_MEMORY;
2182 goto fail;
2185 if (!tevent_req_poll(req, ev)) {
2186 status = map_nt_error_from_unix(errno);
2187 goto fail;
2190 status = cli_negprot_recv(req);
2191 fail:
2192 TALLOC_FREE(frame);
2193 if (!NT_STATUS_IS_OK(status)) {
2194 cli_set_error(cli, status);
2196 return status;
2199 /****************************************************************************
2200 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
2201 ****************************************************************************/
2203 bool cli_session_request(struct cli_state *cli,
2204 struct nmb_name *calling, struct nmb_name *called)
2206 char *p;
2207 int len = 4;
2208 int namelen = 0;
2209 char *tmp;
2211 /* 445 doesn't have session request */
2212 if (cli->port == 445)
2213 return True;
2215 memcpy(&(cli->calling), calling, sizeof(*calling));
2216 memcpy(&(cli->called ), called , sizeof(*called ));
2218 /* put in the destination name */
2220 tmp = name_mangle(talloc_tos(), cli->called.name,
2221 cli->called.name_type);
2222 if (tmp == NULL) {
2223 return false;
2226 p = cli->outbuf+len;
2227 namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
2228 if (namelen > 0) {
2229 memcpy(p, tmp, namelen);
2230 len += namelen;
2232 TALLOC_FREE(tmp);
2234 /* and my name */
2236 tmp = name_mangle(talloc_tos(), cli->calling.name,
2237 cli->calling.name_type);
2238 if (tmp == NULL) {
2239 return false;
2242 p = cli->outbuf+len;
2243 namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
2244 if (namelen > 0) {
2245 memcpy(p, tmp, namelen);
2246 len += namelen;
2248 TALLOC_FREE(tmp);
2250 /* send a session request (RFC 1002) */
2251 /* setup the packet length
2252 * Remove four bytes from the length count, since the length
2253 * field in the NBT Session Service header counts the number
2254 * of bytes which follow. The cli_send_smb() function knows
2255 * about this and accounts for those four bytes.
2256 * CRH.
2258 len -= 4;
2259 _smb_setlen(cli->outbuf,len);
2260 SCVAL(cli->outbuf,0,0x81);
2262 cli_send_smb(cli);
2263 DEBUG(5,("Sent session request\n"));
2265 if (!cli_receive_smb(cli))
2266 return False;
2268 if (CVAL(cli->inbuf,0) == 0x84) {
2269 /* C. Hoch 9/14/95 Start */
2270 /* For information, here is the response structure.
2271 * We do the byte-twiddling to for portability.
2272 struct RetargetResponse{
2273 unsigned char type;
2274 unsigned char flags;
2275 int16 length;
2276 int32 ip_addr;
2277 int16 port;
2280 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
2281 struct in_addr dest_ip;
2282 NTSTATUS status;
2284 /* SESSION RETARGET */
2285 putip((char *)&dest_ip,cli->inbuf+4);
2286 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
2288 status = open_socket_out(&cli->dest_ss, port,
2289 LONG_CONNECT_TIMEOUT, &cli->fd);
2290 if (!NT_STATUS_IS_OK(status)) {
2291 return False;
2294 DEBUG(3,("Retargeted\n"));
2296 set_socket_options(cli->fd, lp_socket_options());
2298 /* Try again */
2300 static int depth;
2301 bool ret;
2302 if (depth > 4) {
2303 DEBUG(0,("Retarget recursion - failing\n"));
2304 return False;
2306 depth++;
2307 ret = cli_session_request(cli, calling, called);
2308 depth--;
2309 return ret;
2311 } /* C. Hoch 9/14/95 End */
2313 if (CVAL(cli->inbuf,0) != 0x82) {
2314 /* This is the wrong place to put the error... JRA. */
2315 cli->rap_error = CVAL(cli->inbuf,4);
2316 return False;
2318 return(True);
2321 struct fd_struct {
2322 int fd;
2325 static void smb_sock_connected(struct tevent_req *req)
2327 struct fd_struct *pfd = tevent_req_callback_data(
2328 req, struct fd_struct);
2329 int fd;
2330 NTSTATUS status;
2332 status = open_socket_out_defer_recv(req, &fd);
2333 if (NT_STATUS_IS_OK(status)) {
2334 pfd->fd = fd;
2338 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
2339 uint16_t *port, int timeout, int *pfd)
2341 struct event_context *ev;
2342 struct tevent_req *r139, *r445;
2343 struct fd_struct *fd139, *fd445;
2344 NTSTATUS status = NT_STATUS_NO_MEMORY;
2346 if (*port != 0) {
2347 return open_socket_out(pss, *port, timeout, pfd);
2350 ev = event_context_init(talloc_tos());
2351 if (ev == NULL) {
2352 return NT_STATUS_NO_MEMORY;
2355 fd139 = talloc(ev, struct fd_struct);
2356 if (fd139 == NULL) {
2357 goto done;
2359 fd139->fd = -1;
2361 fd445 = talloc(ev, struct fd_struct);
2362 if (fd445 == NULL) {
2363 goto done;
2365 fd445->fd = -1;
2367 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
2368 pss, 445, timeout);
2369 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
2370 pss, 139, timeout);
2371 if ((r445 == NULL) || (r139 == NULL)) {
2372 goto done;
2374 tevent_req_set_callback(r445, smb_sock_connected, fd445);
2375 tevent_req_set_callback(r139, smb_sock_connected, fd139);
2377 while ((fd445->fd == -1) && (fd139->fd == -1)
2378 && (tevent_req_is_in_progress(r139)
2379 || tevent_req_is_in_progress(r445))) {
2380 event_loop_once(ev);
2383 if ((fd139->fd != -1) && (fd445->fd != -1)) {
2384 close(fd139->fd);
2385 fd139->fd = -1;
2388 if (fd445->fd != -1) {
2389 *port = 445;
2390 *pfd = fd445->fd;
2391 status = NT_STATUS_OK;
2392 goto done;
2394 if (fd139->fd != -1) {
2395 *port = 139;
2396 *pfd = fd139->fd;
2397 status = NT_STATUS_OK;
2398 goto done;
2401 status = open_socket_out_defer_recv(r445, &fd445->fd);
2402 done:
2403 TALLOC_FREE(ev);
2404 return status;
2407 /****************************************************************************
2408 Open the client sockets.
2409 ****************************************************************************/
2411 NTSTATUS cli_connect(struct cli_state *cli,
2412 const char *host,
2413 struct sockaddr_storage *dest_ss)
2416 int name_type = 0x20;
2417 TALLOC_CTX *frame = talloc_stackframe();
2418 unsigned int num_addrs = 0;
2419 unsigned int i = 0;
2420 struct sockaddr_storage *ss_arr = NULL;
2421 char *p = NULL;
2423 /* reasonable default hostname */
2424 if (!host) {
2425 host = STAR_SMBSERVER;
2428 fstrcpy(cli->desthost, host);
2430 /* allow hostnames of the form NAME#xx and do a netbios lookup */
2431 if ((p = strchr(cli->desthost, '#'))) {
2432 name_type = strtol(p+1, NULL, 16);
2433 *p = 0;
2436 if (!dest_ss || is_zero_addr(dest_ss)) {
2437 NTSTATUS status =resolve_name_list(frame,
2438 cli->desthost,
2439 name_type,
2440 &ss_arr,
2441 &num_addrs);
2442 if (!NT_STATUS_IS_OK(status)) {
2443 TALLOC_FREE(frame);
2444 return NT_STATUS_BAD_NETWORK_NAME;
2446 } else {
2447 num_addrs = 1;
2448 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
2449 if (!ss_arr) {
2450 TALLOC_FREE(frame);
2451 return NT_STATUS_NO_MEMORY;
2453 *ss_arr = *dest_ss;
2456 for (i = 0; i < num_addrs; i++) {
2457 cli->dest_ss = ss_arr[i];
2458 if (getenv("LIBSMB_PROG")) {
2459 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
2460 } else {
2461 uint16_t port = cli->port;
2462 NTSTATUS status;
2463 status = open_smb_socket(&cli->dest_ss, &port,
2464 cli->timeout, &cli->fd);
2465 if (NT_STATUS_IS_OK(status)) {
2466 cli->port = port;
2469 if (cli->fd == -1) {
2470 char addr[INET6_ADDRSTRLEN];
2471 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
2472 DEBUG(2,("Error connecting to %s (%s)\n",
2473 dest_ss?addr:host,strerror(errno)));
2474 } else {
2475 /* Exit from loop on first connection. */
2476 break;
2480 if (cli->fd == -1) {
2481 TALLOC_FREE(frame);
2482 return map_nt_error_from_unix(errno);
2485 if (dest_ss) {
2486 *dest_ss = cli->dest_ss;
2489 set_socket_options(cli->fd, lp_socket_options());
2491 TALLOC_FREE(frame);
2492 return NT_STATUS_OK;
2496 establishes a connection to after the negprot.
2497 @param output_cli A fully initialised cli structure, non-null only on success
2498 @param dest_host The netbios name of the remote host
2499 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2500 @param port (optional) The destination port (0 for default)
2502 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2503 const char *my_name,
2504 const char *dest_host,
2505 struct sockaddr_storage *dest_ss, int port,
2506 int signing_state, int flags)
2508 NTSTATUS nt_status;
2509 struct nmb_name calling;
2510 struct nmb_name called;
2511 struct cli_state *cli;
2512 struct sockaddr_storage ss;
2514 if (!my_name)
2515 my_name = global_myname();
2517 if (!(cli = cli_initialise_ex(signing_state))) {
2518 return NT_STATUS_NO_MEMORY;
2521 make_nmb_name(&calling, my_name, 0x0);
2522 make_nmb_name(&called , dest_host, 0x20);
2524 cli_set_port(cli, port);
2525 cli_set_timeout(cli, 10000); /* 10 seconds. */
2527 if (dest_ss) {
2528 ss = *dest_ss;
2529 } else {
2530 zero_sockaddr(&ss);
2533 again:
2535 DEBUG(3,("Connecting to host=%s\n", dest_host));
2537 nt_status = cli_connect(cli, dest_host, &ss);
2538 if (!NT_STATUS_IS_OK(nt_status)) {
2539 char addr[INET6_ADDRSTRLEN];
2540 print_sockaddr(addr, sizeof(addr), &ss);
2541 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
2542 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
2543 cli_shutdown(cli);
2544 return nt_status;
2547 if (!cli_session_request(cli, &calling, &called)) {
2548 char *p;
2549 DEBUG(1,("session request to %s failed (%s)\n",
2550 called.name, cli_errstr(cli)));
2551 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
2552 *p = 0;
2553 goto again;
2555 if (strcmp(called.name, STAR_SMBSERVER)) {
2556 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
2557 goto again;
2559 return NT_STATUS_BAD_NETWORK_NAME;
2562 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
2563 cli->use_spnego = False;
2564 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
2565 cli->use_kerberos = True;
2567 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
2568 cli->use_kerberos) {
2569 cli->fallback_after_kerberos = true;
2571 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
2572 cli->use_ccache = true;
2575 nt_status = cli_negprot(cli);
2576 if (!NT_STATUS_IS_OK(nt_status)) {
2577 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2578 cli_shutdown(cli);
2579 return nt_status;
2582 *output_cli = cli;
2583 return NT_STATUS_OK;
2588 establishes a connection right up to doing tconX, password specified.
2589 @param output_cli A fully initialised cli structure, non-null only on success
2590 @param dest_host The netbios name of the remote host
2591 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2592 @param port (optional) The destination port (0 for default)
2593 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2594 @param service_type The 'type' of serivice.
2595 @param user Username, unix string
2596 @param domain User's domain
2597 @param password User's password, unencrypted unix string.
2600 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2601 const char *my_name,
2602 const char *dest_host,
2603 struct sockaddr_storage *dest_ss, int port,
2604 const char *service, const char *service_type,
2605 const char *user, const char *domain,
2606 const char *password, int flags,
2607 int signing_state)
2609 NTSTATUS nt_status;
2610 struct cli_state *cli = NULL;
2611 int pw_len = password ? strlen(password)+1 : 0;
2613 *output_cli = NULL;
2615 if (password == NULL) {
2616 password = "";
2619 nt_status = cli_start_connection(&cli, my_name, dest_host,
2620 dest_ss, port, signing_state,
2621 flags);
2623 if (!NT_STATUS_IS_OK(nt_status)) {
2624 return nt_status;
2627 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
2628 cli->use_level_II_oplocks =
2629 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
2631 nt_status = cli_session_setup(cli, user, password, pw_len, password,
2632 pw_len, domain);
2633 if (!NT_STATUS_IS_OK(nt_status)) {
2635 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2636 DEBUG(1,("failed session setup with %s\n",
2637 nt_errstr(nt_status)));
2638 cli_shutdown(cli);
2639 return nt_status;
2642 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2643 if (!NT_STATUS_IS_OK(nt_status)) {
2644 DEBUG(1,("anonymous failed session setup with %s\n",
2645 nt_errstr(nt_status)));
2646 cli_shutdown(cli);
2647 return nt_status;
2651 if (service) {
2652 nt_status = cli_tcon_andx(cli, service, service_type, password,
2653 pw_len);
2654 if (!NT_STATUS_IS_OK(nt_status)) {
2655 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2656 cli_shutdown(cli);
2657 if (NT_STATUS_IS_OK(nt_status)) {
2658 nt_status = NT_STATUS_UNSUCCESSFUL;
2660 return nt_status;
2664 nt_status = cli_init_creds(cli, user, domain, password);
2665 if (!NT_STATUS_IS_OK(nt_status)) {
2666 cli_shutdown(cli);
2667 return nt_status;
2670 *output_cli = cli;
2671 return NT_STATUS_OK;
2674 /****************************************************************************
2675 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2676 ****************************************************************************/
2678 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
2679 struct sockaddr_storage *pdest_ss)
2681 struct nmb_name calling, called;
2683 make_nmb_name(&calling, srchost, 0x0);
2686 * If the called name is an IP address
2687 * then use *SMBSERVER immediately.
2690 if(is_ipaddress(desthost)) {
2691 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
2692 } else {
2693 make_nmb_name(&called, desthost, 0x20);
2696 if (!cli_session_request(*ppcli, &calling, &called)) {
2697 NTSTATUS status;
2698 struct nmb_name smbservername;
2700 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
2703 * If the name wasn't *SMBSERVER then
2704 * try with *SMBSERVER if the first name fails.
2707 if (nmb_name_equal(&called, &smbservername)) {
2710 * The name used was *SMBSERVER, don't bother with another name.
2713 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2714 with error %s.\n", desthost, cli_errstr(*ppcli) ));
2715 return False;
2718 /* Try again... */
2719 cli_shutdown(*ppcli);
2721 *ppcli = cli_initialise();
2722 if (!*ppcli) {
2723 /* Out of memory... */
2724 return False;
2727 status = cli_connect(*ppcli, desthost, pdest_ss);
2728 if (!NT_STATUS_IS_OK(status) ||
2729 !cli_session_request(*ppcli, &calling, &smbservername)) {
2730 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2731 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
2732 return False;
2736 return True;
2739 /****************************************************************************
2740 Send an old style tcon.
2741 ****************************************************************************/
2742 NTSTATUS cli_raw_tcon(struct cli_state *cli,
2743 const char *service, const char *pass, const char *dev,
2744 uint16 *max_xmit, uint16 *tid)
2746 char *p;
2748 if (!lp_client_plaintext_auth() && (*pass)) {
2749 DEBUG(1, ("Server requested plaintext password but 'client "
2750 "plaintext auth' is disabled\n"));
2751 return NT_STATUS_ACCESS_DENIED;
2754 memset(cli->outbuf,'\0',smb_size);
2755 memset(cli->inbuf,'\0',smb_size);
2757 cli_set_message(cli->outbuf, 0, 0, True);
2758 SCVAL(cli->outbuf,smb_com,SMBtcon);
2759 cli_setup_packet(cli);
2761 p = smb_buf(cli->outbuf);
2762 *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
2763 *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
2764 *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
2766 cli_setup_bcc(cli, p);
2768 cli_send_smb(cli);
2769 if (!cli_receive_smb(cli)) {
2770 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2773 if (cli_is_error(cli)) {
2774 return cli_nt_error(cli);
2777 *max_xmit = SVAL(cli->inbuf, smb_vwv0);
2778 *tid = SVAL(cli->inbuf, smb_vwv1);
2780 return NT_STATUS_OK;
2783 /* Return a cli_state pointing at the IPC$ share for the given server */
2785 struct cli_state *get_ipc_connect(char *server,
2786 struct sockaddr_storage *server_ss,
2787 const struct user_auth_info *user_info)
2789 struct cli_state *cli;
2790 NTSTATUS nt_status;
2791 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2793 if (user_info->use_kerberos) {
2794 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2797 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
2798 user_info->username ? user_info->username : "",
2799 lp_workgroup(),
2800 user_info->password ? user_info->password : "",
2801 flags,
2802 Undefined);
2804 if (NT_STATUS_IS_OK(nt_status)) {
2805 return cli;
2806 } else if (is_ipaddress(server)) {
2807 /* windows 9* needs a correct NMB name for connections */
2808 fstring remote_name;
2810 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2811 cli = get_ipc_connect(remote_name, server_ss, user_info);
2812 if (cli)
2813 return cli;
2816 return NULL;
2820 * Given the IP address of a master browser on the network, return its
2821 * workgroup and connect to it.
2823 * This function is provided to allow additional processing beyond what
2824 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2825 * browsers and obtain each master browsers' list of domains (in case the
2826 * first master browser is recently on the network and has not yet
2827 * synchronized with other master browsers and therefore does not yet have the
2828 * entire network browse list)
2831 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2832 struct ip_service *mb_ip,
2833 const struct user_auth_info *user_info,
2834 char **pp_workgroup_out)
2836 char addr[INET6_ADDRSTRLEN];
2837 fstring name;
2838 struct cli_state *cli;
2839 struct sockaddr_storage server_ss;
2841 *pp_workgroup_out = NULL;
2843 print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2844 DEBUG(99, ("Looking up name of master browser %s\n",
2845 addr));
2848 * Do a name status query to find out the name of the master browser.
2849 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2850 * master browser will not respond to a wildcard query (or, at least,
2851 * an NT4 server acting as the domain master browser will not).
2853 * We might be able to use ONLY the query on MSBROWSE, but that's not
2854 * yet been tested with all Windows versions, so until it is, leave
2855 * the original wildcard query as the first choice and fall back to
2856 * MSBROWSE if the wildcard query fails.
2858 if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2859 !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2861 DEBUG(99, ("Could not retrieve name status for %s\n",
2862 addr));
2863 return NULL;
2866 if (!find_master_ip(name, &server_ss)) {
2867 DEBUG(99, ("Could not find master ip for %s\n", name));
2868 return NULL;
2871 *pp_workgroup_out = talloc_strdup(ctx, name);
2873 DEBUG(4, ("found master browser %s, %s\n", name, addr));
2875 print_sockaddr(addr, sizeof(addr), &server_ss);
2876 cli = get_ipc_connect(addr, &server_ss, user_info);
2878 return cli;
2882 * Return the IP address and workgroup of a master browser on the network, and
2883 * connect to it.
2886 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2887 const struct user_auth_info *user_info,
2888 char **pp_workgroup_out)
2890 struct ip_service *ip_list;
2891 struct cli_state *cli;
2892 int i, count;
2894 *pp_workgroup_out = NULL;
2896 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2898 /* Go looking for workgroups by broadcasting on the local network */
2900 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2901 &count))) {
2902 DEBUG(99, ("No master browsers responded\n"));
2903 return False;
2906 for (i = 0; i < count; i++) {
2907 char addr[INET6_ADDRSTRLEN];
2908 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2909 DEBUG(99, ("Found master browser %s\n", addr));
2911 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2912 user_info, pp_workgroup_out);
2913 if (cli)
2914 return(cli);
2917 return NULL;