s3: guest sesssetup is only 13 words
[Samba.git] / source3 / libsmb / cliconnect.c
blobe3d97b60fa7c656819824d1a5b2939a772223fb3
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"
30 #include "libsmb/nmblib.h"
32 static const struct {
33 int prot;
34 const char name[24];
35 } prots[10] = {
36 {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
37 {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
38 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
39 {PROTOCOL_LANMAN1, "LANMAN1.0"},
40 {PROTOCOL_LANMAN2, "LM1.2X002"},
41 {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
42 {PROTOCOL_LANMAN2, "LANMAN2.1"},
43 {PROTOCOL_LANMAN2, "Samba"},
44 {PROTOCOL_NT1, "NT LANMAN 1.0"},
45 {PROTOCOL_NT1, "NT LM 0.12"},
48 #define STAR_SMBSERVER "*SMBSERVER"
50 /**
51 * Set the user session key for a connection
52 * @param cli The cli structure to add it too
53 * @param session_key The session key used. (A copy of this is taken for the cli struct)
57 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
59 cli->user_session_key = data_blob(session_key.data, session_key.length);
62 /****************************************************************************
63 Do an old lanman2 style session setup.
64 ****************************************************************************/
66 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
67 const char *user,
68 const char *pass, size_t passlen,
69 const char *workgroup)
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;
145 return NT_STATUS_OK;
148 /****************************************************************************
149 Work out suitable capabilities to offer the server.
150 ****************************************************************************/
152 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
154 uint32 capabilities = CAP_NT_SMBS;
156 if (!cli->force_dos_errors)
157 capabilities |= CAP_STATUS32;
159 if (cli->use_level_II_oplocks)
160 capabilities |= CAP_LEVEL_II_OPLOCKS;
162 capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
163 return capabilities;
166 /****************************************************************************
167 Do a NT1 guest session setup.
168 ****************************************************************************/
170 struct cli_session_setup_guest_state {
171 struct cli_state *cli;
172 uint16_t vwv[13];
173 struct iovec bytes;
176 static void cli_session_setup_guest_done(struct tevent_req *subreq);
178 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
179 struct event_context *ev,
180 struct cli_state *cli,
181 struct tevent_req **psmbreq)
183 struct tevent_req *req, *subreq;
184 struct cli_session_setup_guest_state *state;
185 uint16_t *vwv;
186 uint8_t *bytes;
188 req = tevent_req_create(mem_ctx, &state,
189 struct cli_session_setup_guest_state);
190 if (req == NULL) {
191 return NULL;
193 state->cli = cli;
194 vwv = state->vwv;
196 SCVAL(vwv+0, 0, 0xFF);
197 SCVAL(vwv+0, 1, 0);
198 SSVAL(vwv+1, 0, 0);
199 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
200 SSVAL(vwv+3, 0, 2);
201 SSVAL(vwv+4, 0, cli->pid);
202 SIVAL(vwv+5, 0, cli->sesskey);
203 SSVAL(vwv+7, 0, 0);
204 SSVAL(vwv+8, 0, 0);
205 SSVAL(vwv+9, 0, 0);
206 SSVAL(vwv+10, 0, 0);
207 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
209 bytes = talloc_array(state, uint8_t, 0);
211 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
212 NULL);
213 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
214 NULL);
215 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
216 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
218 if (bytes == NULL) {
219 TALLOC_FREE(req);
220 return NULL;
223 state->bytes.iov_base = (void *)bytes;
224 state->bytes.iov_len = talloc_get_size(bytes);
226 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
227 1, &state->bytes);
228 if (subreq == NULL) {
229 TALLOC_FREE(req);
230 return NULL;
232 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
233 *psmbreq = subreq;
234 return req;
237 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
238 struct event_context *ev,
239 struct cli_state *cli)
241 struct tevent_req *req, *subreq;
242 NTSTATUS status;
244 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
245 if (req == NULL) {
246 return NULL;
249 status = cli_smb_req_send(subreq);
250 if (NT_STATUS_IS_OK(status)) {
251 tevent_req_nterror(req, status);
252 return tevent_req_post(req, ev);
254 return req;
257 static void cli_session_setup_guest_done(struct tevent_req *subreq)
259 struct tevent_req *req = tevent_req_callback_data(
260 subreq, struct tevent_req);
261 struct cli_session_setup_guest_state *state = tevent_req_data(
262 req, struct cli_session_setup_guest_state);
263 struct cli_state *cli = state->cli;
264 uint32_t num_bytes;
265 uint8_t *in;
266 char *inbuf;
267 uint8_t *bytes;
268 uint8_t *p;
269 NTSTATUS status;
271 status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
272 &num_bytes, &bytes);
273 TALLOC_FREE(subreq);
274 if (!NT_STATUS_IS_OK(status)) {
275 tevent_req_nterror(req, status);
276 return;
279 inbuf = (char *)in;
280 p = bytes;
282 cli->vuid = SVAL(inbuf, smb_uid);
284 p += clistr_pull(inbuf, cli->server_os, (char *)p, sizeof(fstring),
285 bytes+num_bytes-p, STR_TERMINATE);
286 p += clistr_pull(inbuf, cli->server_type, (char *)p, sizeof(fstring),
287 bytes+num_bytes-p, STR_TERMINATE);
288 p += clistr_pull(inbuf, cli->server_domain, (char *)p, sizeof(fstring),
289 bytes+num_bytes-p, STR_TERMINATE);
291 if (strstr(cli->server_type, "Samba")) {
292 cli->is_samba = True;
295 status = cli_set_username(cli, "");
296 if (!NT_STATUS_IS_OK(status)) {
297 tevent_req_nterror(req, status);
298 return;
300 tevent_req_done(req);
303 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
305 return tevent_req_simple_recv_ntstatus(req);
308 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
310 TALLOC_CTX *frame = talloc_stackframe();
311 struct event_context *ev;
312 struct tevent_req *req;
313 NTSTATUS status = NT_STATUS_OK;
315 if (cli_has_async_calls(cli)) {
317 * Can't use sync call while an async call is in flight
319 status = NT_STATUS_INVALID_PARAMETER;
320 goto fail;
323 ev = event_context_init(frame);
324 if (ev == NULL) {
325 status = NT_STATUS_NO_MEMORY;
326 goto fail;
329 req = cli_session_setup_guest_send(frame, ev, cli);
330 if (req == NULL) {
331 status = NT_STATUS_NO_MEMORY;
332 goto fail;
335 if (!tevent_req_poll(req, ev)) {
336 status = map_nt_error_from_unix(errno);
337 goto fail;
340 status = cli_session_setup_guest_recv(req);
341 fail:
342 TALLOC_FREE(frame);
343 if (!NT_STATUS_IS_OK(status)) {
344 cli_set_error(cli, status);
346 return status;
349 /****************************************************************************
350 Do a NT1 plaintext session setup.
351 ****************************************************************************/
353 static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
354 const char *user, const char *pass,
355 const char *workgroup)
357 uint32 capabilities = cli_session_setup_capabilities(cli);
358 char *p;
359 NTSTATUS status;
360 fstring lanman;
362 fstr_sprintf( lanman, "Samba %s", samba_version_string());
364 memset(cli->outbuf, '\0', smb_size);
365 cli_set_message(cli->outbuf,13,0,True);
366 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
367 cli_setup_packet(cli);
369 SCVAL(cli->outbuf,smb_vwv0,0xFF);
370 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
371 SSVAL(cli->outbuf,smb_vwv3,2);
372 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
373 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
374 SSVAL(cli->outbuf,smb_vwv8,0);
375 SIVAL(cli->outbuf,smb_vwv11,capabilities);
376 p = smb_buf(cli->outbuf);
378 /* check wether to send the ASCII or UNICODE version of the password */
380 if ( (capabilities & CAP_UNICODE) == 0 ) {
381 p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
382 SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
384 else {
385 /* For ucs2 passwords clistr_push calls ucs2_align, which causes
386 * the space taken by the unicode password to be one byte too
387 * long (as we're on an odd byte boundary here). Reduce the
388 * count by 1 to cope with this. Fixes smbclient against NetApp
389 * servers which can't cope. Fix from
390 * bryan.kolodziej@allenlund.com in bug #3840.
392 p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
393 SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))-1);
396 p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
397 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
398 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
399 p += clistr_push(cli, p, lanman, -1, STR_TERMINATE);
400 cli_setup_bcc(cli, p);
402 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
403 return cli_nt_error(cli);
406 show_msg(cli->inbuf);
408 if (cli_is_error(cli)) {
409 return cli_nt_error(cli);
412 cli->vuid = SVAL(cli->inbuf,smb_uid);
413 p = smb_buf(cli->inbuf);
414 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
415 -1, STR_TERMINATE);
416 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
417 -1, STR_TERMINATE);
418 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
419 -1, STR_TERMINATE);
420 status = cli_set_username(cli, user);
421 if (!NT_STATUS_IS_OK(status)) {
422 return status;
424 if (strstr(cli->server_type, "Samba")) {
425 cli->is_samba = True;
428 return NT_STATUS_OK;
431 /****************************************************************************
432 do a NT1 NTLM/LM encrypted session setup - for when extended security
433 is not negotiated.
434 @param cli client state to create do session setup on
435 @param user username
436 @param pass *either* cleartext password (passlen !=24) or LM response.
437 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
438 @param workgroup The user's domain.
439 ****************************************************************************/
441 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
442 const char *pass, size_t passlen,
443 const char *ntpass, size_t ntpasslen,
444 const char *workgroup)
446 uint32 capabilities = cli_session_setup_capabilities(cli);
447 DATA_BLOB lm_response = data_blob_null;
448 DATA_BLOB nt_response = data_blob_null;
449 DATA_BLOB session_key = data_blob_null;
450 NTSTATUS result;
451 char *p;
452 bool ok;
454 if (passlen == 0) {
455 /* do nothing - guest login */
456 } else if (passlen != 24) {
457 if (lp_client_ntlmv2_auth()) {
458 DATA_BLOB server_chal;
459 DATA_BLOB names_blob;
460 server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8));
462 /* note that the 'workgroup' here is a best guess - we don't know
463 the server's domain at this point. The 'server name' is also
464 dodgy...
466 names_blob = NTLMv2_generate_names_blob(NULL, cli->called.name, workgroup);
468 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass, &server_chal,
469 &names_blob,
470 &lm_response, &nt_response, NULL, &session_key)) {
471 data_blob_free(&names_blob);
472 data_blob_free(&server_chal);
473 return NT_STATUS_ACCESS_DENIED;
475 data_blob_free(&names_blob);
476 data_blob_free(&server_chal);
478 } else {
479 uchar nt_hash[16];
480 E_md4hash(pass, nt_hash);
482 #ifdef LANMAN_ONLY
483 nt_response = data_blob_null;
484 #else
485 nt_response = data_blob(NULL, 24);
486 SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
487 #endif
488 /* non encrypted password supplied. Ignore ntpass. */
489 if (lp_client_lanman_auth()) {
490 lm_response = data_blob(NULL, 24);
491 if (!SMBencrypt(pass,cli->secblob.data, lm_response.data)) {
492 /* Oops, the LM response is invalid, just put
493 the NT response there instead */
494 data_blob_free(&lm_response);
495 lm_response = data_blob(nt_response.data, nt_response.length);
497 } else {
498 /* LM disabled, place NT# in LM field instead */
499 lm_response = data_blob(nt_response.data, nt_response.length);
502 session_key = data_blob(NULL, 16);
503 #ifdef LANMAN_ONLY
504 E_deshash(pass, session_key.data);
505 memset(&session_key.data[8], '\0', 8);
506 #else
507 SMBsesskeygen_ntv1(nt_hash, session_key.data);
508 #endif
510 cli_temp_set_signing(cli);
511 } else {
512 /* pre-encrypted password supplied. Only used for
513 security=server, can't do
514 signing because we don't have original key */
516 lm_response = data_blob(pass, passlen);
517 nt_response = data_blob(ntpass, ntpasslen);
520 /* send a session setup command */
521 memset(cli->outbuf,'\0',smb_size);
523 cli_set_message(cli->outbuf,13,0,True);
524 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
525 cli_setup_packet(cli);
527 SCVAL(cli->outbuf,smb_vwv0,0xFF);
528 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
529 SSVAL(cli->outbuf,smb_vwv3,2);
530 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
531 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
532 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
533 SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
534 SIVAL(cli->outbuf,smb_vwv11,capabilities);
535 p = smb_buf(cli->outbuf);
536 if (lm_response.length) {
537 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
539 if (nt_response.length) {
540 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
542 p += clistr_push(cli, p, user, -1, STR_TERMINATE);
544 /* Upper case here might help some NTLMv2 implementations */
545 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
546 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
547 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
548 cli_setup_bcc(cli, p);
550 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
551 result = cli_nt_error(cli);
552 goto end;
555 /* show_msg(cli->inbuf); */
557 if (cli_is_error(cli)) {
558 result = cli_nt_error(cli);
559 goto end;
562 #ifdef LANMAN_ONLY
563 ok = cli_simple_set_signing(cli, session_key, lm_response);
564 #else
565 ok = cli_simple_set_signing(cli, session_key, nt_response);
566 #endif
567 if (ok) {
568 if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
569 result = NT_STATUS_ACCESS_DENIED;
570 goto end;
574 /* use the returned vuid from now on */
575 cli->vuid = SVAL(cli->inbuf,smb_uid);
577 p = smb_buf(cli->inbuf);
578 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
579 -1, STR_TERMINATE);
580 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
581 -1, STR_TERMINATE);
582 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
583 -1, STR_TERMINATE);
585 if (strstr(cli->server_type, "Samba")) {
586 cli->is_samba = True;
589 result = cli_set_username(cli, user);
590 if (!NT_STATUS_IS_OK(result)) {
591 goto end;
594 if (session_key.data) {
595 /* Have plaintext orginal */
596 cli_set_session_key(cli, session_key);
599 result = NT_STATUS_OK;
600 end:
601 data_blob_free(&lm_response);
602 data_blob_free(&nt_response);
603 data_blob_free(&session_key);
604 return result;
607 /* The following is calculated from :
608 * (smb_size-4) = 35
609 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
610 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
611 * end of packet.
614 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
616 struct cli_sesssetup_blob_state {
617 struct tevent_context *ev;
618 struct cli_state *cli;
619 DATA_BLOB blob;
620 uint16_t max_blob_size;
621 uint16_t vwv[12];
622 uint8_t *buf;
624 NTSTATUS status;
625 char *inbuf;
626 DATA_BLOB ret_blob;
629 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
630 struct tevent_req **psubreq);
631 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
633 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
634 struct tevent_context *ev,
635 struct cli_state *cli,
636 DATA_BLOB blob)
638 struct tevent_req *req, *subreq;
639 struct cli_sesssetup_blob_state *state;
641 req = tevent_req_create(mem_ctx, &state,
642 struct cli_sesssetup_blob_state);
643 if (req == NULL) {
644 return NULL;
646 state->ev = ev;
647 state->blob = blob;
648 state->cli = cli;
650 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
651 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
652 "(was %u, need minimum %u)\n",
653 (unsigned int)cli->max_xmit,
654 BASE_SESSSETUP_BLOB_PACKET_SIZE));
655 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
656 return tevent_req_post(req, ev);
658 state->max_blob_size =
659 MIN(cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE, 0xFFFF);
661 if (!cli_sesssetup_blob_next(state, &subreq)) {
662 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
663 return tevent_req_post(req, ev);
665 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
666 return req;
669 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
670 struct tevent_req **psubreq)
672 struct tevent_req *subreq;
673 uint16_t thistime;
675 SCVAL(state->vwv+0, 0, 0xFF);
676 SCVAL(state->vwv+0, 1, 0);
677 SSVAL(state->vwv+1, 0, 0);
678 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
679 SSVAL(state->vwv+3, 0, 2);
680 SSVAL(state->vwv+4, 0, 1);
681 SIVAL(state->vwv+5, 0, 0);
683 thistime = MIN(state->blob.length, state->max_blob_size);
684 SSVAL(state->vwv+7, 0, thistime);
686 SSVAL(state->vwv+8, 0, 0);
687 SSVAL(state->vwv+9, 0, 0);
688 SIVAL(state->vwv+10, 0,
689 cli_session_setup_capabilities(state->cli)
690 | CAP_EXTENDED_SECURITY);
692 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
693 thistime);
694 if (state->buf == NULL) {
695 return false;
697 state->blob.data += thistime;
698 state->blob.length -= thistime;
700 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
701 "Unix", 5, NULL);
702 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
703 "Samba", 6, NULL);
704 if (state->buf == NULL) {
705 return false;
707 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
708 12, state->vwv,
709 talloc_get_size(state->buf), state->buf);
710 if (subreq == NULL) {
711 return false;
713 *psubreq = subreq;
714 return true;
717 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
719 struct tevent_req *req = tevent_req_callback_data(
720 subreq, struct tevent_req);
721 struct cli_sesssetup_blob_state *state = tevent_req_data(
722 req, struct cli_sesssetup_blob_state);
723 struct cli_state *cli = state->cli;
724 uint8_t wct;
725 uint16_t *vwv;
726 uint32_t num_bytes;
727 uint8_t *bytes;
728 NTSTATUS status;
729 uint8_t *p;
730 uint16_t blob_length;
731 uint8_t *inbuf;
733 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
734 &num_bytes, &bytes);
735 TALLOC_FREE(subreq);
736 if (!NT_STATUS_IS_OK(status)
737 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
738 tevent_req_nterror(req, status);
739 return;
742 state->status = status;
743 TALLOC_FREE(state->buf);
745 state->inbuf = (char *)inbuf;
746 cli->vuid = SVAL(state->inbuf, smb_uid);
748 blob_length = SVAL(vwv+3, 0);
749 if (blob_length > num_bytes) {
750 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
751 return;
753 state->ret_blob = data_blob_const(bytes, blob_length);
755 p = bytes + blob_length;
757 p += clistr_pull(state->inbuf, cli->server_os,
758 (char *)p, sizeof(fstring),
759 bytes+num_bytes-p, STR_TERMINATE);
760 p += clistr_pull(state->inbuf, cli->server_type,
761 (char *)p, sizeof(fstring),
762 bytes+num_bytes-p, STR_TERMINATE);
763 p += clistr_pull(state->inbuf, cli->server_domain,
764 (char *)p, sizeof(fstring),
765 bytes+num_bytes-p, STR_TERMINATE);
767 if (strstr(cli->server_type, "Samba")) {
768 cli->is_samba = True;
771 if (state->blob.length != 0) {
773 * More to send
775 if (!cli_sesssetup_blob_next(state, &subreq)) {
776 tevent_req_nomem(NULL, req);
777 return;
779 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
780 return;
782 tevent_req_done(req);
785 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
786 TALLOC_CTX *mem_ctx,
787 DATA_BLOB *pblob,
788 char **pinbuf)
790 struct cli_sesssetup_blob_state *state = tevent_req_data(
791 req, struct cli_sesssetup_blob_state);
792 NTSTATUS status;
793 char *inbuf;
795 if (tevent_req_is_nterror(req, &status)) {
796 state->cli->vuid = 0;
797 return status;
800 inbuf = talloc_move(mem_ctx, &state->inbuf);
801 if (pblob != NULL) {
802 *pblob = state->ret_blob;
804 if (pinbuf != NULL) {
805 *pinbuf = inbuf;
807 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
808 return state->status;
811 #ifdef HAVE_KRB5
813 /****************************************************************************
814 Use in-memory credentials cache
815 ****************************************************************************/
817 static void use_in_memory_ccache(void) {
818 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
821 /****************************************************************************
822 Do a spnego/kerberos encrypted session setup.
823 ****************************************************************************/
825 struct cli_session_setup_kerberos_state {
826 struct cli_state *cli;
827 DATA_BLOB negTokenTarg;
828 DATA_BLOB session_key_krb5;
829 ADS_STATUS ads_status;
832 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
834 static struct tevent_req *cli_session_setup_kerberos_send(
835 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
836 const char *principal, const char *workgroup)
838 struct tevent_req *req, *subreq;
839 struct cli_session_setup_kerberos_state *state;
840 int rc;
842 DEBUG(2,("Doing kerberos session setup\n"));
844 req = tevent_req_create(mem_ctx, &state,
845 struct cli_session_setup_kerberos_state);
846 if (req == NULL) {
847 return NULL;
849 state->cli = cli;
850 state->ads_status = ADS_SUCCESS;
852 cli_temp_set_signing(cli);
855 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
856 * we have to acquire a ticket. To be fixed later :-)
858 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
859 &state->session_key_krb5, 0, NULL);
860 if (rc) {
861 DEBUG(1, ("cli_session_setup_kerberos: "
862 "spnego_gen_krb5_negTokenInit failed: %s\n",
863 error_message(rc)));
864 state->ads_status = ADS_ERROR_KRB5(rc);
865 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
866 return tevent_req_post(req, ev);
869 #if 0
870 file_save("negTokenTarg.dat", state->negTokenTarg.data,
871 state->negTokenTarg.length);
872 #endif
874 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
875 if (tevent_req_nomem(subreq, req)) {
876 return tevent_req_post(req, ev);
878 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
879 return req;
882 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
884 struct tevent_req *req = tevent_req_callback_data(
885 subreq, struct tevent_req);
886 struct cli_session_setup_kerberos_state *state = tevent_req_data(
887 req, struct cli_session_setup_kerberos_state);
888 char *inbuf = NULL;
889 NTSTATUS status;
891 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), NULL, &inbuf);
892 if (!NT_STATUS_IS_OK(status)) {
893 TALLOC_FREE(subreq);
894 tevent_req_nterror(req, status);
895 return;
898 cli_set_session_key(state->cli, state->session_key_krb5);
900 if (cli_simple_set_signing(state->cli, state->session_key_krb5,
901 data_blob_null)
902 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
903 TALLOC_FREE(subreq);
904 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
905 return;
907 TALLOC_FREE(subreq);
908 tevent_req_done(req);
911 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
913 struct cli_session_setup_kerberos_state *state = tevent_req_data(
914 req, struct cli_session_setup_kerberos_state);
915 NTSTATUS status;
917 if (tevent_req_is_nterror(req, &status)) {
918 return ADS_ERROR_NT(status);
920 return state->ads_status;
923 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
924 const char *principal,
925 const char *workgroup)
927 struct tevent_context *ev;
928 struct tevent_req *req;
929 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
931 if (cli_has_async_calls(cli)) {
932 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
934 ev = tevent_context_init(talloc_tos());
935 if (ev == NULL) {
936 goto fail;
938 req = cli_session_setup_kerberos_send(ev, ev, cli, principal,
939 workgroup);
940 if (req == NULL) {
941 goto fail;
943 if (!tevent_req_poll(req, ev)) {
944 status = ADS_ERROR_SYSTEM(errno);
945 goto fail;
947 status = cli_session_setup_kerberos_recv(req);
948 fail:
949 TALLOC_FREE(ev);
950 return status;
952 #endif /* HAVE_KRB5 */
954 /****************************************************************************
955 Do a spnego/NTLMSSP encrypted session setup.
956 ****************************************************************************/
958 struct cli_session_setup_ntlmssp_state {
959 struct tevent_context *ev;
960 struct cli_state *cli;
961 struct ntlmssp_state *ntlmssp_state;
962 int turn;
963 DATA_BLOB blob_out;
966 static int cli_session_setup_ntlmssp_state_destructor(
967 struct cli_session_setup_ntlmssp_state *state)
969 if (state->ntlmssp_state != NULL) {
970 TALLOC_FREE(state->ntlmssp_state);
972 return 0;
975 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
977 static struct tevent_req *cli_session_setup_ntlmssp_send(
978 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
979 const char *user, const char *pass, const char *domain)
981 struct tevent_req *req, *subreq;
982 struct cli_session_setup_ntlmssp_state *state;
983 NTSTATUS status;
984 DATA_BLOB blob_out;
985 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
987 req = tevent_req_create(mem_ctx, &state,
988 struct cli_session_setup_ntlmssp_state);
989 if (req == NULL) {
990 return NULL;
992 state->ev = ev;
993 state->cli = cli;
994 state->turn = 1;
996 state->ntlmssp_state = NULL;
997 talloc_set_destructor(
998 state, cli_session_setup_ntlmssp_state_destructor);
1000 cli_temp_set_signing(cli);
1002 status = ntlmssp_client_start(state,
1003 global_myname(),
1004 lp_workgroup(),
1005 lp_client_ntlmv2_auth(),
1006 &state->ntlmssp_state);
1007 if (!NT_STATUS_IS_OK(status)) {
1008 goto fail;
1010 ntlmssp_want_feature(state->ntlmssp_state,
1011 NTLMSSP_FEATURE_SESSION_KEY);
1012 if (cli->use_ccache) {
1013 ntlmssp_want_feature(state->ntlmssp_state,
1014 NTLMSSP_FEATURE_CCACHE);
1016 status = ntlmssp_set_username(state->ntlmssp_state, user);
1017 if (!NT_STATUS_IS_OK(status)) {
1018 goto fail;
1020 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1021 if (!NT_STATUS_IS_OK(status)) {
1022 goto fail;
1024 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1025 if (!NT_STATUS_IS_OK(status)) {
1026 goto fail;
1028 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1029 &blob_out);
1030 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1031 goto fail;
1034 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1035 data_blob_free(&blob_out);
1037 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1038 if (tevent_req_nomem(subreq, req)) {
1039 return tevent_req_post(req, ev);
1041 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1042 return req;
1043 fail:
1044 tevent_req_nterror(req, status);
1045 return tevent_req_post(req, ev);
1048 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1050 struct tevent_req *req = tevent_req_callback_data(
1051 subreq, struct tevent_req);
1052 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1053 req, struct cli_session_setup_ntlmssp_state);
1054 DATA_BLOB blob_in, msg_in, blob_out;
1055 char *inbuf = NULL;
1056 bool parse_ret;
1057 NTSTATUS status;
1059 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1060 &inbuf);
1061 TALLOC_FREE(subreq);
1062 data_blob_free(&state->blob_out);
1064 if (NT_STATUS_IS_OK(status)) {
1065 if (state->cli->server_domain[0] == '\0') {
1066 fstrcpy(state->cli->server_domain,
1067 state->ntlmssp_state->server.netbios_domain);
1069 cli_set_session_key(
1070 state->cli, state->ntlmssp_state->session_key);
1072 if (cli_simple_set_signing(
1073 state->cli, state->ntlmssp_state->session_key,
1074 data_blob_null)
1075 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1076 TALLOC_FREE(subreq);
1077 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1078 return;
1080 TALLOC_FREE(subreq);
1081 TALLOC_FREE(state->ntlmssp_state);
1082 tevent_req_done(req);
1083 return;
1085 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1086 tevent_req_nterror(req, status);
1087 return;
1090 if (blob_in.length == 0) {
1091 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1092 return;
1095 if ((state->turn == 1)
1096 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1097 DATA_BLOB tmp_blob = data_blob_null;
1098 /* the server might give us back two challenges */
1099 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1100 &tmp_blob);
1101 data_blob_free(&tmp_blob);
1102 } else {
1103 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1104 OID_NTLMSSP, &msg_in);
1106 state->turn += 1;
1108 if (!parse_ret) {
1109 DEBUG(3,("Failed to parse auth response\n"));
1110 if (NT_STATUS_IS_OK(status)
1111 || NT_STATUS_EQUAL(status,
1112 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1113 tevent_req_nterror(
1114 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1115 return;
1119 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1121 if (!NT_STATUS_IS_OK(status)
1122 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1123 TALLOC_FREE(subreq);
1124 TALLOC_FREE(state->ntlmssp_state);
1125 tevent_req_nterror(req, status);
1126 return;
1129 state->blob_out = spnego_gen_auth(state, blob_out);
1130 TALLOC_FREE(subreq);
1131 if (tevent_req_nomem(state->blob_out.data, req)) {
1132 return;
1135 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1136 state->blob_out);
1137 if (tevent_req_nomem(subreq, req)) {
1138 return;
1140 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1143 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1145 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1146 req, struct cli_session_setup_ntlmssp_state);
1147 NTSTATUS status;
1149 if (tevent_req_is_nterror(req, &status)) {
1150 state->cli->vuid = 0;
1151 return status;
1153 return NT_STATUS_OK;
1156 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1157 const char *user,
1158 const char *pass,
1159 const char *domain)
1161 struct tevent_context *ev;
1162 struct tevent_req *req;
1163 NTSTATUS status = NT_STATUS_NO_MEMORY;
1165 if (cli_has_async_calls(cli)) {
1166 return NT_STATUS_INVALID_PARAMETER;
1168 ev = tevent_context_init(talloc_tos());
1169 if (ev == NULL) {
1170 goto fail;
1172 req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1173 if (req == NULL) {
1174 goto fail;
1176 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1177 goto fail;
1179 status = cli_session_setup_ntlmssp_recv(req);
1180 fail:
1181 TALLOC_FREE(ev);
1182 if (!NT_STATUS_IS_OK(status)) {
1183 cli_set_error(cli, status);
1185 return status;
1188 /****************************************************************************
1189 Do a spnego encrypted session setup.
1191 user_domain: The shortname of the domain the user/machine is a member of.
1192 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1193 ****************************************************************************/
1195 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
1196 const char *pass, const char *user_domain,
1197 const char * dest_realm)
1199 char *principal = NULL;
1200 char *OIDs[ASN1_MAX_OIDS];
1201 int i;
1202 DATA_BLOB blob;
1203 const char *p = NULL;
1204 char *account = NULL;
1205 NTSTATUS status;
1207 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
1209 /* the server might not even do spnego */
1210 if (cli->secblob.length <= 16) {
1211 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1212 goto ntlmssp;
1215 #if 0
1216 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1217 #endif
1219 /* there is 16 bytes of GUID before the real spnego packet starts */
1220 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1222 /* The server sent us the first part of the SPNEGO exchange in the
1223 * negprot reply. It is WRONG to depend on the principal sent in the
1224 * negprot reply, but right now we do it. If we don't receive one,
1225 * we try to best guess, then fall back to NTLM. */
1226 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1227 OIDs[0] == NULL) {
1228 data_blob_free(&blob);
1229 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1231 data_blob_free(&blob);
1233 /* make sure the server understands kerberos */
1234 for (i=0;OIDs[i];i++) {
1235 if (i == 0)
1236 DEBUG(3,("got OID=%s\n", OIDs[i]));
1237 else
1238 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1239 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1240 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1241 cli->got_kerberos_mechanism = True;
1243 talloc_free(OIDs[i]);
1246 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1248 status = cli_set_username(cli, user);
1249 if (!NT_STATUS_IS_OK(status)) {
1250 TALLOC_FREE(principal);
1251 return ADS_ERROR_NT(status);
1254 #ifdef HAVE_KRB5
1255 /* If password is set we reauthenticate to kerberos server
1256 * and do not store results */
1258 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1259 ADS_STATUS rc;
1261 if (pass && *pass) {
1262 int ret;
1264 use_in_memory_ccache();
1265 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1267 if (ret){
1268 TALLOC_FREE(principal);
1269 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1270 if (cli->fallback_after_kerberos)
1271 goto ntlmssp;
1272 return ADS_ERROR_KRB5(ret);
1276 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1278 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1279 TALLOC_FREE(principal);
1282 if (principal == NULL &&
1283 !is_ipaddress(cli->desthost) &&
1284 !strequal(STAR_SMBSERVER,
1285 cli->desthost)) {
1286 char *realm = NULL;
1287 char *host = NULL;
1288 DEBUG(3,("cli_session_setup_spnego: using target "
1289 "hostname not SPNEGO principal\n"));
1291 host = strchr_m(cli->desthost, '.');
1292 if (dest_realm) {
1293 realm = SMB_STRDUP(dest_realm);
1294 strupper_m(realm);
1295 } else {
1296 if (host) {
1297 /* DNS name. */
1298 realm = kerberos_get_realm_from_hostname(cli->desthost);
1299 } else {
1300 /* NetBIOS name - use our realm. */
1301 realm = kerberos_get_default_realm_from_ccache();
1305 if (realm && *realm) {
1306 principal = talloc_asprintf(talloc_tos(),
1307 "cifs/%s@%s",
1308 cli->desthost,
1309 realm);
1310 if (!principal) {
1311 SAFE_FREE(realm);
1312 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1314 DEBUG(3,("cli_session_setup_spnego: guessed "
1315 "server principal=%s\n",
1316 principal ? principal : "<null>"));
1318 SAFE_FREE(realm);
1321 if (principal) {
1322 rc = cli_session_setup_kerberos(cli, principal,
1323 dest_realm);
1324 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1325 TALLOC_FREE(principal);
1326 return rc;
1330 #endif
1332 TALLOC_FREE(principal);
1334 ntlmssp:
1336 account = talloc_strdup(talloc_tos(), user);
1337 if (!account) {
1338 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1341 /* when falling back to ntlmssp while authenticating with a machine
1342 * account strip off the realm - gd */
1344 if ((p = strchr_m(user, '@')) != NULL) {
1345 account[PTR_DIFF(p,user)] = '\0';
1348 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1351 /****************************************************************************
1352 Send a session setup. The username and workgroup is in UNIX character
1353 format and must be converted to DOS codepage format before sending. If the
1354 password is in plaintext, the same should be done.
1355 ****************************************************************************/
1357 NTSTATUS cli_session_setup(struct cli_state *cli,
1358 const char *user,
1359 const char *pass, int passlen,
1360 const char *ntpass, int ntpasslen,
1361 const char *workgroup)
1363 char *p;
1364 fstring user2;
1366 if (user) {
1367 fstrcpy(user2, user);
1368 } else {
1369 user2[0] ='\0';
1372 if (!workgroup) {
1373 workgroup = "";
1376 /* allow for workgroups as part of the username */
1377 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1378 (p=strchr_m(user2,*lp_winbind_separator()))) {
1379 *p = 0;
1380 user = p+1;
1381 workgroup = user2;
1384 if (cli->protocol < PROTOCOL_LANMAN1) {
1385 return NT_STATUS_OK;
1388 /* now work out what sort of session setup we are going to
1389 do. I have split this into separate functions to make the
1390 flow a bit easier to understand (tridge) */
1392 /* if its an older server then we have to use the older request format */
1394 if (cli->protocol < PROTOCOL_NT1) {
1395 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1396 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
1397 " or 'client ntlmv2 auth = yes'\n"));
1398 return NT_STATUS_ACCESS_DENIED;
1401 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1402 !lp_client_plaintext_auth() && (*pass)) {
1403 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
1404 " or 'client ntlmv2 auth = yes'\n"));
1405 return NT_STATUS_ACCESS_DENIED;
1408 return cli_session_setup_lanman2(cli, user, pass, passlen,
1409 workgroup);
1412 /* if no user is supplied then we have to do an anonymous connection.
1413 passwords are ignored */
1415 if (!user || !*user)
1416 return cli_session_setup_guest(cli);
1418 /* if the server is share level then send a plaintext null
1419 password at this point. The password is sent in the tree
1420 connect */
1422 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
1423 return cli_session_setup_plaintext(cli, user, "", workgroup);
1425 /* if the server doesn't support encryption then we have to use
1426 plaintext. The second password is ignored */
1428 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1429 if (!lp_client_plaintext_auth() && (*pass)) {
1430 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
1431 " or 'client ntlmv2 auth = yes'\n"));
1432 return NT_STATUS_ACCESS_DENIED;
1434 return cli_session_setup_plaintext(cli, user, pass, workgroup);
1437 /* if the server supports extended security then use SPNEGO */
1439 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
1440 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
1441 workgroup, NULL);
1442 if (!ADS_ERR_OK(status)) {
1443 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1444 return ads_ntstatus(status);
1446 } else {
1447 NTSTATUS status;
1449 /* otherwise do a NT1 style session setup */
1450 status = cli_session_setup_nt1(cli, user, pass, passlen,
1451 ntpass, ntpasslen, workgroup);
1452 if (!NT_STATUS_IS_OK(status)) {
1453 DEBUG(3,("cli_session_setup: NT1 session setup "
1454 "failed: %s\n", nt_errstr(status)));
1455 return status;
1459 if (strstr(cli->server_type, "Samba")) {
1460 cli->is_samba = True;
1463 return NT_STATUS_OK;
1466 /****************************************************************************
1467 Send a uloggoff.
1468 *****************************************************************************/
1470 struct cli_ulogoff_state {
1471 struct cli_state *cli;
1472 uint16_t vwv[3];
1475 static void cli_ulogoff_done(struct tevent_req *subreq);
1477 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1478 struct tevent_context *ev,
1479 struct cli_state *cli)
1481 struct tevent_req *req, *subreq;
1482 struct cli_ulogoff_state *state;
1484 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1485 if (req == NULL) {
1486 return NULL;
1488 state->cli = cli;
1490 SCVAL(state->vwv+0, 0, 0xFF);
1491 SCVAL(state->vwv+1, 0, 0);
1492 SSVAL(state->vwv+2, 0, 0);
1494 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
1495 0, NULL);
1496 if (tevent_req_nomem(subreq, req)) {
1497 return tevent_req_post(req, ev);
1499 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1500 return req;
1503 static void cli_ulogoff_done(struct tevent_req *subreq)
1505 struct tevent_req *req = tevent_req_callback_data(
1506 subreq, struct tevent_req);
1507 struct cli_ulogoff_state *state = tevent_req_data(
1508 req, struct cli_ulogoff_state);
1509 NTSTATUS status;
1511 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1512 if (!NT_STATUS_IS_OK(status)) {
1513 tevent_req_nterror(req, status);
1514 return;
1516 state->cli->vuid = -1;
1517 tevent_req_done(req);
1520 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1522 return tevent_req_simple_recv_ntstatus(req);
1525 NTSTATUS cli_ulogoff(struct cli_state *cli)
1527 struct tevent_context *ev;
1528 struct tevent_req *req;
1529 NTSTATUS status = NT_STATUS_NO_MEMORY;
1531 if (cli_has_async_calls(cli)) {
1532 return NT_STATUS_INVALID_PARAMETER;
1534 ev = tevent_context_init(talloc_tos());
1535 if (ev == NULL) {
1536 goto fail;
1538 req = cli_ulogoff_send(ev, ev, cli);
1539 if (req == NULL) {
1540 goto fail;
1542 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1543 goto fail;
1545 status = cli_ulogoff_recv(req);
1546 fail:
1547 TALLOC_FREE(ev);
1548 if (!NT_STATUS_IS_OK(status)) {
1549 cli_set_error(cli, status);
1551 return status;
1554 /****************************************************************************
1555 Send a tconX.
1556 ****************************************************************************/
1558 struct cli_tcon_andx_state {
1559 struct cli_state *cli;
1560 uint16_t vwv[4];
1561 struct iovec bytes;
1564 static void cli_tcon_andx_done(struct tevent_req *subreq);
1566 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1567 struct event_context *ev,
1568 struct cli_state *cli,
1569 const char *share, const char *dev,
1570 const char *pass, int passlen,
1571 struct tevent_req **psmbreq)
1573 struct tevent_req *req, *subreq;
1574 struct cli_tcon_andx_state *state;
1575 fstring pword;
1576 uint16_t *vwv;
1577 char *tmp = NULL;
1578 uint8_t *bytes;
1580 *psmbreq = NULL;
1582 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1583 if (req == NULL) {
1584 return NULL;
1586 state->cli = cli;
1587 vwv = state->vwv;
1589 fstrcpy(cli->share, share);
1591 /* in user level security don't send a password now */
1592 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1593 passlen = 1;
1594 pass = "";
1595 } else if (pass == NULL) {
1596 DEBUG(1, ("Server not using user level security and no "
1597 "password supplied.\n"));
1598 goto access_denied;
1601 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1602 *pass && passlen != 24) {
1603 if (!lp_client_lanman_auth()) {
1604 DEBUG(1, ("Server requested LANMAN password "
1605 "(share-level security) but "
1606 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
1607 goto access_denied;
1611 * Non-encrypted passwords - convert to DOS codepage before
1612 * encryption.
1614 passlen = 24;
1615 SMBencrypt(pass, cli->secblob.data, (uchar *)pword);
1616 } else {
1617 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1618 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1619 == 0) {
1620 if (!lp_client_plaintext_auth() && (*pass)) {
1621 DEBUG(1, ("Server requested plaintext "
1622 "password but "
1623 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
1624 goto access_denied;
1628 * Non-encrypted passwords - convert to DOS codepage
1629 * before using.
1631 passlen = clistr_push(cli, pword, pass, sizeof(pword),
1632 STR_TERMINATE);
1633 if (passlen == -1) {
1634 DEBUG(1, ("clistr_push(pword) failed\n"));
1635 goto access_denied;
1637 } else {
1638 if (passlen) {
1639 memcpy(pword, pass, passlen);
1644 SCVAL(vwv+0, 0, 0xFF);
1645 SCVAL(vwv+0, 1, 0);
1646 SSVAL(vwv+1, 0, 0);
1647 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
1648 SSVAL(vwv+3, 0, passlen);
1650 if (passlen) {
1651 bytes = (uint8_t *)talloc_memdup(state, pword, passlen);
1652 } else {
1653 bytes = talloc_array(state, uint8_t, 0);
1657 * Add the sharename
1659 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1660 cli->desthost, share);
1661 if (tmp == NULL) {
1662 TALLOC_FREE(req);
1663 return NULL;
1665 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
1666 NULL);
1667 TALLOC_FREE(tmp);
1670 * Add the devicetype
1672 tmp = talloc_strdup_upper(talloc_tos(), dev);
1673 if (tmp == NULL) {
1674 TALLOC_FREE(req);
1675 return NULL;
1677 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
1678 TALLOC_FREE(tmp);
1680 if (bytes == NULL) {
1681 TALLOC_FREE(req);
1682 return NULL;
1685 state->bytes.iov_base = (void *)bytes;
1686 state->bytes.iov_len = talloc_get_size(bytes);
1688 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
1689 1, &state->bytes);
1690 if (subreq == NULL) {
1691 TALLOC_FREE(req);
1692 return NULL;
1694 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
1695 *psmbreq = subreq;
1696 return req;
1698 access_denied:
1699 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1700 return tevent_req_post(req, ev);
1703 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
1704 struct event_context *ev,
1705 struct cli_state *cli,
1706 const char *share, const char *dev,
1707 const char *pass, int passlen)
1709 struct tevent_req *req, *subreq;
1710 NTSTATUS status;
1712 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
1713 &subreq);
1714 if (req == NULL) {
1715 return NULL;
1717 if (subreq == NULL) {
1718 return req;
1720 status = cli_smb_req_send(subreq);
1721 if (!NT_STATUS_IS_OK(status)) {
1722 tevent_req_nterror(req, status);
1723 return tevent_req_post(req, ev);
1725 return req;
1728 static void cli_tcon_andx_done(struct tevent_req *subreq)
1730 struct tevent_req *req = tevent_req_callback_data(
1731 subreq, struct tevent_req);
1732 struct cli_tcon_andx_state *state = tevent_req_data(
1733 req, struct cli_tcon_andx_state);
1734 struct cli_state *cli = state->cli;
1735 uint8_t *in;
1736 char *inbuf;
1737 uint8_t wct;
1738 uint16_t *vwv;
1739 uint32_t num_bytes;
1740 uint8_t *bytes;
1741 NTSTATUS status;
1743 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
1744 &num_bytes, &bytes);
1745 TALLOC_FREE(subreq);
1746 if (!NT_STATUS_IS_OK(status)) {
1747 tevent_req_nterror(req, status);
1748 return;
1751 inbuf = (char *)in;
1753 clistr_pull(inbuf, cli->dev, bytes, sizeof(fstring), num_bytes,
1754 STR_TERMINATE|STR_ASCII);
1756 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
1757 /* almost certainly win95 - enable bug fixes */
1758 cli->win95 = True;
1762 * Make sure that we have the optional support 16-bit field. WCT > 2.
1763 * Avoids issues when connecting to Win9x boxes sharing files
1766 cli->dfsroot = false;
1768 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
1769 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
1772 cli->cnum = SVAL(inbuf,smb_tid);
1773 tevent_req_done(req);
1776 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
1778 return tevent_req_simple_recv_ntstatus(req);
1781 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
1782 const char *dev, const char *pass, int passlen)
1784 TALLOC_CTX *frame = talloc_stackframe();
1785 struct event_context *ev;
1786 struct tevent_req *req;
1787 NTSTATUS status = NT_STATUS_OK;
1789 if (cli_has_async_calls(cli)) {
1791 * Can't use sync call while an async call is in flight
1793 status = NT_STATUS_INVALID_PARAMETER;
1794 goto fail;
1797 ev = event_context_init(frame);
1798 if (ev == NULL) {
1799 status = NT_STATUS_NO_MEMORY;
1800 goto fail;
1803 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
1804 if (req == NULL) {
1805 status = NT_STATUS_NO_MEMORY;
1806 goto fail;
1809 if (!tevent_req_poll(req, ev)) {
1810 status = map_nt_error_from_unix(errno);
1811 goto fail;
1814 status = cli_tcon_andx_recv(req);
1815 fail:
1816 TALLOC_FREE(frame);
1817 if (!NT_STATUS_IS_OK(status)) {
1818 cli_set_error(cli, status);
1820 return status;
1823 /****************************************************************************
1824 Send a tree disconnect.
1825 ****************************************************************************/
1827 struct cli_tdis_state {
1828 struct cli_state *cli;
1831 static void cli_tdis_done(struct tevent_req *subreq);
1833 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
1834 struct tevent_context *ev,
1835 struct cli_state *cli)
1837 struct tevent_req *req, *subreq;
1838 struct cli_tdis_state *state;
1840 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
1841 if (req == NULL) {
1842 return NULL;
1844 state->cli = cli;
1846 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
1847 if (tevent_req_nomem(subreq, req)) {
1848 return tevent_req_post(req, ev);
1850 tevent_req_set_callback(subreq, cli_tdis_done, req);
1851 return req;
1854 static void cli_tdis_done(struct tevent_req *subreq)
1856 struct tevent_req *req = tevent_req_callback_data(
1857 subreq, struct tevent_req);
1858 struct cli_tdis_state *state = tevent_req_data(
1859 req, struct cli_tdis_state);
1860 NTSTATUS status;
1862 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1863 TALLOC_FREE(subreq);
1864 if (!NT_STATUS_IS_OK(status)) {
1865 tevent_req_nterror(req, status);
1866 return;
1868 state->cli->cnum = -1;
1869 tevent_req_done(req);
1872 NTSTATUS cli_tdis_recv(struct tevent_req *req)
1874 return tevent_req_simple_recv_ntstatus(req);
1877 NTSTATUS cli_tdis(struct cli_state *cli)
1879 struct tevent_context *ev;
1880 struct tevent_req *req;
1881 NTSTATUS status = NT_STATUS_NO_MEMORY;
1883 if (cli_has_async_calls(cli)) {
1884 return NT_STATUS_INVALID_PARAMETER;
1886 ev = tevent_context_init(talloc_tos());
1887 if (ev == NULL) {
1888 goto fail;
1890 req = cli_tdis_send(ev, ev, cli);
1891 if (req == NULL) {
1892 goto fail;
1894 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1895 goto fail;
1897 status = cli_tdis_recv(req);
1898 fail:
1899 TALLOC_FREE(ev);
1900 if (!NT_STATUS_IS_OK(status)) {
1901 cli_set_error(cli, status);
1903 return status;
1906 /****************************************************************************
1907 Send a negprot command.
1908 ****************************************************************************/
1910 struct cli_negprot_state {
1911 struct cli_state *cli;
1914 static void cli_negprot_done(struct tevent_req *subreq);
1916 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
1917 struct event_context *ev,
1918 struct cli_state *cli)
1920 struct tevent_req *req, *subreq;
1921 struct cli_negprot_state *state;
1922 uint8_t *bytes = NULL;
1923 int numprots;
1924 uint16_t cnum;
1926 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
1927 if (req == NULL) {
1928 return NULL;
1930 state->cli = cli;
1932 if (cli->protocol < PROTOCOL_NT1)
1933 cli->use_spnego = False;
1935 /* setup the protocol strings */
1936 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1937 uint8_t c = 2;
1938 if (prots[numprots].prot > cli->protocol) {
1939 break;
1941 bytes = (uint8_t *)talloc_append_blob(
1942 state, bytes, data_blob_const(&c, sizeof(c)));
1943 if (tevent_req_nomem(bytes, req)) {
1944 return tevent_req_post(req, ev);
1946 bytes = smb_bytes_push_str(bytes, false,
1947 prots[numprots].name,
1948 strlen(prots[numprots].name)+1,
1949 NULL);
1950 if (tevent_req_nomem(bytes, req)) {
1951 return tevent_req_post(req, ev);
1955 cnum = cli->cnum;
1957 cli->cnum = 0;
1958 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
1959 talloc_get_size(bytes), bytes);
1960 cli->cnum = cnum;
1962 if (tevent_req_nomem(subreq, req)) {
1963 return tevent_req_post(req, ev);
1965 tevent_req_set_callback(subreq, cli_negprot_done, req);
1966 return req;
1969 static void cli_negprot_done(struct tevent_req *subreq)
1971 struct tevent_req *req = tevent_req_callback_data(
1972 subreq, struct tevent_req);
1973 struct cli_negprot_state *state = tevent_req_data(
1974 req, struct cli_negprot_state);
1975 struct cli_state *cli = state->cli;
1976 uint8_t wct;
1977 uint16_t *vwv;
1978 uint32_t num_bytes;
1979 uint8_t *bytes;
1980 NTSTATUS status;
1981 uint16_t protnum;
1982 uint8_t *inbuf;
1984 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
1985 &num_bytes, &bytes);
1986 TALLOC_FREE(subreq);
1987 if (!NT_STATUS_IS_OK(status)) {
1988 tevent_req_nterror(req, status);
1989 return;
1992 protnum = SVAL(vwv, 0);
1994 if ((protnum >= ARRAY_SIZE(prots))
1995 || (prots[protnum].prot > cli->protocol)) {
1996 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1997 return;
2000 cli->protocol = prots[protnum].prot;
2002 if ((cli->protocol < PROTOCOL_NT1) &&
2003 client_is_signing_mandatory(cli)) {
2004 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2005 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2006 return;
2009 if (cli->protocol >= PROTOCOL_NT1) {
2010 struct timespec ts;
2011 bool negotiated_smb_signing = false;
2013 /* NT protocol */
2014 cli->sec_mode = CVAL(vwv + 1, 0);
2015 cli->max_mux = SVAL(vwv + 1, 1);
2016 cli->max_xmit = IVAL(vwv + 3, 1);
2017 cli->sesskey = IVAL(vwv + 7, 1);
2018 cli->serverzone = SVALS(vwv + 15, 1);
2019 cli->serverzone *= 60;
2020 /* this time arrives in real GMT */
2021 ts = interpret_long_date(((char *)(vwv+11))+1);
2022 cli->servertime = ts.tv_sec;
2023 cli->secblob = data_blob(bytes, num_bytes);
2024 cli->capabilities = IVAL(vwv + 9, 1);
2025 if (cli->capabilities & CAP_RAW_MODE) {
2026 cli->readbraw_supported = True;
2027 cli->writebraw_supported = True;
2029 /* work out if they sent us a workgroup */
2030 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
2031 smb_buflen(cli->inbuf) > 8) {
2032 clistr_pull(cli->inbuf, cli->server_domain,
2033 bytes+8, sizeof(cli->server_domain),
2034 num_bytes-8,
2035 STR_UNICODE|STR_NOALIGN);
2039 * As signing is slow we only turn it on if either the client or
2040 * the server require it. JRA.
2043 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2044 /* Fail if server says signing is mandatory and we don't want to support it. */
2045 if (!client_is_signing_allowed(cli)) {
2046 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
2047 tevent_req_nterror(req,
2048 NT_STATUS_ACCESS_DENIED);
2049 return;
2051 negotiated_smb_signing = true;
2052 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
2053 /* Fail if client says signing is mandatory and the server doesn't support it. */
2054 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
2055 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
2056 tevent_req_nterror(req,
2057 NT_STATUS_ACCESS_DENIED);
2058 return;
2060 negotiated_smb_signing = true;
2061 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2062 negotiated_smb_signing = true;
2065 if (negotiated_smb_signing) {
2066 cli_set_signing_negotiated(cli);
2069 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
2070 SAFE_FREE(cli->outbuf);
2071 SAFE_FREE(cli->inbuf);
2072 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2073 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2074 if (!cli->outbuf || !cli->inbuf) {
2075 tevent_req_nterror(req,
2076 NT_STATUS_NO_MEMORY);
2077 return;
2079 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
2082 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2083 cli->use_spnego = False;
2084 cli->sec_mode = SVAL(vwv + 1, 0);
2085 cli->max_xmit = SVAL(vwv + 2, 0);
2086 cli->max_mux = SVAL(vwv + 3, 0);
2087 cli->sesskey = IVAL(vwv + 6, 0);
2088 cli->serverzone = SVALS(vwv + 10, 0);
2089 cli->serverzone *= 60;
2090 /* this time is converted to GMT by make_unix_date */
2091 cli->servertime = make_unix_date(
2092 (char *)(vwv + 8), cli->serverzone);
2093 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2094 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2095 cli->secblob = data_blob(bytes, num_bytes);
2096 } else {
2097 /* the old core protocol */
2098 cli->use_spnego = False;
2099 cli->sec_mode = 0;
2100 cli->serverzone = get_time_zone(time(NULL));
2103 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2105 /* a way to force ascii SMB */
2106 if (getenv("CLI_FORCE_ASCII"))
2107 cli->capabilities &= ~CAP_UNICODE;
2109 tevent_req_done(req);
2112 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2114 return tevent_req_simple_recv_ntstatus(req);
2117 NTSTATUS cli_negprot(struct cli_state *cli)
2119 TALLOC_CTX *frame = talloc_stackframe();
2120 struct event_context *ev;
2121 struct tevent_req *req;
2122 NTSTATUS status = NT_STATUS_OK;
2124 if (cli_has_async_calls(cli)) {
2126 * Can't use sync call while an async call is in flight
2128 status = NT_STATUS_INVALID_PARAMETER;
2129 goto fail;
2132 ev = event_context_init(frame);
2133 if (ev == NULL) {
2134 status = NT_STATUS_NO_MEMORY;
2135 goto fail;
2138 req = cli_negprot_send(frame, ev, cli);
2139 if (req == NULL) {
2140 status = NT_STATUS_NO_MEMORY;
2141 goto fail;
2144 if (!tevent_req_poll(req, ev)) {
2145 status = map_nt_error_from_unix(errno);
2146 goto fail;
2149 status = cli_negprot_recv(req);
2150 fail:
2151 TALLOC_FREE(frame);
2152 if (!NT_STATUS_IS_OK(status)) {
2153 cli_set_error(cli, status);
2155 return status;
2158 /****************************************************************************
2159 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
2160 ****************************************************************************/
2162 bool cli_session_request(struct cli_state *cli,
2163 struct nmb_name *calling, struct nmb_name *called)
2165 char *p;
2166 int len = 4;
2167 int namelen = 0;
2168 char *tmp;
2170 /* 445 doesn't have session request */
2171 if (cli->port == 445)
2172 return True;
2174 memcpy(&(cli->calling), calling, sizeof(*calling));
2175 memcpy(&(cli->called ), called , sizeof(*called ));
2177 /* put in the destination name */
2179 tmp = name_mangle(talloc_tos(), cli->called.name,
2180 cli->called.name_type);
2181 if (tmp == NULL) {
2182 return false;
2185 p = cli->outbuf+len;
2186 namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
2187 if (namelen > 0) {
2188 memcpy(p, tmp, namelen);
2189 len += namelen;
2191 TALLOC_FREE(tmp);
2193 /* and my name */
2195 tmp = name_mangle(talloc_tos(), cli->calling.name,
2196 cli->calling.name_type);
2197 if (tmp == NULL) {
2198 return false;
2201 p = cli->outbuf+len;
2202 namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
2203 if (namelen > 0) {
2204 memcpy(p, tmp, namelen);
2205 len += namelen;
2207 TALLOC_FREE(tmp);
2209 /* send a session request (RFC 1002) */
2210 /* setup the packet length
2211 * Remove four bytes from the length count, since the length
2212 * field in the NBT Session Service header counts the number
2213 * of bytes which follow. The cli_send_smb() function knows
2214 * about this and accounts for those four bytes.
2215 * CRH.
2217 len -= 4;
2218 _smb_setlen(cli->outbuf,len);
2219 SCVAL(cli->outbuf,0,0x81);
2221 cli_send_smb(cli);
2222 DEBUG(5,("Sent session request\n"));
2224 if (!cli_receive_smb(cli))
2225 return False;
2227 if (CVAL(cli->inbuf,0) == 0x84) {
2228 /* C. Hoch 9/14/95 Start */
2229 /* For information, here is the response structure.
2230 * We do the byte-twiddling to for portability.
2231 struct RetargetResponse{
2232 unsigned char type;
2233 unsigned char flags;
2234 int16 length;
2235 int32 ip_addr;
2236 int16 port;
2239 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
2240 struct in_addr dest_ip;
2241 NTSTATUS status;
2243 /* SESSION RETARGET */
2244 putip((char *)&dest_ip,cli->inbuf+4);
2245 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
2247 status = open_socket_out(&cli->dest_ss, port,
2248 LONG_CONNECT_TIMEOUT, &cli->fd);
2249 if (!NT_STATUS_IS_OK(status)) {
2250 return False;
2253 DEBUG(3,("Retargeted\n"));
2255 set_socket_options(cli->fd, lp_socket_options());
2257 /* Try again */
2259 static int depth;
2260 bool ret;
2261 if (depth > 4) {
2262 DEBUG(0,("Retarget recursion - failing\n"));
2263 return False;
2265 depth++;
2266 ret = cli_session_request(cli, calling, called);
2267 depth--;
2268 return ret;
2270 } /* C. Hoch 9/14/95 End */
2272 if (CVAL(cli->inbuf,0) != 0x82) {
2273 /* This is the wrong place to put the error... JRA. */
2274 cli->rap_error = CVAL(cli->inbuf,4);
2275 return False;
2277 return(True);
2280 struct fd_struct {
2281 int fd;
2284 static void smb_sock_connected(struct tevent_req *req)
2286 struct fd_struct *pfd = tevent_req_callback_data(
2287 req, struct fd_struct);
2288 int fd;
2289 NTSTATUS status;
2291 status = open_socket_out_defer_recv(req, &fd);
2292 if (NT_STATUS_IS_OK(status)) {
2293 pfd->fd = fd;
2297 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
2298 uint16_t *port, int timeout, int *pfd)
2300 struct event_context *ev;
2301 struct tevent_req *r139, *r445;
2302 struct fd_struct *fd139, *fd445;
2303 NTSTATUS status = NT_STATUS_NO_MEMORY;
2305 if (*port != 0) {
2306 return open_socket_out(pss, *port, timeout, pfd);
2309 ev = event_context_init(talloc_tos());
2310 if (ev == NULL) {
2311 return NT_STATUS_NO_MEMORY;
2314 fd139 = talloc(ev, struct fd_struct);
2315 if (fd139 == NULL) {
2316 goto done;
2318 fd139->fd = -1;
2320 fd445 = talloc(ev, struct fd_struct);
2321 if (fd445 == NULL) {
2322 goto done;
2324 fd445->fd = -1;
2326 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
2327 pss, 445, timeout);
2328 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
2329 pss, 139, timeout);
2330 if ((r445 == NULL) || (r139 == NULL)) {
2331 goto done;
2333 tevent_req_set_callback(r445, smb_sock_connected, fd445);
2334 tevent_req_set_callback(r139, smb_sock_connected, fd139);
2336 while ((fd445->fd == -1) && (fd139->fd == -1)
2337 && (tevent_req_is_in_progress(r139)
2338 || tevent_req_is_in_progress(r445))) {
2339 event_loop_once(ev);
2342 if ((fd139->fd != -1) && (fd445->fd != -1)) {
2343 close(fd139->fd);
2344 fd139->fd = -1;
2347 if (fd445->fd != -1) {
2348 *port = 445;
2349 *pfd = fd445->fd;
2350 status = NT_STATUS_OK;
2351 goto done;
2353 if (fd139->fd != -1) {
2354 *port = 139;
2355 *pfd = fd139->fd;
2356 status = NT_STATUS_OK;
2357 goto done;
2360 status = open_socket_out_defer_recv(r445, &fd445->fd);
2361 done:
2362 TALLOC_FREE(ev);
2363 return status;
2366 /****************************************************************************
2367 Open the client sockets.
2368 ****************************************************************************/
2370 NTSTATUS cli_connect(struct cli_state *cli,
2371 const char *host,
2372 struct sockaddr_storage *dest_ss)
2375 int name_type = 0x20;
2376 TALLOC_CTX *frame = talloc_stackframe();
2377 unsigned int num_addrs = 0;
2378 unsigned int i = 0;
2379 struct sockaddr_storage *ss_arr = NULL;
2380 char *p = NULL;
2382 /* reasonable default hostname */
2383 if (!host) {
2384 host = STAR_SMBSERVER;
2387 fstrcpy(cli->desthost, host);
2389 /* allow hostnames of the form NAME#xx and do a netbios lookup */
2390 if ((p = strchr(cli->desthost, '#'))) {
2391 name_type = strtol(p+1, NULL, 16);
2392 *p = 0;
2395 if (!dest_ss || is_zero_addr(dest_ss)) {
2396 NTSTATUS status =resolve_name_list(frame,
2397 cli->desthost,
2398 name_type,
2399 &ss_arr,
2400 &num_addrs);
2401 if (!NT_STATUS_IS_OK(status)) {
2402 TALLOC_FREE(frame);
2403 return NT_STATUS_BAD_NETWORK_NAME;
2405 } else {
2406 num_addrs = 1;
2407 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
2408 if (!ss_arr) {
2409 TALLOC_FREE(frame);
2410 return NT_STATUS_NO_MEMORY;
2412 *ss_arr = *dest_ss;
2415 for (i = 0; i < num_addrs; i++) {
2416 cli->dest_ss = ss_arr[i];
2417 if (getenv("LIBSMB_PROG")) {
2418 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
2419 } else {
2420 uint16_t port = cli->port;
2421 NTSTATUS status;
2422 status = open_smb_socket(&cli->dest_ss, &port,
2423 cli->timeout, &cli->fd);
2424 if (NT_STATUS_IS_OK(status)) {
2425 cli->port = port;
2428 if (cli->fd == -1) {
2429 char addr[INET6_ADDRSTRLEN];
2430 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
2431 DEBUG(2,("Error connecting to %s (%s)\n",
2432 dest_ss?addr:host,strerror(errno)));
2433 } else {
2434 /* Exit from loop on first connection. */
2435 break;
2439 if (cli->fd == -1) {
2440 TALLOC_FREE(frame);
2441 return map_nt_error_from_unix(errno);
2444 if (dest_ss) {
2445 *dest_ss = cli->dest_ss;
2448 set_socket_options(cli->fd, lp_socket_options());
2450 TALLOC_FREE(frame);
2451 return NT_STATUS_OK;
2455 establishes a connection to after the negprot.
2456 @param output_cli A fully initialised cli structure, non-null only on success
2457 @param dest_host The netbios name of the remote host
2458 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2459 @param port (optional) The destination port (0 for default)
2461 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2462 const char *my_name,
2463 const char *dest_host,
2464 struct sockaddr_storage *dest_ss, int port,
2465 int signing_state, int flags)
2467 NTSTATUS nt_status;
2468 struct nmb_name calling;
2469 struct nmb_name called;
2470 struct cli_state *cli;
2471 struct sockaddr_storage ss;
2473 if (!my_name)
2474 my_name = global_myname();
2476 if (!(cli = cli_initialise_ex(signing_state))) {
2477 return NT_STATUS_NO_MEMORY;
2480 make_nmb_name(&calling, my_name, 0x0);
2481 make_nmb_name(&called , dest_host, 0x20);
2483 cli_set_port(cli, port);
2484 cli_set_timeout(cli, 10000); /* 10 seconds. */
2486 if (dest_ss) {
2487 ss = *dest_ss;
2488 } else {
2489 zero_sockaddr(&ss);
2492 again:
2494 DEBUG(3,("Connecting to host=%s\n", dest_host));
2496 nt_status = cli_connect(cli, dest_host, &ss);
2497 if (!NT_STATUS_IS_OK(nt_status)) {
2498 char addr[INET6_ADDRSTRLEN];
2499 print_sockaddr(addr, sizeof(addr), &ss);
2500 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
2501 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
2502 cli_shutdown(cli);
2503 return nt_status;
2506 if (!cli_session_request(cli, &calling, &called)) {
2507 char *p;
2508 DEBUG(1,("session request to %s failed (%s)\n",
2509 called.name, cli_errstr(cli)));
2510 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
2511 *p = 0;
2512 goto again;
2514 if (strcmp(called.name, STAR_SMBSERVER)) {
2515 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
2516 goto again;
2518 return NT_STATUS_BAD_NETWORK_NAME;
2521 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
2522 cli->use_spnego = False;
2523 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
2524 cli->use_kerberos = True;
2526 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
2527 cli->use_kerberos) {
2528 cli->fallback_after_kerberos = true;
2530 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
2531 cli->use_ccache = true;
2534 nt_status = cli_negprot(cli);
2535 if (!NT_STATUS_IS_OK(nt_status)) {
2536 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2537 cli_shutdown(cli);
2538 return nt_status;
2541 *output_cli = cli;
2542 return NT_STATUS_OK;
2547 establishes a connection right up to doing tconX, password specified.
2548 @param output_cli A fully initialised cli structure, non-null only on success
2549 @param dest_host The netbios name of the remote host
2550 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2551 @param port (optional) The destination port (0 for default)
2552 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2553 @param service_type The 'type' of serivice.
2554 @param user Username, unix string
2555 @param domain User's domain
2556 @param password User's password, unencrypted unix string.
2559 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2560 const char *my_name,
2561 const char *dest_host,
2562 struct sockaddr_storage *dest_ss, int port,
2563 const char *service, const char *service_type,
2564 const char *user, const char *domain,
2565 const char *password, int flags,
2566 int signing_state)
2568 NTSTATUS nt_status;
2569 struct cli_state *cli = NULL;
2570 int pw_len = password ? strlen(password)+1 : 0;
2572 *output_cli = NULL;
2574 if (password == NULL) {
2575 password = "";
2578 nt_status = cli_start_connection(&cli, my_name, dest_host,
2579 dest_ss, port, signing_state,
2580 flags);
2582 if (!NT_STATUS_IS_OK(nt_status)) {
2583 return nt_status;
2586 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
2587 cli->use_level_II_oplocks =
2588 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
2590 nt_status = cli_session_setup(cli, user, password, pw_len, password,
2591 pw_len, domain);
2592 if (!NT_STATUS_IS_OK(nt_status)) {
2594 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2595 DEBUG(1,("failed session setup with %s\n",
2596 nt_errstr(nt_status)));
2597 cli_shutdown(cli);
2598 return nt_status;
2601 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2602 if (!NT_STATUS_IS_OK(nt_status)) {
2603 DEBUG(1,("anonymous failed session setup with %s\n",
2604 nt_errstr(nt_status)));
2605 cli_shutdown(cli);
2606 return nt_status;
2610 if (service) {
2611 nt_status = cli_tcon_andx(cli, service, service_type, password,
2612 pw_len);
2613 if (!NT_STATUS_IS_OK(nt_status)) {
2614 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2615 cli_shutdown(cli);
2616 if (NT_STATUS_IS_OK(nt_status)) {
2617 nt_status = NT_STATUS_UNSUCCESSFUL;
2619 return nt_status;
2623 nt_status = cli_init_creds(cli, user, domain, password);
2624 if (!NT_STATUS_IS_OK(nt_status)) {
2625 cli_shutdown(cli);
2626 return nt_status;
2629 *output_cli = cli;
2630 return NT_STATUS_OK;
2633 /****************************************************************************
2634 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2635 ****************************************************************************/
2637 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
2638 struct sockaddr_storage *pdest_ss)
2640 struct nmb_name calling, called;
2642 make_nmb_name(&calling, srchost, 0x0);
2645 * If the called name is an IP address
2646 * then use *SMBSERVER immediately.
2649 if(is_ipaddress(desthost)) {
2650 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
2651 } else {
2652 make_nmb_name(&called, desthost, 0x20);
2655 if (!cli_session_request(*ppcli, &calling, &called)) {
2656 NTSTATUS status;
2657 struct nmb_name smbservername;
2659 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
2662 * If the name wasn't *SMBSERVER then
2663 * try with *SMBSERVER if the first name fails.
2666 if (nmb_name_equal(&called, &smbservername)) {
2669 * The name used was *SMBSERVER, don't bother with another name.
2672 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2673 with error %s.\n", desthost, cli_errstr(*ppcli) ));
2674 return False;
2677 /* Try again... */
2678 cli_shutdown(*ppcli);
2680 *ppcli = cli_initialise();
2681 if (!*ppcli) {
2682 /* Out of memory... */
2683 return False;
2686 status = cli_connect(*ppcli, desthost, pdest_ss);
2687 if (!NT_STATUS_IS_OK(status) ||
2688 !cli_session_request(*ppcli, &calling, &smbservername)) {
2689 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2690 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
2691 return False;
2695 return True;
2698 /****************************************************************************
2699 Send an old style tcon.
2700 ****************************************************************************/
2701 NTSTATUS cli_raw_tcon(struct cli_state *cli,
2702 const char *service, const char *pass, const char *dev,
2703 uint16 *max_xmit, uint16 *tid)
2705 struct tevent_req *req;
2706 uint16_t *ret_vwv;
2707 uint8_t *bytes;
2708 NTSTATUS status;
2710 if (!lp_client_plaintext_auth() && (*pass)) {
2711 DEBUG(1, ("Server requested plaintext password but 'client "
2712 "plaintext auth' is disabled\n"));
2713 return NT_STATUS_ACCESS_DENIED;
2716 bytes = talloc_array(talloc_tos(), uint8_t, 0);
2717 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
2718 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
2719 service, strlen(service)+1, NULL);
2720 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
2721 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
2722 pass, strlen(pass)+1, NULL);
2723 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
2724 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
2725 dev, strlen(dev)+1, NULL);
2727 status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
2728 talloc_get_size(bytes), bytes, &req,
2729 2, NULL, &ret_vwv, NULL, NULL);
2730 if (!NT_STATUS_IS_OK(status)) {
2731 return status;
2734 *max_xmit = SVAL(ret_vwv + 0, 0);
2735 *tid = SVAL(ret_vwv + 1, 0);
2737 return NT_STATUS_OK;
2740 /* Return a cli_state pointing at the IPC$ share for the given server */
2742 struct cli_state *get_ipc_connect(char *server,
2743 struct sockaddr_storage *server_ss,
2744 const struct user_auth_info *user_info)
2746 struct cli_state *cli;
2747 NTSTATUS nt_status;
2748 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2750 if (user_info->use_kerberos) {
2751 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2754 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
2755 user_info->username ? user_info->username : "",
2756 lp_workgroup(),
2757 user_info->password ? user_info->password : "",
2758 flags,
2759 Undefined);
2761 if (NT_STATUS_IS_OK(nt_status)) {
2762 return cli;
2763 } else if (is_ipaddress(server)) {
2764 /* windows 9* needs a correct NMB name for connections */
2765 fstring remote_name;
2767 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2768 cli = get_ipc_connect(remote_name, server_ss, user_info);
2769 if (cli)
2770 return cli;
2773 return NULL;
2777 * Given the IP address of a master browser on the network, return its
2778 * workgroup and connect to it.
2780 * This function is provided to allow additional processing beyond what
2781 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2782 * browsers and obtain each master browsers' list of domains (in case the
2783 * first master browser is recently on the network and has not yet
2784 * synchronized with other master browsers and therefore does not yet have the
2785 * entire network browse list)
2788 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2789 struct ip_service *mb_ip,
2790 const struct user_auth_info *user_info,
2791 char **pp_workgroup_out)
2793 char addr[INET6_ADDRSTRLEN];
2794 fstring name;
2795 struct cli_state *cli;
2796 struct sockaddr_storage server_ss;
2798 *pp_workgroup_out = NULL;
2800 print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2801 DEBUG(99, ("Looking up name of master browser %s\n",
2802 addr));
2805 * Do a name status query to find out the name of the master browser.
2806 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2807 * master browser will not respond to a wildcard query (or, at least,
2808 * an NT4 server acting as the domain master browser will not).
2810 * We might be able to use ONLY the query on MSBROWSE, but that's not
2811 * yet been tested with all Windows versions, so until it is, leave
2812 * the original wildcard query as the first choice and fall back to
2813 * MSBROWSE if the wildcard query fails.
2815 if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2816 !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2818 DEBUG(99, ("Could not retrieve name status for %s\n",
2819 addr));
2820 return NULL;
2823 if (!find_master_ip(name, &server_ss)) {
2824 DEBUG(99, ("Could not find master ip for %s\n", name));
2825 return NULL;
2828 *pp_workgroup_out = talloc_strdup(ctx, name);
2830 DEBUG(4, ("found master browser %s, %s\n", name, addr));
2832 print_sockaddr(addr, sizeof(addr), &server_ss);
2833 cli = get_ipc_connect(addr, &server_ss, user_info);
2835 return cli;
2839 * Return the IP address and workgroup of a master browser on the network, and
2840 * connect to it.
2843 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2844 const struct user_auth_info *user_info,
2845 char **pp_workgroup_out)
2847 struct ip_service *ip_list;
2848 struct cli_state *cli;
2849 int i, count;
2851 *pp_workgroup_out = NULL;
2853 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2855 /* Go looking for workgroups by broadcasting on the local network */
2857 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2858 &count))) {
2859 DEBUG(99, ("No master browsers responded\n"));
2860 return False;
2863 for (i = 0; i < count; i++) {
2864 char addr[INET6_ADDRSTRLEN];
2865 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2866 DEBUG(99, ("Found master browser %s\n", addr));
2868 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2869 user_info, pp_workgroup_out);
2870 if (cli)
2871 return(cli);
2874 return NULL;