s3:libsmb: fallback to SMBtcon for old servers
[Samba/gebeck_regimport.git] / source3 / libsmb / cliconnect.c
blobe45bf25702a5f718e2f9451fa395082d0bf1423d
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
6 Copyright (C) Volker Lendecke 2011
7 Copyright (C) Jeremy Allison 2011
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "libsmb/libsmb.h"
25 #include "auth_info.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../libcli/auth/spnego.h"
28 #include "smb_krb5.h"
29 #include "../auth/ntlmssp/ntlmssp.h"
30 #include "libads/kerberos_proto.h"
31 #include "krb5_env.h"
32 #include "../lib/util/tevent_ntstatus.h"
33 #include "async_smb.h"
34 #include "libsmb/nmblib.h"
35 #include "librpc/ndr/libndr.h"
36 #include "../libcli/smb/smbXcli_base.h"
37 #include "smb2cli.h"
39 #define STAR_SMBSERVER "*SMBSERVER"
41 /********************************************************
42 Utility function to ensure we always return at least
43 a valid char * pointer to an empty string for the
44 cli->server_os, cli->server_type and cli->server_domain
45 strings.
46 *******************************************************/
48 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
49 char *inbuf,
50 char **dest,
51 uint8_t *src,
52 size_t srclen,
53 ssize_t *destlen)
55 *destlen = clistr_pull_talloc(mem_ctx,
56 inbuf,
57 SVAL(inbuf, smb_flg2),
58 dest,
59 (char *)src,
60 srclen,
61 STR_TERMINATE);
62 if (*destlen == -1) {
63 return NT_STATUS_NO_MEMORY;
66 if (*dest == NULL) {
67 *dest = talloc_strdup(mem_ctx, "");
68 if (*dest == NULL) {
69 return NT_STATUS_NO_MEMORY;
72 return NT_STATUS_OK;
75 /**
76 * Set the user session key for a connection
77 * @param cli The cli structure to add it too
78 * @param session_key The session key used. (A copy of this is taken for the cli struct)
82 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
84 cli->user_session_key = data_blob(session_key.data, session_key.length);
87 /****************************************************************************
88 Do an old lanman2 style session setup.
89 ****************************************************************************/
91 struct cli_session_setup_lanman2_state {
92 struct cli_state *cli;
93 uint16_t vwv[10];
94 const char *user;
97 static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
99 static struct tevent_req *cli_session_setup_lanman2_send(
100 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
101 struct cli_state *cli, const char *user,
102 const char *pass, size_t passlen,
103 const char *workgroup)
105 struct tevent_req *req, *subreq;
106 struct cli_session_setup_lanman2_state *state;
107 DATA_BLOB lm_response = data_blob_null;
108 uint16_t *vwv;
109 uint8_t *bytes;
110 char *tmp;
111 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
113 req = tevent_req_create(mem_ctx, &state,
114 struct cli_session_setup_lanman2_state);
115 if (req == NULL) {
116 return NULL;
118 state->cli = cli;
119 state->user = user;
120 vwv = state->vwv;
123 * if in share level security then don't send a password now
125 if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
126 passlen = 0;
129 if (passlen > 0
130 && (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
131 && passlen != 24) {
133 * Encrypted mode needed, and non encrypted password
134 * supplied.
136 lm_response = data_blob(NULL, 24);
137 if (tevent_req_nomem(lm_response.data, req)) {
138 return tevent_req_post(req, ev);
141 if (!SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
142 (uint8_t *)lm_response.data)) {
143 DEBUG(1, ("Password is > 14 chars in length, and is "
144 "therefore incompatible with Lanman "
145 "authentication\n"));
146 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
147 return tevent_req_post(req, ev);
149 } else if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
150 && passlen == 24) {
152 * Encrypted mode needed, and encrypted password
153 * supplied.
155 lm_response = data_blob(pass, passlen);
156 if (tevent_req_nomem(lm_response.data, req)) {
157 return tevent_req_post(req, ev);
159 } else if (passlen > 0) {
160 uint8_t *buf;
161 size_t converted_size;
163 * Plaintext mode needed, assume plaintext supplied.
165 buf = talloc_array(talloc_tos(), uint8_t, 0);
166 buf = smb_bytes_push_str(buf, smbXcli_conn_use_unicode(cli->conn), pass, passlen+1,
167 &converted_size);
168 if (tevent_req_nomem(buf, req)) {
169 return tevent_req_post(req, ev);
171 lm_response = data_blob(pass, passlen);
172 TALLOC_FREE(buf);
173 if (tevent_req_nomem(lm_response.data, req)) {
174 return tevent_req_post(req, ev);
178 SCVAL(vwv+0, 0, 0xff);
179 SCVAL(vwv+0, 1, 0);
180 SSVAL(vwv+1, 0, 0);
181 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
182 SSVAL(vwv+3, 0, 2);
183 SSVAL(vwv+4, 0, 1);
184 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
185 SSVAL(vwv+7, 0, lm_response.length);
187 bytes = talloc_array(state, uint8_t, lm_response.length);
188 if (tevent_req_nomem(bytes, req)) {
189 return tevent_req_post(req, ev);
191 if (lm_response.length != 0) {
192 memcpy(bytes, lm_response.data, lm_response.length);
194 data_blob_free(&lm_response);
196 tmp = talloc_strdup_upper(talloc_tos(), user);
197 if (tevent_req_nomem(tmp, req)) {
198 return tevent_req_post(req, ev);
200 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
201 NULL);
202 TALLOC_FREE(tmp);
204 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
205 if (tevent_req_nomem(tmp, req)) {
206 return tevent_req_post(req, ev);
208 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
209 NULL);
210 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
211 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
213 if (tevent_req_nomem(bytes, req)) {
214 return tevent_req_post(req, ev);
217 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
218 talloc_get_size(bytes), bytes);
219 if (tevent_req_nomem(subreq, req)) {
220 return tevent_req_post(req, ev);
222 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
223 return req;
226 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
228 struct tevent_req *req = tevent_req_callback_data(
229 subreq, struct tevent_req);
230 struct cli_session_setup_lanman2_state *state = tevent_req_data(
231 req, struct cli_session_setup_lanman2_state);
232 struct cli_state *cli = state->cli;
233 uint32_t num_bytes;
234 uint8_t *in;
235 char *inbuf;
236 uint8_t *bytes;
237 uint8_t *p;
238 NTSTATUS status;
239 ssize_t ret;
240 uint8_t wct;
241 uint16_t *vwv;
243 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
244 &num_bytes, &bytes);
245 TALLOC_FREE(subreq);
246 if (!NT_STATUS_IS_OK(status)) {
247 tevent_req_nterror(req, status);
248 return;
251 inbuf = (char *)in;
252 p = bytes;
254 cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
255 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
257 status = smb_bytes_talloc_string(cli,
258 inbuf,
259 &cli->server_os,
261 bytes+num_bytes-p,
262 &ret);
264 if (!NT_STATUS_IS_OK(status)) {
265 tevent_req_nterror(req, status);
266 return;
268 p += ret;
270 status = smb_bytes_talloc_string(cli,
271 inbuf,
272 &cli->server_type,
274 bytes+num_bytes-p,
275 &ret);
277 if (!NT_STATUS_IS_OK(status)) {
278 tevent_req_nterror(req, status);
279 return;
281 p += ret;
283 status = smb_bytes_talloc_string(cli,
284 inbuf,
285 &cli->server_domain,
287 bytes+num_bytes-p,
288 &ret);
290 if (!NT_STATUS_IS_OK(status)) {
291 tevent_req_nterror(req, status);
292 return;
294 p += ret;
296 status = cli_set_username(cli, state->user);
297 if (tevent_req_nterror(req, status)) {
298 return;
300 tevent_req_done(req);
303 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
305 return tevent_req_simple_recv_ntstatus(req);
308 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli, const char *user,
309 const char *pass, size_t passlen,
310 const char *workgroup)
312 TALLOC_CTX *frame = talloc_stackframe();
313 struct event_context *ev;
314 struct tevent_req *req;
315 NTSTATUS status = NT_STATUS_NO_MEMORY;
317 if (smbXcli_conn_has_async_calls(cli->conn)) {
319 * Can't use sync call while an async call is in flight
321 status = NT_STATUS_INVALID_PARAMETER;
322 goto fail;
324 ev = event_context_init(frame);
325 if (ev == NULL) {
326 goto fail;
328 req = cli_session_setup_lanman2_send(frame, ev, cli, user, pass, passlen,
329 workgroup);
330 if (req == NULL) {
331 goto fail;
333 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
334 goto fail;
336 status = cli_session_setup_lanman2_recv(req);
337 fail:
338 TALLOC_FREE(frame);
339 return status;
342 /****************************************************************************
343 Work out suitable capabilities to offer the server.
344 ****************************************************************************/
346 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
347 uint32_t sesssetup_capabilities)
349 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
352 * We only send capabilities based on the mask for:
353 * - client only flags
354 * - flags used in both directions
356 * We do not echo the server only flags.
358 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_CLIENT_MASK);
361 * Session Setup specific flags CAP_DYNAMIC_REAUTH
362 * and CAP_EXTENDED_SECURITY are passed by the caller.
363 * We need that in order to do guest logins even if
364 * CAP_EXTENDED_SECURITY is negotiated.
366 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
367 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
368 client_capabilities |= sesssetup_capabilities;
370 return client_capabilities;
373 /****************************************************************************
374 Do a NT1 guest session setup.
375 ****************************************************************************/
377 struct cli_session_setup_guest_state {
378 struct cli_state *cli;
379 uint16_t vwv[13];
380 struct iovec bytes;
383 static void cli_session_setup_guest_done(struct tevent_req *subreq);
385 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
386 struct event_context *ev,
387 struct cli_state *cli,
388 struct tevent_req **psmbreq)
390 struct tevent_req *req, *subreq;
391 struct cli_session_setup_guest_state *state;
392 uint16_t *vwv;
393 uint8_t *bytes;
395 req = tevent_req_create(mem_ctx, &state,
396 struct cli_session_setup_guest_state);
397 if (req == NULL) {
398 return NULL;
400 state->cli = cli;
401 vwv = state->vwv;
403 SCVAL(vwv+0, 0, 0xFF);
404 SCVAL(vwv+0, 1, 0);
405 SSVAL(vwv+1, 0, 0);
406 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
407 SSVAL(vwv+3, 0, 2);
408 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
409 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
410 SSVAL(vwv+7, 0, 0);
411 SSVAL(vwv+8, 0, 0);
412 SSVAL(vwv+9, 0, 0);
413 SSVAL(vwv+10, 0, 0);
414 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
416 bytes = talloc_array(state, uint8_t, 0);
418 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
419 NULL);
420 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
421 NULL);
422 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
423 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
425 if (bytes == NULL) {
426 TALLOC_FREE(req);
427 return NULL;
430 state->bytes.iov_base = (void *)bytes;
431 state->bytes.iov_len = talloc_get_size(bytes);
433 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
434 1, &state->bytes);
435 if (subreq == NULL) {
436 TALLOC_FREE(req);
437 return NULL;
439 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
440 *psmbreq = subreq;
441 return req;
444 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
445 struct event_context *ev,
446 struct cli_state *cli)
448 struct tevent_req *req, *subreq;
449 NTSTATUS status;
451 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
452 if (req == NULL) {
453 return NULL;
456 status = cli_smb_req_send(subreq);
457 if (NT_STATUS_IS_OK(status)) {
458 tevent_req_nterror(req, status);
459 return tevent_req_post(req, ev);
461 return req;
464 static void cli_session_setup_guest_done(struct tevent_req *subreq)
466 struct tevent_req *req = tevent_req_callback_data(
467 subreq, struct tevent_req);
468 struct cli_session_setup_guest_state *state = tevent_req_data(
469 req, struct cli_session_setup_guest_state);
470 struct cli_state *cli = state->cli;
471 uint32_t num_bytes;
472 uint8_t *in;
473 char *inbuf;
474 uint8_t *bytes;
475 uint8_t *p;
476 NTSTATUS status;
477 ssize_t ret;
478 uint8_t wct;
479 uint16_t *vwv;
481 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
482 &num_bytes, &bytes);
483 TALLOC_FREE(subreq);
484 if (!NT_STATUS_IS_OK(status)) {
485 tevent_req_nterror(req, status);
486 return;
489 inbuf = (char *)in;
490 p = bytes;
492 cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
493 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
495 status = smb_bytes_talloc_string(cli,
496 inbuf,
497 &cli->server_os,
499 bytes+num_bytes-p,
500 &ret);
502 if (!NT_STATUS_IS_OK(status)) {
503 tevent_req_nterror(req, status);
504 return;
506 p += ret;
508 status = smb_bytes_talloc_string(cli,
509 inbuf,
510 &cli->server_type,
512 bytes+num_bytes-p,
513 &ret);
515 if (!NT_STATUS_IS_OK(status)) {
516 tevent_req_nterror(req, status);
517 return;
519 p += ret;
521 status = smb_bytes_talloc_string(cli,
522 inbuf,
523 &cli->server_domain,
525 bytes+num_bytes-p,
526 &ret);
528 if (!NT_STATUS_IS_OK(status)) {
529 tevent_req_nterror(req, status);
530 return;
532 p += ret;
534 status = cli_set_username(cli, "");
535 if (!NT_STATUS_IS_OK(status)) {
536 tevent_req_nterror(req, status);
537 return;
539 tevent_req_done(req);
542 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
544 return tevent_req_simple_recv_ntstatus(req);
547 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
549 TALLOC_CTX *frame = talloc_stackframe();
550 struct event_context *ev;
551 struct tevent_req *req;
552 NTSTATUS status = NT_STATUS_OK;
554 if (smbXcli_conn_has_async_calls(cli->conn)) {
556 * Can't use sync call while an async call is in flight
558 status = NT_STATUS_INVALID_PARAMETER;
559 goto fail;
562 ev = event_context_init(frame);
563 if (ev == NULL) {
564 status = NT_STATUS_NO_MEMORY;
565 goto fail;
568 req = cli_session_setup_guest_send(frame, ev, cli);
569 if (req == NULL) {
570 status = NT_STATUS_NO_MEMORY;
571 goto fail;
574 if (!tevent_req_poll(req, ev)) {
575 status = map_nt_error_from_unix(errno);
576 goto fail;
579 status = cli_session_setup_guest_recv(req);
580 fail:
581 TALLOC_FREE(frame);
582 return status;
585 /****************************************************************************
586 Do a NT1 plaintext session setup.
587 ****************************************************************************/
589 struct cli_session_setup_plain_state {
590 struct cli_state *cli;
591 uint16_t vwv[13];
592 const char *user;
595 static void cli_session_setup_plain_done(struct tevent_req *subreq);
597 static struct tevent_req *cli_session_setup_plain_send(
598 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
599 struct cli_state *cli,
600 const char *user, const char *pass, const char *workgroup)
602 struct tevent_req *req, *subreq;
603 struct cli_session_setup_plain_state *state;
604 uint16_t *vwv;
605 uint8_t *bytes;
606 size_t passlen;
607 char *version;
609 req = tevent_req_create(mem_ctx, &state,
610 struct cli_session_setup_plain_state);
611 if (req == NULL) {
612 return NULL;
614 state->cli = cli;
615 state->user = user;
616 vwv = state->vwv;
618 SCVAL(vwv+0, 0, 0xff);
619 SCVAL(vwv+0, 1, 0);
620 SSVAL(vwv+1, 0, 0);
621 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
622 SSVAL(vwv+3, 0, 2);
623 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
624 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
625 SSVAL(vwv+7, 0, 0);
626 SSVAL(vwv+8, 0, 0);
627 SSVAL(vwv+9, 0, 0);
628 SSVAL(vwv+10, 0, 0);
629 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
631 bytes = talloc_array(state, uint8_t, 0);
632 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), pass, strlen(pass)+1,
633 &passlen);
634 if (tevent_req_nomem(bytes, req)) {
635 return tevent_req_post(req, ev);
637 SSVAL(vwv + (smbXcli_conn_use_unicode(cli->conn) ? 8 : 7), 0, passlen);
639 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
640 user, strlen(user)+1, NULL);
641 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
642 workgroup, strlen(workgroup)+1, NULL);
643 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
644 "Unix", 5, NULL);
646 version = talloc_asprintf(talloc_tos(), "Samba %s",
647 samba_version_string());
648 if (tevent_req_nomem(version, req)){
649 return tevent_req_post(req, ev);
651 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
652 version, strlen(version)+1, NULL);
653 TALLOC_FREE(version);
655 if (tevent_req_nomem(bytes, req)) {
656 return tevent_req_post(req, ev);
659 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
660 talloc_get_size(bytes), bytes);
661 if (tevent_req_nomem(subreq, req)) {
662 return tevent_req_post(req, ev);
664 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
665 return req;
668 static void cli_session_setup_plain_done(struct tevent_req *subreq)
670 struct tevent_req *req = tevent_req_callback_data(
671 subreq, struct tevent_req);
672 struct cli_session_setup_plain_state *state = tevent_req_data(
673 req, struct cli_session_setup_plain_state);
674 struct cli_state *cli = state->cli;
675 uint32_t num_bytes;
676 uint8_t *in;
677 char *inbuf;
678 uint8_t *bytes;
679 uint8_t *p;
680 NTSTATUS status;
681 ssize_t ret;
682 uint8_t wct;
683 uint16_t *vwv;
685 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
686 &num_bytes, &bytes);
687 TALLOC_FREE(subreq);
688 if (tevent_req_nterror(req, status)) {
689 return;
692 inbuf = (char *)in;
693 p = bytes;
695 cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
696 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
698 status = smb_bytes_talloc_string(cli,
699 inbuf,
700 &cli->server_os,
702 bytes+num_bytes-p,
703 &ret);
705 if (!NT_STATUS_IS_OK(status)) {
706 tevent_req_nterror(req, status);
707 return;
709 p += ret;
711 status = smb_bytes_talloc_string(cli,
712 inbuf,
713 &cli->server_type,
715 bytes+num_bytes-p,
716 &ret);
718 if (!NT_STATUS_IS_OK(status)) {
719 tevent_req_nterror(req, status);
720 return;
722 p += ret;
724 status = smb_bytes_talloc_string(cli,
725 inbuf,
726 &cli->server_domain,
728 bytes+num_bytes-p,
729 &ret);
731 if (!NT_STATUS_IS_OK(status)) {
732 tevent_req_nterror(req, status);
733 return;
735 p += ret;
737 status = cli_set_username(cli, state->user);
738 if (tevent_req_nterror(req, status)) {
739 return;
742 tevent_req_done(req);
745 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
747 return tevent_req_simple_recv_ntstatus(req);
750 static NTSTATUS cli_session_setup_plain(struct cli_state *cli,
751 const char *user, const char *pass,
752 const char *workgroup)
754 TALLOC_CTX *frame = talloc_stackframe();
755 struct event_context *ev;
756 struct tevent_req *req;
757 NTSTATUS status = NT_STATUS_NO_MEMORY;
759 if (smbXcli_conn_has_async_calls(cli->conn)) {
761 * Can't use sync call while an async call is in flight
763 status = NT_STATUS_INVALID_PARAMETER;
764 goto fail;
766 ev = event_context_init(frame);
767 if (ev == NULL) {
768 goto fail;
770 req = cli_session_setup_plain_send(frame, ev, cli, user, pass,
771 workgroup);
772 if (req == NULL) {
773 goto fail;
775 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
776 goto fail;
778 status = cli_session_setup_plain_recv(req);
779 fail:
780 TALLOC_FREE(frame);
781 return status;
784 /****************************************************************************
785 do a NT1 NTLM/LM encrypted session setup - for when extended security
786 is not negotiated.
787 @param cli client state to create do session setup on
788 @param user username
789 @param pass *either* cleartext password (passlen !=24) or LM response.
790 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
791 @param workgroup The user's domain.
792 ****************************************************************************/
794 struct cli_session_setup_nt1_state {
795 struct cli_state *cli;
796 uint16_t vwv[13];
797 DATA_BLOB response;
798 DATA_BLOB session_key;
799 const char *user;
802 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
804 static struct tevent_req *cli_session_setup_nt1_send(
805 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
806 struct cli_state *cli, const char *user,
807 const char *pass, size_t passlen,
808 const char *ntpass, size_t ntpasslen,
809 const char *workgroup)
811 struct tevent_req *req, *subreq;
812 struct cli_session_setup_nt1_state *state;
813 DATA_BLOB lm_response = data_blob_null;
814 DATA_BLOB nt_response = data_blob_null;
815 DATA_BLOB session_key = data_blob_null;
816 uint16_t *vwv;
817 uint8_t *bytes;
818 char *workgroup_upper;
820 req = tevent_req_create(mem_ctx, &state,
821 struct cli_session_setup_nt1_state);
822 if (req == NULL) {
823 return NULL;
825 state->cli = cli;
826 state->user = user;
827 vwv = state->vwv;
829 if (passlen == 0) {
830 /* do nothing - guest login */
831 } else if (passlen != 24) {
832 if (lp_client_ntlmv2_auth()) {
833 DATA_BLOB server_chal;
834 DATA_BLOB names_blob;
836 server_chal =
837 data_blob_const(smb1cli_conn_server_challenge(cli->conn),
841 * note that the 'workgroup' here is a best
842 * guess - we don't know the server's domain
843 * at this point. Windows clients also don't
844 * use hostname...
846 names_blob = NTLMv2_generate_names_blob(
847 NULL, NULL, workgroup);
849 if (tevent_req_nomem(names_blob.data, req)) {
850 return tevent_req_post(req, ev);
853 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
854 &server_chal, &names_blob,
855 &lm_response, &nt_response,
856 NULL, &session_key)) {
857 data_blob_free(&names_blob);
858 tevent_req_nterror(
859 req, NT_STATUS_ACCESS_DENIED);
860 return tevent_req_post(req, ev);
862 data_blob_free(&names_blob);
864 } else {
865 uchar nt_hash[16];
866 E_md4hash(pass, nt_hash);
868 #ifdef LANMAN_ONLY
869 nt_response = data_blob_null;
870 #else
871 nt_response = data_blob(NULL, 24);
872 if (tevent_req_nomem(nt_response.data, req)) {
873 return tevent_req_post(req, ev);
876 SMBNTencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
877 nt_response.data);
878 #endif
879 /* non encrypted password supplied. Ignore ntpass. */
880 if (lp_client_lanman_auth()) {
882 lm_response = data_blob(NULL, 24);
883 if (tevent_req_nomem(lm_response.data, req)) {
884 return tevent_req_post(req, ev);
887 if (!SMBencrypt(pass,
888 smb1cli_conn_server_challenge(cli->conn),
889 lm_response.data)) {
891 * Oops, the LM response is
892 * invalid, just put the NT
893 * response there instead
895 data_blob_free(&lm_response);
896 lm_response = data_blob(
897 nt_response.data,
898 nt_response.length);
900 } else {
902 * LM disabled, place NT# in LM field
903 * instead
905 lm_response = data_blob(
906 nt_response.data, nt_response.length);
909 if (tevent_req_nomem(lm_response.data, req)) {
910 return tevent_req_post(req, ev);
913 session_key = data_blob(NULL, 16);
914 if (tevent_req_nomem(session_key.data, req)) {
915 return tevent_req_post(req, ev);
917 #ifdef LANMAN_ONLY
918 E_deshash(pass, session_key.data);
919 memset(&session_key.data[8], '\0', 8);
920 #else
921 SMBsesskeygen_ntv1(nt_hash, session_key.data);
922 #endif
924 } else {
925 /* pre-encrypted password supplied. Only used for
926 security=server, can't do
927 signing because we don't have original key */
929 lm_response = data_blob(pass, passlen);
930 if (tevent_req_nomem(lm_response.data, req)) {
931 return tevent_req_post(req, ev);
934 nt_response = data_blob(ntpass, ntpasslen);
935 if (tevent_req_nomem(nt_response.data, req)) {
936 return tevent_req_post(req, ev);
940 #ifdef LANMAN_ONLY
941 state->response = data_blob_talloc(
942 state, lm_response.data, lm_response.length);
943 #else
944 state->response = data_blob_talloc(
945 state, nt_response.data, nt_response.length);
946 #endif
947 if (tevent_req_nomem(state->response.data, req)) {
948 return tevent_req_post(req, ev);
951 if (session_key.data) {
952 state->session_key = data_blob_talloc(
953 state, session_key.data, session_key.length);
954 if (tevent_req_nomem(state->session_key.data, req)) {
955 return tevent_req_post(req, ev);
958 data_blob_free(&session_key);
960 SCVAL(vwv+0, 0, 0xff);
961 SCVAL(vwv+0, 1, 0);
962 SSVAL(vwv+1, 0, 0);
963 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
964 SSVAL(vwv+3, 0, 2);
965 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
966 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
967 SSVAL(vwv+7, 0, lm_response.length);
968 SSVAL(vwv+8, 0, nt_response.length);
969 SSVAL(vwv+9, 0, 0);
970 SSVAL(vwv+10, 0, 0);
971 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
973 bytes = talloc_array(state, uint8_t,
974 lm_response.length + nt_response.length);
975 if (tevent_req_nomem(bytes, req)) {
976 return tevent_req_post(req, ev);
978 if (lm_response.length != 0) {
979 memcpy(bytes, lm_response.data, lm_response.length);
981 if (nt_response.length != 0) {
982 memcpy(bytes + lm_response.length,
983 nt_response.data, nt_response.length);
985 data_blob_free(&lm_response);
986 data_blob_free(&nt_response);
988 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
989 user, strlen(user)+1, NULL);
992 * Upper case here might help some NTLMv2 implementations
994 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
995 if (tevent_req_nomem(workgroup_upper, req)) {
996 return tevent_req_post(req, ev);
998 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
999 workgroup_upper, strlen(workgroup_upper)+1,
1000 NULL);
1001 TALLOC_FREE(workgroup_upper);
1003 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
1004 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
1005 if (tevent_req_nomem(bytes, req)) {
1006 return tevent_req_post(req, ev);
1009 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
1010 talloc_get_size(bytes), bytes);
1011 if (tevent_req_nomem(subreq, req)) {
1012 return tevent_req_post(req, ev);
1014 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
1015 return req;
1018 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
1020 struct tevent_req *req = tevent_req_callback_data(
1021 subreq, struct tevent_req);
1022 struct cli_session_setup_nt1_state *state = tevent_req_data(
1023 req, struct cli_session_setup_nt1_state);
1024 struct cli_state *cli = state->cli;
1025 uint32_t num_bytes;
1026 uint8_t *in;
1027 char *inbuf;
1028 uint8_t *bytes;
1029 uint8_t *p;
1030 NTSTATUS status;
1031 ssize_t ret;
1032 uint8_t wct;
1033 uint16_t *vwv;
1035 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
1036 &num_bytes, &bytes);
1037 TALLOC_FREE(subreq);
1038 if (!NT_STATUS_IS_OK(status)) {
1039 tevent_req_nterror(req, status);
1040 return;
1043 inbuf = (char *)in;
1044 p = bytes;
1046 cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
1047 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1049 status = smb_bytes_talloc_string(cli,
1050 inbuf,
1051 &cli->server_os,
1053 bytes+num_bytes-p,
1054 &ret);
1055 if (!NT_STATUS_IS_OK(status)) {
1056 tevent_req_nterror(req, status);
1057 return;
1059 p += ret;
1061 status = smb_bytes_talloc_string(cli,
1062 inbuf,
1063 &cli->server_type,
1065 bytes+num_bytes-p,
1066 &ret);
1067 if (!NT_STATUS_IS_OK(status)) {
1068 tevent_req_nterror(req, status);
1069 return;
1071 p += ret;
1073 status = smb_bytes_talloc_string(cli,
1074 inbuf,
1075 &cli->server_domain,
1077 bytes+num_bytes-p,
1078 &ret);
1079 if (!NT_STATUS_IS_OK(status)) {
1080 tevent_req_nterror(req, status);
1081 return;
1083 p += ret;
1085 status = cli_set_username(cli, state->user);
1086 if (tevent_req_nterror(req, status)) {
1087 return;
1089 if (smb1cli_conn_activate_signing(cli->conn, state->session_key, state->response)
1090 && !smb1cli_conn_check_signing(cli->conn, (uint8_t *)in, 1)) {
1091 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1092 return;
1094 if (state->session_key.data) {
1095 /* Have plaintext orginal */
1096 cli_set_session_key(cli, state->session_key);
1098 tevent_req_done(req);
1101 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
1103 return tevent_req_simple_recv_ntstatus(req);
1106 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
1107 const char *pass, size_t passlen,
1108 const char *ntpass, size_t ntpasslen,
1109 const char *workgroup)
1111 TALLOC_CTX *frame = talloc_stackframe();
1112 struct event_context *ev;
1113 struct tevent_req *req;
1114 NTSTATUS status = NT_STATUS_NO_MEMORY;
1116 if (smbXcli_conn_has_async_calls(cli->conn)) {
1118 * Can't use sync call while an async call is in flight
1120 status = NT_STATUS_INVALID_PARAMETER;
1121 goto fail;
1123 ev = event_context_init(frame);
1124 if (ev == NULL) {
1125 goto fail;
1127 req = cli_session_setup_nt1_send(frame, ev, cli, user, pass, passlen,
1128 ntpass, ntpasslen, workgroup);
1129 if (req == NULL) {
1130 goto fail;
1132 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1133 goto fail;
1135 status = cli_session_setup_nt1_recv(req);
1136 fail:
1137 TALLOC_FREE(frame);
1138 return status;
1141 /* The following is calculated from :
1142 * (smb_size-4) = 35
1143 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
1144 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1145 * end of packet.
1148 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1150 struct cli_sesssetup_blob_state {
1151 struct tevent_context *ev;
1152 struct cli_state *cli;
1153 DATA_BLOB blob;
1154 uint16_t max_blob_size;
1155 uint16_t vwv[12];
1156 uint8_t *buf;
1158 DATA_BLOB smb2_blob;
1159 struct iovec *recv_iov;
1161 NTSTATUS status;
1162 char *inbuf;
1163 DATA_BLOB ret_blob;
1166 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1167 struct tevent_req **psubreq);
1168 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1170 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1171 struct tevent_context *ev,
1172 struct cli_state *cli,
1173 DATA_BLOB blob)
1175 struct tevent_req *req, *subreq;
1176 struct cli_sesssetup_blob_state *state;
1177 uint32_t usable_space;
1179 req = tevent_req_create(mem_ctx, &state,
1180 struct cli_sesssetup_blob_state);
1181 if (req == NULL) {
1182 return NULL;
1184 state->ev = ev;
1185 state->blob = blob;
1186 state->cli = cli;
1188 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1189 usable_space = UINT16_MAX;
1190 } else {
1191 usable_space = cli_state_available_size(cli,
1192 BASE_SESSSETUP_BLOB_PACKET_SIZE);
1195 if (usable_space == 0) {
1196 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1197 "(not possible to send %u bytes)\n",
1198 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
1199 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1200 return tevent_req_post(req, ev);
1202 state->max_blob_size = MIN(usable_space, 0xFFFF);
1204 if (!cli_sesssetup_blob_next(state, &subreq)) {
1205 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1206 return tevent_req_post(req, ev);
1208 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1209 return req;
1212 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1213 struct tevent_req **psubreq)
1215 struct tevent_req *subreq;
1216 uint16_t thistime;
1218 thistime = MIN(state->blob.length, state->max_blob_size);
1220 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1222 state->smb2_blob.data = state->blob.data;
1223 state->smb2_blob.length = thistime;
1225 state->blob.data += thistime;
1226 state->blob.length -= thistime;
1228 subreq = smb2cli_session_setup_send(state, state->ev,
1229 state->cli->conn,
1230 state->cli->timeout,
1231 state->cli->smb2.session,
1232 0, /* in_flags */
1233 SMB2_CAP_DFS, /* in_capabilities */
1234 0, /* in_channel */
1235 0, /* in_previous_session_id */
1236 &state->smb2_blob);
1237 if (subreq == NULL) {
1238 return false;
1240 *psubreq = subreq;
1241 return true;
1244 SCVAL(state->vwv+0, 0, 0xFF);
1245 SCVAL(state->vwv+0, 1, 0);
1246 SSVAL(state->vwv+1, 0, 0);
1247 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1248 SSVAL(state->vwv+3, 0, 2);
1249 SSVAL(state->vwv+4, 0, 1);
1250 SIVAL(state->vwv+5, 0, 0);
1252 SSVAL(state->vwv+7, 0, thistime);
1254 SSVAL(state->vwv+8, 0, 0);
1255 SSVAL(state->vwv+9, 0, 0);
1256 SIVAL(state->vwv+10, 0,
1257 cli_session_setup_capabilities(state->cli, CAP_EXTENDED_SECURITY));
1259 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1260 thistime);
1261 if (state->buf == NULL) {
1262 return false;
1264 state->blob.data += thistime;
1265 state->blob.length -= thistime;
1267 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1268 "Unix", 5, NULL);
1269 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1270 "Samba", 6, NULL);
1271 if (state->buf == NULL) {
1272 return false;
1274 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1275 12, state->vwv,
1276 talloc_get_size(state->buf), state->buf);
1277 if (subreq == NULL) {
1278 return false;
1280 *psubreq = subreq;
1281 return true;
1284 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1286 struct tevent_req *req = tevent_req_callback_data(
1287 subreq, struct tevent_req);
1288 struct cli_sesssetup_blob_state *state = tevent_req_data(
1289 req, struct cli_sesssetup_blob_state);
1290 struct cli_state *cli = state->cli;
1291 uint8_t wct;
1292 uint16_t *vwv;
1293 uint32_t num_bytes;
1294 uint8_t *bytes;
1295 NTSTATUS status;
1296 uint8_t *p;
1297 uint16_t blob_length;
1298 uint8_t *inbuf;
1299 ssize_t ret;
1301 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1302 status = smb2cli_session_setup_recv(subreq, state,
1303 &state->recv_iov,
1304 &state->ret_blob);
1305 } else {
1306 status = cli_smb_recv(subreq, state, &inbuf, 4, &wct, &vwv,
1307 &num_bytes, &bytes);
1308 TALLOC_FREE(state->buf);
1310 TALLOC_FREE(subreq);
1311 if (!NT_STATUS_IS_OK(status)
1312 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1313 tevent_req_nterror(req, status);
1314 return;
1317 state->status = status;
1319 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1320 goto next;
1323 state->inbuf = (char *)inbuf;
1324 cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
1325 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1327 blob_length = SVAL(vwv+3, 0);
1328 if (blob_length > num_bytes) {
1329 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1330 return;
1332 state->ret_blob = data_blob_const(bytes, blob_length);
1334 p = bytes + blob_length;
1336 status = smb_bytes_talloc_string(cli,
1337 (char *)inbuf,
1338 &cli->server_os,
1340 bytes+num_bytes-p,
1341 &ret);
1343 if (!NT_STATUS_IS_OK(status)) {
1344 tevent_req_nterror(req, status);
1345 return;
1347 p += ret;
1349 status = smb_bytes_talloc_string(cli,
1350 (char *)inbuf,
1351 &cli->server_type,
1353 bytes+num_bytes-p,
1354 &ret);
1356 if (!NT_STATUS_IS_OK(status)) {
1357 tevent_req_nterror(req, status);
1358 return;
1360 p += ret;
1362 status = smb_bytes_talloc_string(cli,
1363 (char *)inbuf,
1364 &cli->server_domain,
1366 bytes+num_bytes-p,
1367 &ret);
1369 if (!NT_STATUS_IS_OK(status)) {
1370 tevent_req_nterror(req, status);
1371 return;
1373 p += ret;
1375 next:
1376 if (state->blob.length != 0) {
1378 * More to send
1380 if (!cli_sesssetup_blob_next(state, &subreq)) {
1381 tevent_req_oom(req);
1382 return;
1384 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1385 return;
1387 tevent_req_done(req);
1390 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1391 TALLOC_CTX *mem_ctx,
1392 DATA_BLOB *pblob,
1393 char **pinbuf,
1394 struct iovec **precv_iov)
1396 struct cli_sesssetup_blob_state *state = tevent_req_data(
1397 req, struct cli_sesssetup_blob_state);
1398 NTSTATUS status;
1399 char *inbuf;
1400 struct iovec *recv_iov;
1402 if (tevent_req_is_nterror(req, &status)) {
1403 TALLOC_FREE(state->cli->smb2.session);
1404 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1405 return status;
1408 inbuf = talloc_move(mem_ctx, &state->inbuf);
1409 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
1410 if (pblob != NULL) {
1411 *pblob = state->ret_blob;
1413 if (pinbuf != NULL) {
1414 *pinbuf = inbuf;
1416 if (precv_iov != NULL) {
1417 *precv_iov = recv_iov;
1419 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1420 return state->status;
1423 #ifdef HAVE_KRB5
1425 /****************************************************************************
1426 Use in-memory credentials cache
1427 ****************************************************************************/
1429 static void use_in_memory_ccache(void) {
1430 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1433 /****************************************************************************
1434 Do a spnego/kerberos encrypted session setup.
1435 ****************************************************************************/
1437 struct cli_session_setup_kerberos_state {
1438 struct cli_state *cli;
1439 DATA_BLOB negTokenTarg;
1440 DATA_BLOB session_key_krb5;
1441 ADS_STATUS ads_status;
1444 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
1446 static struct tevent_req *cli_session_setup_kerberos_send(
1447 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1448 const char *principal)
1450 struct tevent_req *req, *subreq;
1451 struct cli_session_setup_kerberos_state *state;
1452 int rc;
1454 DEBUG(2,("Doing kerberos session setup\n"));
1456 req = tevent_req_create(mem_ctx, &state,
1457 struct cli_session_setup_kerberos_state);
1458 if (req == NULL) {
1459 return NULL;
1461 state->cli = cli;
1462 state->ads_status = ADS_SUCCESS;
1465 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1466 * we have to acquire a ticket. To be fixed later :-)
1468 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
1469 &state->session_key_krb5, 0, NULL);
1470 if (rc) {
1471 DEBUG(1, ("cli_session_setup_kerberos: "
1472 "spnego_gen_krb5_negTokenInit failed: %s\n",
1473 error_message(rc)));
1474 state->ads_status = ADS_ERROR_KRB5(rc);
1475 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1476 return tevent_req_post(req, ev);
1479 #if 0
1480 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1481 state->negTokenTarg.length);
1482 #endif
1484 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1485 state->cli->smb2.session = smbXcli_session_create(cli,
1486 cli->conn);
1487 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1488 return tevent_req_post(req, ev);
1492 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1493 if (tevent_req_nomem(subreq, req)) {
1494 return tevent_req_post(req, ev);
1496 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1497 return req;
1500 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1502 struct tevent_req *req = tevent_req_callback_data(
1503 subreq, struct tevent_req);
1504 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1505 req, struct cli_session_setup_kerberos_state);
1506 char *inbuf = NULL;
1507 struct iovec *recv_iov = NULL;
1508 NTSTATUS status;
1510 status = cli_sesssetup_blob_recv(subreq, state,
1511 NULL, &inbuf, &recv_iov);
1512 TALLOC_FREE(subreq);
1513 if (!NT_STATUS_IS_OK(status)) {
1514 tevent_req_nterror(req, status);
1515 return;
1518 cli_set_session_key(state->cli, state->session_key_krb5);
1520 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1521 struct smbXcli_session *session = state->cli->smb2.session;
1522 status = smb2cli_session_set_session_key(session,
1523 state->session_key_krb5,
1524 recv_iov);
1525 if (tevent_req_nterror(req, status)) {
1526 return;
1528 } else {
1529 if (smb1cli_conn_activate_signing(state->cli->conn, state->session_key_krb5,
1530 data_blob_null)
1531 && !smb1cli_conn_check_signing(state->cli->conn, (uint8_t *)inbuf, 1)) {
1532 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1533 return;
1537 tevent_req_done(req);
1540 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1542 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1543 req, struct cli_session_setup_kerberos_state);
1544 NTSTATUS status;
1546 if (tevent_req_is_nterror(req, &status)) {
1547 return ADS_ERROR_NT(status);
1549 return state->ads_status;
1552 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
1553 const char *principal)
1555 struct tevent_context *ev;
1556 struct tevent_req *req;
1557 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1559 if (smbXcli_conn_has_async_calls(cli->conn)) {
1560 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1562 ev = tevent_context_init(talloc_tos());
1563 if (ev == NULL) {
1564 goto fail;
1566 req = cli_session_setup_kerberos_send(ev, ev, cli, principal);
1567 if (req == NULL) {
1568 goto fail;
1570 if (!tevent_req_poll(req, ev)) {
1571 status = ADS_ERROR_SYSTEM(errno);
1572 goto fail;
1574 status = cli_session_setup_kerberos_recv(req);
1575 fail:
1576 TALLOC_FREE(ev);
1577 return status;
1579 #endif /* HAVE_KRB5 */
1581 /****************************************************************************
1582 Do a spnego/NTLMSSP encrypted session setup.
1583 ****************************************************************************/
1585 struct cli_session_setup_ntlmssp_state {
1586 struct tevent_context *ev;
1587 struct cli_state *cli;
1588 struct ntlmssp_state *ntlmssp_state;
1589 int turn;
1590 DATA_BLOB blob_out;
1593 static int cli_session_setup_ntlmssp_state_destructor(
1594 struct cli_session_setup_ntlmssp_state *state)
1596 if (state->ntlmssp_state != NULL) {
1597 TALLOC_FREE(state->ntlmssp_state);
1599 return 0;
1602 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1604 static struct tevent_req *cli_session_setup_ntlmssp_send(
1605 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1606 const char *user, const char *pass, const char *domain)
1608 struct tevent_req *req, *subreq;
1609 struct cli_session_setup_ntlmssp_state *state;
1610 NTSTATUS status;
1611 DATA_BLOB blob_out;
1612 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1614 req = tevent_req_create(mem_ctx, &state,
1615 struct cli_session_setup_ntlmssp_state);
1616 if (req == NULL) {
1617 return NULL;
1619 state->ev = ev;
1620 state->cli = cli;
1621 state->turn = 1;
1623 state->ntlmssp_state = NULL;
1624 talloc_set_destructor(
1625 state, cli_session_setup_ntlmssp_state_destructor);
1627 status = ntlmssp_client_start(state,
1628 lp_netbios_name(),
1629 lp_workgroup(),
1630 lp_client_ntlmv2_auth(),
1631 &state->ntlmssp_state);
1632 if (!NT_STATUS_IS_OK(status)) {
1633 goto fail;
1635 ntlmssp_want_feature(state->ntlmssp_state,
1636 NTLMSSP_FEATURE_SESSION_KEY);
1637 if (cli->use_ccache) {
1638 ntlmssp_want_feature(state->ntlmssp_state,
1639 NTLMSSP_FEATURE_CCACHE);
1641 status = ntlmssp_set_username(state->ntlmssp_state, user);
1642 if (!NT_STATUS_IS_OK(status)) {
1643 goto fail;
1645 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1646 if (!NT_STATUS_IS_OK(status)) {
1647 goto fail;
1649 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1650 if (!NT_STATUS_IS_OK(status)) {
1651 goto fail;
1653 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1654 &blob_out);
1655 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1656 goto fail;
1659 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1660 data_blob_free(&blob_out);
1662 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1663 state->cli->smb2.session = smbXcli_session_create(cli,
1664 cli->conn);
1665 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1666 return tevent_req_post(req, ev);
1670 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1671 if (tevent_req_nomem(subreq, req)) {
1672 return tevent_req_post(req, ev);
1674 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1675 return req;
1676 fail:
1677 tevent_req_nterror(req, status);
1678 return tevent_req_post(req, ev);
1681 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1683 struct tevent_req *req = tevent_req_callback_data(
1684 subreq, struct tevent_req);
1685 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1686 req, struct cli_session_setup_ntlmssp_state);
1687 DATA_BLOB blob_in, msg_in, blob_out;
1688 char *inbuf = NULL;
1689 struct iovec *recv_iov = NULL;
1690 bool parse_ret;
1691 NTSTATUS status;
1693 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1694 &inbuf, &recv_iov);
1695 TALLOC_FREE(subreq);
1696 data_blob_free(&state->blob_out);
1698 if (NT_STATUS_IS_OK(status)) {
1699 if (state->cli->server_domain[0] == '\0') {
1700 TALLOC_FREE(state->cli->server_domain);
1701 state->cli->server_domain = talloc_strdup(state->cli,
1702 state->ntlmssp_state->server.netbios_domain);
1703 if (state->cli->server_domain == NULL) {
1704 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1705 return;
1708 cli_set_session_key(
1709 state->cli, state->ntlmssp_state->session_key);
1711 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1712 struct smbXcli_session *session = state->cli->smb2.session;
1714 if (ntlmssp_is_anonymous(state->ntlmssp_state)) {
1716 * Windows server does not set the
1717 * SMB2_SESSION_FLAG_IS_GUEST nor
1718 * SMB2_SESSION_FLAG_IS_NULL flag.
1720 * This fix makes sure we do not try
1721 * to verify a signature on the final
1722 * session setup response.
1724 TALLOC_FREE(state->ntlmssp_state);
1725 tevent_req_done(req);
1726 return;
1729 status = smb2cli_session_set_session_key(session,
1730 state->ntlmssp_state->session_key,
1731 recv_iov);
1732 if (tevent_req_nterror(req, status)) {
1733 return;
1735 } else {
1736 if (smb1cli_conn_activate_signing(
1737 state->cli->conn, state->ntlmssp_state->session_key,
1738 data_blob_null)
1739 && !smb1cli_conn_check_signing(state->cli->conn, (uint8_t *)inbuf, 1)) {
1740 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1741 return;
1744 TALLOC_FREE(state->ntlmssp_state);
1745 tevent_req_done(req);
1746 return;
1748 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1749 tevent_req_nterror(req, status);
1750 return;
1753 if (blob_in.length == 0) {
1754 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1755 return;
1758 if ((state->turn == 1)
1759 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1760 DATA_BLOB tmp_blob = data_blob_null;
1761 /* the server might give us back two challenges */
1762 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1763 &tmp_blob);
1764 data_blob_free(&tmp_blob);
1765 } else {
1766 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1767 OID_NTLMSSP, &msg_in);
1769 state->turn += 1;
1771 if (!parse_ret) {
1772 DEBUG(3,("Failed to parse auth response\n"));
1773 if (NT_STATUS_IS_OK(status)
1774 || NT_STATUS_EQUAL(status,
1775 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1776 tevent_req_nterror(
1777 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1778 return;
1782 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1784 if (!NT_STATUS_IS_OK(status)
1785 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1786 TALLOC_FREE(state->ntlmssp_state);
1787 tevent_req_nterror(req, status);
1788 return;
1791 state->blob_out = spnego_gen_auth(state, blob_out);
1792 if (tevent_req_nomem(state->blob_out.data, req)) {
1793 return;
1796 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1797 state->blob_out);
1798 if (tevent_req_nomem(subreq, req)) {
1799 return;
1801 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1804 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1806 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1807 req, struct cli_session_setup_ntlmssp_state);
1808 NTSTATUS status;
1810 if (tevent_req_is_nterror(req, &status)) {
1811 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1812 return status;
1814 return NT_STATUS_OK;
1817 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1818 const char *user,
1819 const char *pass,
1820 const char *domain)
1822 struct tevent_context *ev;
1823 struct tevent_req *req;
1824 NTSTATUS status = NT_STATUS_NO_MEMORY;
1826 if (smbXcli_conn_has_async_calls(cli->conn)) {
1827 return NT_STATUS_INVALID_PARAMETER;
1829 ev = tevent_context_init(talloc_tos());
1830 if (ev == NULL) {
1831 goto fail;
1833 req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1834 if (req == NULL) {
1835 goto fail;
1837 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1838 goto fail;
1840 status = cli_session_setup_ntlmssp_recv(req);
1841 fail:
1842 TALLOC_FREE(ev);
1843 return status;
1846 /****************************************************************************
1847 Do a spnego encrypted session setup.
1849 user_domain: The shortname of the domain the user/machine is a member of.
1850 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1851 ****************************************************************************/
1853 static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
1854 const char *user,
1855 const char *pass,
1856 const char *user_domain,
1857 const char * dest_realm)
1859 char *principal = NULL;
1860 char *OIDs[ASN1_MAX_OIDS];
1861 int i;
1862 const DATA_BLOB *server_blob;
1863 DATA_BLOB blob = data_blob_null;
1864 const char *p = NULL;
1865 char *account = NULL;
1866 NTSTATUS status;
1868 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1869 if (server_blob) {
1870 blob = data_blob(server_blob->data, server_blob->length);
1873 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)blob.length));
1875 /* the server might not even do spnego */
1876 if (blob.length == 0) {
1877 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1878 goto ntlmssp;
1881 #if 0
1882 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1883 #endif
1885 /* The server sent us the first part of the SPNEGO exchange in the
1886 * negprot reply. It is WRONG to depend on the principal sent in the
1887 * negprot reply, but right now we do it. If we don't receive one,
1888 * we try to best guess, then fall back to NTLM. */
1889 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1890 OIDs[0] == NULL) {
1891 data_blob_free(&blob);
1892 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1894 data_blob_free(&blob);
1896 /* make sure the server understands kerberos */
1897 for (i=0;OIDs[i];i++) {
1898 if (i == 0)
1899 DEBUG(3,("got OID=%s\n", OIDs[i]));
1900 else
1901 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1902 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1903 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1904 cli->got_kerberos_mechanism = True;
1906 talloc_free(OIDs[i]);
1909 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1911 status = cli_set_username(cli, user);
1912 if (!NT_STATUS_IS_OK(status)) {
1913 TALLOC_FREE(principal);
1914 return ADS_ERROR_NT(status);
1917 #ifdef HAVE_KRB5
1918 /* If password is set we reauthenticate to kerberos server
1919 * and do not store results */
1921 if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
1922 ADS_STATUS rc;
1923 const char *remote_name = smbXcli_conn_remote_name(cli->conn);
1925 if (pass && *pass) {
1926 int ret;
1928 use_in_memory_ccache();
1929 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1931 if (ret){
1932 TALLOC_FREE(principal);
1933 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1934 if (cli->fallback_after_kerberos)
1935 goto ntlmssp;
1936 return ADS_ERROR_KRB5(ret);
1940 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1942 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1943 TALLOC_FREE(principal);
1946 if (principal == NULL &&
1947 !is_ipaddress(remote_name) &&
1948 !strequal(STAR_SMBSERVER,
1949 remote_name)) {
1950 DEBUG(3,("cli_session_setup_spnego: using target "
1951 "hostname not SPNEGO principal\n"));
1953 if (dest_realm) {
1954 char *realm = strupper_talloc(talloc_tos(), dest_realm);
1955 if (realm) {
1956 principal = talloc_asprintf(talloc_tos(),
1957 "cifs/%s@%s",
1958 remote_name,
1959 realm);
1960 TALLOC_FREE(realm);
1962 } else {
1963 principal = kerberos_get_principal_from_service_hostname(talloc_tos(),
1964 "cifs",
1965 remote_name,
1966 lp_realm());
1969 if (!principal) {
1970 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1972 DEBUG(3,("cli_session_setup_spnego: guessed "
1973 "server principal=%s\n",
1974 principal ? principal : "<null>"));
1977 if (principal) {
1978 rc = cli_session_setup_kerberos(cli, principal);
1979 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1980 TALLOC_FREE(principal);
1981 return rc;
1985 #endif
1987 TALLOC_FREE(principal);
1989 ntlmssp:
1991 account = talloc_strdup(talloc_tos(), user);
1992 if (!account) {
1993 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1996 /* when falling back to ntlmssp while authenticating with a machine
1997 * account strip off the realm - gd */
1999 if ((p = strchr_m(user, '@')) != NULL) {
2000 account[PTR_DIFF(p,user)] = '\0';
2003 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
2006 /****************************************************************************
2007 Send a session setup. The username and workgroup is in UNIX character
2008 format and must be converted to DOS codepage format before sending. If the
2009 password is in plaintext, the same should be done.
2010 ****************************************************************************/
2012 NTSTATUS cli_session_setup(struct cli_state *cli,
2013 const char *user,
2014 const char *pass, int passlen,
2015 const char *ntpass, int ntpasslen,
2016 const char *workgroup)
2018 char *p;
2019 char *user2;
2020 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2022 if (user) {
2023 user2 = talloc_strdup(talloc_tos(), user);
2024 } else {
2025 user2 = talloc_strdup(talloc_tos(), "");
2027 if (user2 == NULL) {
2028 return NT_STATUS_NO_MEMORY;
2031 if (!workgroup) {
2032 workgroup = "";
2035 /* allow for workgroups as part of the username */
2036 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
2037 (p=strchr_m(user2,*lp_winbind_separator()))) {
2038 *p = 0;
2039 user = p+1;
2040 strupper_m(user2);
2041 workgroup = user2;
2044 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
2045 return NT_STATUS_OK;
2048 /* now work out what sort of session setup we are going to
2049 do. I have split this into separate functions to make the
2050 flow a bit easier to understand (tridge) */
2052 /* if its an older server then we have to use the older request format */
2054 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
2055 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2056 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2057 " or 'client ntlmv2 auth = yes'\n"));
2058 return NT_STATUS_ACCESS_DENIED;
2061 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2062 !lp_client_plaintext_auth() && (*pass)) {
2063 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2064 " or 'client ntlmv2 auth = yes'\n"));
2065 return NT_STATUS_ACCESS_DENIED;
2068 return cli_session_setup_lanman2(cli, user, pass, passlen,
2069 workgroup);
2072 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2073 const char *remote_realm = cli_state_remote_realm(cli);
2074 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2075 workgroup,
2076 remote_realm);
2077 if (!ADS_ERR_OK(status)) {
2078 DEBUG(3, ("SMB2-SPNEGO login failed: %s\n", ads_errstr(status)));
2079 return ads_ntstatus(status);
2081 return NT_STATUS_OK;
2084 /* if no user is supplied then we have to do an anonymous connection.
2085 passwords are ignored */
2087 if (!user || !*user)
2088 return cli_session_setup_guest(cli);
2090 /* if the server is share level then send a plaintext null
2091 password at this point. The password is sent in the tree
2092 connect */
2094 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
2095 return cli_session_setup_plain(cli, user, "", workgroup);
2097 /* if the server doesn't support encryption then we have to use
2098 plaintext. The second password is ignored */
2100 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2101 if (!lp_client_plaintext_auth() && (*pass)) {
2102 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2103 " or 'client ntlmv2 auth = yes'\n"));
2104 return NT_STATUS_ACCESS_DENIED;
2106 return cli_session_setup_plain(cli, user, pass, workgroup);
2109 /* if the server supports extended security then use SPNEGO */
2111 if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
2112 const char *remote_realm = cli_state_remote_realm(cli);
2113 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2114 workgroup,
2115 remote_realm);
2116 if (!ADS_ERR_OK(status)) {
2117 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2118 return ads_ntstatus(status);
2120 } else {
2121 NTSTATUS status;
2123 /* otherwise do a NT1 style session setup */
2124 status = cli_session_setup_nt1(cli, user, pass, passlen,
2125 ntpass, ntpasslen, workgroup);
2126 if (!NT_STATUS_IS_OK(status)) {
2127 DEBUG(3,("cli_session_setup: NT1 session setup "
2128 "failed: %s\n", nt_errstr(status)));
2129 return status;
2133 return NT_STATUS_OK;
2136 /****************************************************************************
2137 Send a uloggoff.
2138 *****************************************************************************/
2140 struct cli_ulogoff_state {
2141 struct cli_state *cli;
2142 uint16_t vwv[3];
2145 static void cli_ulogoff_done(struct tevent_req *subreq);
2147 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2148 struct tevent_context *ev,
2149 struct cli_state *cli)
2151 struct tevent_req *req, *subreq;
2152 struct cli_ulogoff_state *state;
2154 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2155 if (req == NULL) {
2156 return NULL;
2158 state->cli = cli;
2160 SCVAL(state->vwv+0, 0, 0xFF);
2161 SCVAL(state->vwv+1, 0, 0);
2162 SSVAL(state->vwv+2, 0, 0);
2164 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2165 0, NULL);
2166 if (tevent_req_nomem(subreq, req)) {
2167 return tevent_req_post(req, ev);
2169 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2170 return req;
2173 static void cli_ulogoff_done(struct tevent_req *subreq)
2175 struct tevent_req *req = tevent_req_callback_data(
2176 subreq, struct tevent_req);
2177 struct cli_ulogoff_state *state = tevent_req_data(
2178 req, struct cli_ulogoff_state);
2179 NTSTATUS status;
2181 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2182 if (!NT_STATUS_IS_OK(status)) {
2183 tevent_req_nterror(req, status);
2184 return;
2186 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2187 tevent_req_done(req);
2190 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2192 return tevent_req_simple_recv_ntstatus(req);
2195 NTSTATUS cli_ulogoff(struct cli_state *cli)
2197 struct tevent_context *ev;
2198 struct tevent_req *req;
2199 NTSTATUS status = NT_STATUS_NO_MEMORY;
2201 if (smbXcli_conn_has_async_calls(cli->conn)) {
2202 return NT_STATUS_INVALID_PARAMETER;
2204 ev = tevent_context_init(talloc_tos());
2205 if (ev == NULL) {
2206 goto fail;
2208 req = cli_ulogoff_send(ev, ev, cli);
2209 if (req == NULL) {
2210 goto fail;
2212 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2213 goto fail;
2215 status = cli_ulogoff_recv(req);
2216 fail:
2217 TALLOC_FREE(ev);
2218 return status;
2221 /****************************************************************************
2222 Send a tconX.
2223 ****************************************************************************/
2225 struct cli_tcon_andx_state {
2226 struct cli_state *cli;
2227 uint16_t vwv[4];
2228 struct iovec bytes;
2231 static void cli_tcon_andx_done(struct tevent_req *subreq);
2233 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2234 struct event_context *ev,
2235 struct cli_state *cli,
2236 const char *share, const char *dev,
2237 const char *pass, int passlen,
2238 struct tevent_req **psmbreq)
2240 struct tevent_req *req, *subreq;
2241 struct cli_tcon_andx_state *state;
2242 uint8_t p24[24];
2243 uint16_t *vwv;
2244 char *tmp = NULL;
2245 uint8_t *bytes;
2246 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2248 *psmbreq = NULL;
2250 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2251 if (req == NULL) {
2252 return NULL;
2254 state->cli = cli;
2255 vwv = state->vwv;
2257 cli->share = talloc_strdup(cli, share);
2258 if (!cli->share) {
2259 return NULL;
2262 /* in user level security don't send a password now */
2263 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2264 passlen = 1;
2265 pass = "";
2266 } else if (pass == NULL) {
2267 DEBUG(1, ("Server not using user level security and no "
2268 "password supplied.\n"));
2269 goto access_denied;
2272 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2273 *pass && passlen != 24) {
2274 if (!lp_client_lanman_auth()) {
2275 DEBUG(1, ("Server requested LANMAN password "
2276 "(share-level security) but "
2277 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2278 goto access_denied;
2282 * Non-encrypted passwords - convert to DOS codepage before
2283 * encryption.
2285 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2286 passlen = 24;
2287 pass = (const char *)p24;
2288 } else {
2289 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2290 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2291 == 0) {
2292 uint8_t *tmp_pass;
2294 if (!lp_client_plaintext_auth() && (*pass)) {
2295 DEBUG(1, ("Server requested plaintext "
2296 "password but "
2297 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2298 goto access_denied;
2302 * Non-encrypted passwords - convert to DOS codepage
2303 * before using.
2305 tmp_pass = talloc_array(talloc_tos(), uint8, 0);
2306 if (tevent_req_nomem(tmp_pass, req)) {
2307 return tevent_req_post(req, ev);
2309 tmp_pass = trans2_bytes_push_str(tmp_pass,
2310 false, /* always DOS */
2311 pass,
2312 passlen,
2313 NULL);
2314 if (tevent_req_nomem(tmp_pass, req)) {
2315 return tevent_req_post(req, ev);
2317 pass = (const char *)tmp_pass;
2318 passlen = talloc_get_size(tmp_pass);
2322 SCVAL(vwv+0, 0, 0xFF);
2323 SCVAL(vwv+0, 1, 0);
2324 SSVAL(vwv+1, 0, 0);
2325 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
2326 SSVAL(vwv+3, 0, passlen);
2328 if (passlen && pass) {
2329 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2330 } else {
2331 bytes = talloc_array(state, uint8_t, 0);
2335 * Add the sharename
2337 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2338 smbXcli_conn_remote_name(cli->conn), share);
2339 if (tmp == NULL) {
2340 TALLOC_FREE(req);
2341 return NULL;
2343 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2344 NULL);
2345 TALLOC_FREE(tmp);
2348 * Add the devicetype
2350 tmp = talloc_strdup_upper(talloc_tos(), dev);
2351 if (tmp == NULL) {
2352 TALLOC_FREE(req);
2353 return NULL;
2355 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2356 TALLOC_FREE(tmp);
2358 if (bytes == NULL) {
2359 TALLOC_FREE(req);
2360 return NULL;
2363 state->bytes.iov_base = (void *)bytes;
2364 state->bytes.iov_len = talloc_get_size(bytes);
2366 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2367 1, &state->bytes);
2368 if (subreq == NULL) {
2369 TALLOC_FREE(req);
2370 return NULL;
2372 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2373 *psmbreq = subreq;
2374 return req;
2376 access_denied:
2377 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2378 return tevent_req_post(req, ev);
2381 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2382 struct event_context *ev,
2383 struct cli_state *cli,
2384 const char *share, const char *dev,
2385 const char *pass, int passlen)
2387 struct tevent_req *req, *subreq;
2388 NTSTATUS status;
2390 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2391 &subreq);
2392 if (req == NULL) {
2393 return NULL;
2395 if (subreq == NULL) {
2396 return req;
2398 status = cli_smb_req_send(subreq);
2399 if (!NT_STATUS_IS_OK(status)) {
2400 tevent_req_nterror(req, status);
2401 return tevent_req_post(req, ev);
2403 return req;
2406 static void cli_tcon_andx_done(struct tevent_req *subreq)
2408 struct tevent_req *req = tevent_req_callback_data(
2409 subreq, struct tevent_req);
2410 struct cli_tcon_andx_state *state = tevent_req_data(
2411 req, struct cli_tcon_andx_state);
2412 struct cli_state *cli = state->cli;
2413 uint8_t *in;
2414 char *inbuf;
2415 uint8_t wct;
2416 uint16_t *vwv;
2417 uint32_t num_bytes;
2418 uint8_t *bytes;
2419 NTSTATUS status;
2421 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2422 &num_bytes, &bytes);
2423 TALLOC_FREE(subreq);
2424 if (!NT_STATUS_IS_OK(status)) {
2425 tevent_req_nterror(req, status);
2426 return;
2429 inbuf = (char *)in;
2431 if (num_bytes) {
2432 if (clistr_pull_talloc(cli,
2433 inbuf,
2434 SVAL(inbuf, smb_flg2),
2435 &cli->dev,
2436 bytes,
2437 num_bytes,
2438 STR_TERMINATE|STR_ASCII) == -1) {
2439 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2440 return;
2442 } else {
2443 cli->dev = talloc_strdup(cli, "");
2444 if (cli->dev == NULL) {
2445 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2446 return;
2450 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2451 /* almost certainly win95 - enable bug fixes */
2452 cli->win95 = True;
2456 * Make sure that we have the optional support 16-bit field. WCT > 2.
2457 * Avoids issues when connecting to Win9x boxes sharing files
2460 cli->dfsroot = false;
2462 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2463 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
2466 cli->smb1.tid = SVAL(inbuf,smb_tid);
2467 tevent_req_done(req);
2470 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2472 return tevent_req_simple_recv_ntstatus(req);
2475 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2476 const char *dev, const char *pass, int passlen)
2478 TALLOC_CTX *frame = talloc_stackframe();
2479 struct event_context *ev;
2480 struct tevent_req *req;
2481 NTSTATUS status = NT_STATUS_OK;
2483 if (smbXcli_conn_has_async_calls(cli->conn)) {
2485 * Can't use sync call while an async call is in flight
2487 status = NT_STATUS_INVALID_PARAMETER;
2488 goto fail;
2491 ev = event_context_init(frame);
2492 if (ev == NULL) {
2493 status = NT_STATUS_NO_MEMORY;
2494 goto fail;
2497 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2498 if (req == NULL) {
2499 status = NT_STATUS_NO_MEMORY;
2500 goto fail;
2503 if (!tevent_req_poll(req, ev)) {
2504 status = map_nt_error_from_unix(errno);
2505 goto fail;
2508 status = cli_tcon_andx_recv(req);
2509 fail:
2510 TALLOC_FREE(frame);
2511 return status;
2514 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2515 const char *dev, const char *pass, int passlen)
2517 NTSTATUS status;
2518 uint16_t max_xmit = 0;
2519 uint16_t tid = 0;
2521 cli->share = talloc_strdup(cli, share);
2522 if (!cli->share) {
2523 return NT_STATUS_NO_MEMORY;
2526 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2527 return smb2cli_tcon(cli, share);
2530 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2531 return cli_tcon_andx(cli, share, dev, pass, passlen);
2534 status = cli_raw_tcon(cli, share, pass, dev, &max_xmit, &tid);
2535 if (!NT_STATUS_IS_OK(status)) {
2536 return status;
2538 cli->smb1.tid = tid;
2540 return NT_STATUS_OK;
2543 /****************************************************************************
2544 Send a tree disconnect.
2545 ****************************************************************************/
2547 struct cli_tdis_state {
2548 struct cli_state *cli;
2551 static void cli_tdis_done(struct tevent_req *subreq);
2553 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2554 struct tevent_context *ev,
2555 struct cli_state *cli)
2557 struct tevent_req *req, *subreq;
2558 struct cli_tdis_state *state;
2560 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2561 if (req == NULL) {
2562 return NULL;
2564 state->cli = cli;
2566 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2567 if (tevent_req_nomem(subreq, req)) {
2568 return tevent_req_post(req, ev);
2570 tevent_req_set_callback(subreq, cli_tdis_done, req);
2571 return req;
2574 static void cli_tdis_done(struct tevent_req *subreq)
2576 struct tevent_req *req = tevent_req_callback_data(
2577 subreq, struct tevent_req);
2578 struct cli_tdis_state *state = tevent_req_data(
2579 req, struct cli_tdis_state);
2580 NTSTATUS status;
2582 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2583 TALLOC_FREE(subreq);
2584 if (!NT_STATUS_IS_OK(status)) {
2585 tevent_req_nterror(req, status);
2586 return;
2588 state->cli->smb1.tid = UINT16_MAX;
2589 tevent_req_done(req);
2592 NTSTATUS cli_tdis_recv(struct tevent_req *req)
2594 return tevent_req_simple_recv_ntstatus(req);
2597 NTSTATUS cli_tdis(struct cli_state *cli)
2599 struct tevent_context *ev;
2600 struct tevent_req *req;
2601 NTSTATUS status = NT_STATUS_NO_MEMORY;
2603 if (smbXcli_conn_has_async_calls(cli->conn)) {
2604 return NT_STATUS_INVALID_PARAMETER;
2606 ev = tevent_context_init(talloc_tos());
2607 if (ev == NULL) {
2608 goto fail;
2610 req = cli_tdis_send(ev, ev, cli);
2611 if (req == NULL) {
2612 goto fail;
2614 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2615 goto fail;
2617 status = cli_tdis_recv(req);
2618 fail:
2619 TALLOC_FREE(ev);
2620 return status;
2623 static NTSTATUS cli_connect_sock(const char *host, int name_type,
2624 const struct sockaddr_storage *pss,
2625 const char *myname, uint16_t port,
2626 int sec_timeout, int *pfd, uint16_t *pport)
2628 TALLOC_CTX *frame = talloc_stackframe();
2629 const char *prog;
2630 unsigned int i, num_addrs;
2631 const char **called_names;
2632 const char **calling_names;
2633 int *called_types;
2634 NTSTATUS status;
2635 int fd;
2637 prog = getenv("LIBSMB_PROG");
2638 if (prog != NULL) {
2639 fd = sock_exec(prog);
2640 if (fd == -1) {
2641 return map_nt_error_from_unix(errno);
2643 port = 0;
2644 goto done;
2647 if ((pss == NULL) || is_zero_addr(pss)) {
2648 struct sockaddr_storage *addrs;
2649 status = resolve_name_list(talloc_tos(), host, name_type,
2650 &addrs, &num_addrs);
2651 if (!NT_STATUS_IS_OK(status)) {
2652 goto fail;
2654 pss = addrs;
2655 } else {
2656 num_addrs = 1;
2659 called_names = talloc_array(talloc_tos(), const char *, num_addrs);
2660 if (called_names == NULL) {
2661 status = NT_STATUS_NO_MEMORY;
2662 goto fail;
2664 called_types = talloc_array(talloc_tos(), int, num_addrs);
2665 if (called_types == NULL) {
2666 status = NT_STATUS_NO_MEMORY;
2667 goto fail;
2669 calling_names = talloc_array(talloc_tos(), const char *, num_addrs);
2670 if (calling_names == NULL) {
2671 status = NT_STATUS_NO_MEMORY;
2672 goto fail;
2674 for (i=0; i<num_addrs; i++) {
2675 called_names[i] = host;
2676 called_types[i] = name_type;
2677 calling_names[i] = myname;
2679 status = smbsock_any_connect(pss, called_names, called_types,
2680 calling_names, NULL, num_addrs, port,
2681 sec_timeout, &fd, NULL, &port);
2682 if (!NT_STATUS_IS_OK(status)) {
2683 goto fail;
2685 set_socket_options(fd, lp_socket_options());
2686 done:
2687 *pfd = fd;
2688 *pport = port;
2689 status = NT_STATUS_OK;
2690 fail:
2691 TALLOC_FREE(frame);
2692 return status;
2695 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2696 uint16_t port, int name_type, const char *myname,
2697 int signing_state, int flags, struct cli_state **pcli)
2699 TALLOC_CTX *frame = talloc_stackframe();
2700 struct cli_state *cli;
2701 NTSTATUS status = NT_STATUS_NO_MEMORY;
2702 int fd = -1;
2703 char *desthost;
2704 char *p;
2706 desthost = talloc_strdup(talloc_tos(), host);
2707 if (desthost == NULL) {
2708 goto fail;
2711 p = strchr(host, '#');
2712 if (p != NULL) {
2713 name_type = strtol(p+1, NULL, 16);
2714 host = talloc_strndup(talloc_tos(), host, p - host);
2715 if (host == NULL) {
2716 goto fail;
2720 status = cli_connect_sock(host, name_type, dest_ss, myname, port,
2721 20, &fd, &port);
2722 if (!NT_STATUS_IS_OK(status)) {
2723 goto fail;
2726 cli = cli_state_create(NULL, fd, desthost, NULL, signing_state, flags);
2727 if (cli == NULL) {
2728 close(fd);
2729 fd = -1;
2730 goto fail;
2733 *pcli = cli;
2734 status = NT_STATUS_OK;
2735 fail:
2736 TALLOC_FREE(frame);
2737 return status;
2741 establishes a connection to after the negprot.
2742 @param output_cli A fully initialised cli structure, non-null only on success
2743 @param dest_host The netbios name of the remote host
2744 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2745 @param port (optional) The destination port (0 for default)
2747 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2748 const char *my_name,
2749 const char *dest_host,
2750 const struct sockaddr_storage *dest_ss, int port,
2751 int signing_state, int flags)
2753 NTSTATUS nt_status;
2754 struct cli_state *cli;
2756 nt_status = cli_connect_nb(dest_host, dest_ss, port, 0x20, my_name,
2757 signing_state, flags, &cli);
2758 if (!NT_STATUS_IS_OK(nt_status)) {
2759 DEBUG(10, ("cli_connect_nb failed: %s\n",
2760 nt_errstr(nt_status)));
2761 return nt_status;
2764 nt_status = smbXcli_negprot(cli->conn, cli->timeout, PROTOCOL_CORE,
2765 PROTOCOL_NT1);
2766 if (!NT_STATUS_IS_OK(nt_status)) {
2767 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2768 cli_shutdown(cli);
2769 return nt_status;
2772 *output_cli = cli;
2773 return NT_STATUS_OK;
2778 establishes a connection right up to doing tconX, password specified.
2779 @param output_cli A fully initialised cli structure, non-null only on success
2780 @param dest_host The netbios name of the remote host
2781 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2782 @param port (optional) The destination port (0 for default)
2783 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2784 @param service_type The 'type' of serivice.
2785 @param user Username, unix string
2786 @param domain User's domain
2787 @param password User's password, unencrypted unix string.
2790 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2791 const char *my_name,
2792 const char *dest_host,
2793 const struct sockaddr_storage *dest_ss, int port,
2794 const char *service, const char *service_type,
2795 const char *user, const char *domain,
2796 const char *password, int flags,
2797 int signing_state)
2799 NTSTATUS nt_status;
2800 struct cli_state *cli = NULL;
2801 int pw_len = password ? strlen(password)+1 : 0;
2803 *output_cli = NULL;
2805 if (password == NULL) {
2806 password = "";
2809 nt_status = cli_start_connection(&cli, my_name, dest_host,
2810 dest_ss, port, signing_state,
2811 flags);
2813 if (!NT_STATUS_IS_OK(nt_status)) {
2814 return nt_status;
2817 nt_status = cli_session_setup(cli, user, password, pw_len, password,
2818 pw_len, domain);
2819 if (!NT_STATUS_IS_OK(nt_status)) {
2821 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2822 DEBUG(1,("failed session setup with %s\n",
2823 nt_errstr(nt_status)));
2824 cli_shutdown(cli);
2825 return nt_status;
2828 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2829 if (!NT_STATUS_IS_OK(nt_status)) {
2830 DEBUG(1,("anonymous failed session setup with %s\n",
2831 nt_errstr(nt_status)));
2832 cli_shutdown(cli);
2833 return nt_status;
2837 if (service) {
2838 nt_status = cli_tcon_andx(cli, service, service_type, password,
2839 pw_len);
2840 if (!NT_STATUS_IS_OK(nt_status)) {
2841 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2842 cli_shutdown(cli);
2843 if (NT_STATUS_IS_OK(nt_status)) {
2844 nt_status = NT_STATUS_UNSUCCESSFUL;
2846 return nt_status;
2850 nt_status = cli_init_creds(cli, user, domain, password);
2851 if (!NT_STATUS_IS_OK(nt_status)) {
2852 cli_shutdown(cli);
2853 return nt_status;
2856 *output_cli = cli;
2857 return NT_STATUS_OK;
2860 /****************************************************************************
2861 Send an old style tcon.
2862 ****************************************************************************/
2863 NTSTATUS cli_raw_tcon(struct cli_state *cli,
2864 const char *service, const char *pass, const char *dev,
2865 uint16 *max_xmit, uint16 *tid)
2867 struct tevent_req *req;
2868 uint16_t *ret_vwv;
2869 uint8_t *bytes;
2870 NTSTATUS status;
2872 if (!lp_client_plaintext_auth() && (*pass)) {
2873 DEBUG(1, ("Server requested plaintext password but 'client "
2874 "plaintext auth' is disabled\n"));
2875 return NT_STATUS_ACCESS_DENIED;
2878 bytes = talloc_array(talloc_tos(), uint8_t, 0);
2879 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
2880 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
2881 service, strlen(service)+1, NULL);
2882 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
2883 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
2884 pass, strlen(pass)+1, NULL);
2885 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
2886 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
2887 dev, strlen(dev)+1, NULL);
2889 status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
2890 talloc_get_size(bytes), bytes, &req,
2891 2, NULL, &ret_vwv, NULL, NULL);
2892 if (!NT_STATUS_IS_OK(status)) {
2893 return status;
2896 *max_xmit = SVAL(ret_vwv + 0, 0);
2897 *tid = SVAL(ret_vwv + 1, 0);
2899 return NT_STATUS_OK;
2902 /* Return a cli_state pointing at the IPC$ share for the given server */
2904 struct cli_state *get_ipc_connect(char *server,
2905 struct sockaddr_storage *server_ss,
2906 const struct user_auth_info *user_info)
2908 struct cli_state *cli;
2909 NTSTATUS nt_status;
2910 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2912 if (user_info->use_kerberos) {
2913 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2916 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
2917 user_info->username ? user_info->username : "",
2918 lp_workgroup(),
2919 user_info->password ? user_info->password : "",
2920 flags,
2921 SMB_SIGNING_DEFAULT);
2923 if (NT_STATUS_IS_OK(nt_status)) {
2924 return cli;
2925 } else if (is_ipaddress(server)) {
2926 /* windows 9* needs a correct NMB name for connections */
2927 fstring remote_name;
2929 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2930 cli = get_ipc_connect(remote_name, server_ss, user_info);
2931 if (cli)
2932 return cli;
2935 return NULL;
2939 * Given the IP address of a master browser on the network, return its
2940 * workgroup and connect to it.
2942 * This function is provided to allow additional processing beyond what
2943 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2944 * browsers and obtain each master browsers' list of domains (in case the
2945 * first master browser is recently on the network and has not yet
2946 * synchronized with other master browsers and therefore does not yet have the
2947 * entire network browse list)
2950 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2951 struct sockaddr_storage *mb_ip,
2952 const struct user_auth_info *user_info,
2953 char **pp_workgroup_out)
2955 char addr[INET6_ADDRSTRLEN];
2956 fstring name;
2957 struct cli_state *cli;
2958 struct sockaddr_storage server_ss;
2960 *pp_workgroup_out = NULL;
2962 print_sockaddr(addr, sizeof(addr), mb_ip);
2963 DEBUG(99, ("Looking up name of master browser %s\n",
2964 addr));
2967 * Do a name status query to find out the name of the master browser.
2968 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2969 * master browser will not respond to a wildcard query (or, at least,
2970 * an NT4 server acting as the domain master browser will not).
2972 * We might be able to use ONLY the query on MSBROWSE, but that's not
2973 * yet been tested with all Windows versions, so until it is, leave
2974 * the original wildcard query as the first choice and fall back to
2975 * MSBROWSE if the wildcard query fails.
2977 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
2978 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
2980 DEBUG(99, ("Could not retrieve name status for %s\n",
2981 addr));
2982 return NULL;
2985 if (!find_master_ip(name, &server_ss)) {
2986 DEBUG(99, ("Could not find master ip for %s\n", name));
2987 return NULL;
2990 *pp_workgroup_out = talloc_strdup(ctx, name);
2992 DEBUG(4, ("found master browser %s, %s\n", name, addr));
2994 print_sockaddr(addr, sizeof(addr), &server_ss);
2995 cli = get_ipc_connect(addr, &server_ss, user_info);
2997 return cli;
3001 * Return the IP address and workgroup of a master browser on the network, and
3002 * connect to it.
3005 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3006 const struct user_auth_info *user_info,
3007 char **pp_workgroup_out)
3009 struct sockaddr_storage *ip_list;
3010 struct cli_state *cli;
3011 int i, count;
3012 NTSTATUS status;
3014 *pp_workgroup_out = NULL;
3016 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3018 /* Go looking for workgroups by broadcasting on the local network */
3020 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3021 &ip_list, &count);
3022 if (!NT_STATUS_IS_OK(status)) {
3023 DEBUG(99, ("No master browsers responded: %s\n",
3024 nt_errstr(status)));
3025 return NULL;
3028 for (i = 0; i < count; i++) {
3029 char addr[INET6_ADDRSTRLEN];
3030 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3031 DEBUG(99, ("Found master browser %s\n", addr));
3033 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3034 user_info, pp_workgroup_out);
3035 if (cli)
3036 return(cli);
3039 return NULL;