s3: Add cli_state->pw_nt_hash
[Samba/gebeck_regimport.git] / source3 / libsmb / cliconnect.c
blobacc3a21c744b7c70c307c718c0ce3be412937b13
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 const uint8_t *hdr,
50 char **dest,
51 uint8_t *src,
52 size_t srclen,
53 ssize_t *destlen)
55 *destlen = clistr_pull_talloc(mem_ctx,
56 (const char *)hdr,
57 SVAL(hdr, HDR_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 uint8_t *inhdr;
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 inhdr = in + NBT_HDR_SIZE;
252 p = bytes;
254 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
255 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
257 status = smb_bytes_talloc_string(cli,
258 inhdr,
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 inhdr,
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 inhdr,
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 = smb1cli_req_chain_submit(&subreq, 1);
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 uint8_t *inhdr;
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 inhdr = in + NBT_HDR_SIZE;
490 p = bytes;
492 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
493 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
495 status = smb_bytes_talloc_string(cli,
496 inhdr,
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 inhdr,
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 inhdr,
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 uint8_t *inhdr;
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 inhdr = in + NBT_HDR_SIZE;
693 p = bytes;
695 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
696 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
698 status = smb_bytes_talloc_string(cli,
699 inhdr,
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 inhdr,
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 inhdr,
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 uint8_t *inhdr;
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 inhdr = in + NBT_HDR_SIZE;
1044 p = bytes;
1046 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
1047 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1049 status = smb_bytes_talloc_string(cli,
1050 inhdr,
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 inhdr,
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 inhdr,
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 uint8_t *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 *in;
1299 uint8_t *inhdr;
1300 ssize_t ret;
1302 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1303 status = smb2cli_session_setup_recv(subreq, state,
1304 &state->recv_iov,
1305 &state->ret_blob);
1306 } else {
1307 status = cli_smb_recv(subreq, state, &in, 4, &wct, &vwv,
1308 &num_bytes, &bytes);
1309 TALLOC_FREE(state->buf);
1311 TALLOC_FREE(subreq);
1312 if (!NT_STATUS_IS_OK(status)
1313 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1314 tevent_req_nterror(req, status);
1315 return;
1318 state->status = status;
1320 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1321 goto next;
1324 state->inbuf = in;
1325 inhdr = in + NBT_HDR_SIZE;
1326 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
1327 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1329 blob_length = SVAL(vwv+3, 0);
1330 if (blob_length > num_bytes) {
1331 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1332 return;
1334 state->ret_blob = data_blob_const(bytes, blob_length);
1336 p = bytes + blob_length;
1338 status = smb_bytes_talloc_string(cli,
1339 inhdr,
1340 &cli->server_os,
1342 bytes+num_bytes-p,
1343 &ret);
1345 if (!NT_STATUS_IS_OK(status)) {
1346 tevent_req_nterror(req, status);
1347 return;
1349 p += ret;
1351 status = smb_bytes_talloc_string(cli,
1352 inhdr,
1353 &cli->server_type,
1355 bytes+num_bytes-p,
1356 &ret);
1358 if (!NT_STATUS_IS_OK(status)) {
1359 tevent_req_nterror(req, status);
1360 return;
1362 p += ret;
1364 status = smb_bytes_talloc_string(cli,
1365 inhdr,
1366 &cli->server_domain,
1368 bytes+num_bytes-p,
1369 &ret);
1371 if (!NT_STATUS_IS_OK(status)) {
1372 tevent_req_nterror(req, status);
1373 return;
1375 p += ret;
1377 next:
1378 if (state->blob.length != 0) {
1380 * More to send
1382 if (!cli_sesssetup_blob_next(state, &subreq)) {
1383 tevent_req_oom(req);
1384 return;
1386 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1387 return;
1389 tevent_req_done(req);
1392 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1393 TALLOC_CTX *mem_ctx,
1394 DATA_BLOB *pblob,
1395 uint8_t **pinbuf,
1396 struct iovec **precv_iov)
1398 struct cli_sesssetup_blob_state *state = tevent_req_data(
1399 req, struct cli_sesssetup_blob_state);
1400 NTSTATUS status;
1401 uint8_t *inbuf;
1402 struct iovec *recv_iov;
1404 if (tevent_req_is_nterror(req, &status)) {
1405 TALLOC_FREE(state->cli->smb2.session);
1406 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1407 return status;
1410 inbuf = talloc_move(mem_ctx, &state->inbuf);
1411 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
1412 if (pblob != NULL) {
1413 *pblob = state->ret_blob;
1415 if (pinbuf != NULL) {
1416 *pinbuf = inbuf;
1418 if (precv_iov != NULL) {
1419 *precv_iov = recv_iov;
1421 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1422 return state->status;
1425 #ifdef HAVE_KRB5
1427 /****************************************************************************
1428 Use in-memory credentials cache
1429 ****************************************************************************/
1431 static void use_in_memory_ccache(void) {
1432 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1435 /****************************************************************************
1436 Do a spnego/kerberos encrypted session setup.
1437 ****************************************************************************/
1439 struct cli_session_setup_kerberos_state {
1440 struct cli_state *cli;
1441 DATA_BLOB negTokenTarg;
1442 DATA_BLOB session_key_krb5;
1443 ADS_STATUS ads_status;
1446 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
1448 static struct tevent_req *cli_session_setup_kerberos_send(
1449 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1450 const char *principal)
1452 struct tevent_req *req, *subreq;
1453 struct cli_session_setup_kerberos_state *state;
1454 int rc;
1456 DEBUG(2,("Doing kerberos session setup\n"));
1458 req = tevent_req_create(mem_ctx, &state,
1459 struct cli_session_setup_kerberos_state);
1460 if (req == NULL) {
1461 return NULL;
1463 state->cli = cli;
1464 state->ads_status = ADS_SUCCESS;
1467 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1468 * we have to acquire a ticket. To be fixed later :-)
1470 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
1471 &state->session_key_krb5, 0, NULL);
1472 if (rc) {
1473 DEBUG(1, ("cli_session_setup_kerberos: "
1474 "spnego_gen_krb5_negTokenInit failed: %s\n",
1475 error_message(rc)));
1476 state->ads_status = ADS_ERROR_KRB5(rc);
1477 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1478 return tevent_req_post(req, ev);
1481 #if 0
1482 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1483 state->negTokenTarg.length);
1484 #endif
1486 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1487 state->cli->smb2.session = smbXcli_session_create(cli,
1488 cli->conn);
1489 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1490 return tevent_req_post(req, ev);
1494 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1495 if (tevent_req_nomem(subreq, req)) {
1496 return tevent_req_post(req, ev);
1498 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1499 return req;
1502 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1504 struct tevent_req *req = tevent_req_callback_data(
1505 subreq, struct tevent_req);
1506 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1507 req, struct cli_session_setup_kerberos_state);
1508 uint8_t *inbuf = NULL;
1509 struct iovec *recv_iov = NULL;
1510 NTSTATUS status;
1512 status = cli_sesssetup_blob_recv(subreq, state,
1513 NULL, &inbuf, &recv_iov);
1514 TALLOC_FREE(subreq);
1515 if (!NT_STATUS_IS_OK(status)) {
1516 tevent_req_nterror(req, status);
1517 return;
1520 cli_set_session_key(state->cli, state->session_key_krb5);
1522 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1523 struct smbXcli_session *session = state->cli->smb2.session;
1524 status = smb2cli_session_set_session_key(session,
1525 state->session_key_krb5,
1526 recv_iov);
1527 if (tevent_req_nterror(req, status)) {
1528 return;
1530 } else {
1531 if (smb1cli_conn_activate_signing(state->cli->conn, state->session_key_krb5,
1532 data_blob_null)
1533 && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) {
1534 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1535 return;
1539 tevent_req_done(req);
1542 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1544 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1545 req, struct cli_session_setup_kerberos_state);
1546 NTSTATUS status;
1548 if (tevent_req_is_nterror(req, &status)) {
1549 return ADS_ERROR_NT(status);
1551 return state->ads_status;
1554 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
1555 const char *principal)
1557 struct tevent_context *ev;
1558 struct tevent_req *req;
1559 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1561 if (smbXcli_conn_has_async_calls(cli->conn)) {
1562 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1564 ev = tevent_context_init(talloc_tos());
1565 if (ev == NULL) {
1566 goto fail;
1568 req = cli_session_setup_kerberos_send(ev, ev, cli, principal);
1569 if (req == NULL) {
1570 goto fail;
1572 if (!tevent_req_poll(req, ev)) {
1573 status = ADS_ERROR_SYSTEM(errno);
1574 goto fail;
1576 status = cli_session_setup_kerberos_recv(req);
1577 fail:
1578 TALLOC_FREE(ev);
1579 return status;
1581 #endif /* HAVE_KRB5 */
1583 /****************************************************************************
1584 Do a spnego/NTLMSSP encrypted session setup.
1585 ****************************************************************************/
1587 struct cli_session_setup_ntlmssp_state {
1588 struct tevent_context *ev;
1589 struct cli_state *cli;
1590 struct ntlmssp_state *ntlmssp_state;
1591 int turn;
1592 DATA_BLOB blob_out;
1595 static int cli_session_setup_ntlmssp_state_destructor(
1596 struct cli_session_setup_ntlmssp_state *state)
1598 if (state->ntlmssp_state != NULL) {
1599 TALLOC_FREE(state->ntlmssp_state);
1601 return 0;
1604 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1606 static struct tevent_req *cli_session_setup_ntlmssp_send(
1607 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1608 const char *user, const char *pass, const char *domain)
1610 struct tevent_req *req, *subreq;
1611 struct cli_session_setup_ntlmssp_state *state;
1612 NTSTATUS status;
1613 DATA_BLOB blob_out;
1614 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1616 req = tevent_req_create(mem_ctx, &state,
1617 struct cli_session_setup_ntlmssp_state);
1618 if (req == NULL) {
1619 return NULL;
1621 state->ev = ev;
1622 state->cli = cli;
1623 state->turn = 1;
1625 state->ntlmssp_state = NULL;
1626 talloc_set_destructor(
1627 state, cli_session_setup_ntlmssp_state_destructor);
1629 status = ntlmssp_client_start(state,
1630 lp_netbios_name(),
1631 lp_workgroup(),
1632 lp_client_ntlmv2_auth(),
1633 &state->ntlmssp_state);
1634 if (!NT_STATUS_IS_OK(status)) {
1635 goto fail;
1637 ntlmssp_want_feature(state->ntlmssp_state,
1638 NTLMSSP_FEATURE_SESSION_KEY);
1639 if (cli->use_ccache) {
1640 ntlmssp_want_feature(state->ntlmssp_state,
1641 NTLMSSP_FEATURE_CCACHE);
1643 status = ntlmssp_set_username(state->ntlmssp_state, user);
1644 if (!NT_STATUS_IS_OK(status)) {
1645 goto fail;
1647 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1648 if (!NT_STATUS_IS_OK(status)) {
1649 goto fail;
1651 if (cli->pw_nt_hash) {
1652 status = ntlmssp_set_password_hash(state->ntlmssp_state, pass);
1653 } else {
1654 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1656 if (!NT_STATUS_IS_OK(status)) {
1657 goto fail;
1659 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1660 &blob_out);
1661 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1662 goto fail;
1665 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1666 data_blob_free(&blob_out);
1668 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1669 state->cli->smb2.session = smbXcli_session_create(cli,
1670 cli->conn);
1671 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1672 return tevent_req_post(req, ev);
1676 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1677 if (tevent_req_nomem(subreq, req)) {
1678 return tevent_req_post(req, ev);
1680 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1681 return req;
1682 fail:
1683 tevent_req_nterror(req, status);
1684 return tevent_req_post(req, ev);
1687 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1689 struct tevent_req *req = tevent_req_callback_data(
1690 subreq, struct tevent_req);
1691 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1692 req, struct cli_session_setup_ntlmssp_state);
1693 DATA_BLOB blob_in, msg_in, blob_out;
1694 uint8_t *inbuf = NULL;
1695 struct iovec *recv_iov = NULL;
1696 bool parse_ret;
1697 NTSTATUS status;
1699 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1700 &inbuf, &recv_iov);
1701 TALLOC_FREE(subreq);
1702 data_blob_free(&state->blob_out);
1704 if (NT_STATUS_IS_OK(status)) {
1705 if (state->cli->server_domain[0] == '\0') {
1706 TALLOC_FREE(state->cli->server_domain);
1707 state->cli->server_domain = talloc_strdup(state->cli,
1708 state->ntlmssp_state->server.netbios_domain);
1709 if (state->cli->server_domain == NULL) {
1710 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1711 return;
1714 cli_set_session_key(
1715 state->cli, state->ntlmssp_state->session_key);
1717 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1718 struct smbXcli_session *session = state->cli->smb2.session;
1720 if (ntlmssp_is_anonymous(state->ntlmssp_state)) {
1722 * Windows server does not set the
1723 * SMB2_SESSION_FLAG_IS_GUEST nor
1724 * SMB2_SESSION_FLAG_IS_NULL flag.
1726 * This fix makes sure we do not try
1727 * to verify a signature on the final
1728 * session setup response.
1730 TALLOC_FREE(state->ntlmssp_state);
1731 tevent_req_done(req);
1732 return;
1735 status = smb2cli_session_set_session_key(session,
1736 state->ntlmssp_state->session_key,
1737 recv_iov);
1738 if (tevent_req_nterror(req, status)) {
1739 return;
1741 } else {
1742 if (smb1cli_conn_activate_signing(
1743 state->cli->conn, state->ntlmssp_state->session_key,
1744 data_blob_null)
1745 && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) {
1746 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1747 return;
1750 TALLOC_FREE(state->ntlmssp_state);
1751 tevent_req_done(req);
1752 return;
1754 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1755 tevent_req_nterror(req, status);
1756 return;
1759 if (blob_in.length == 0) {
1760 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1761 return;
1764 if ((state->turn == 1)
1765 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1766 DATA_BLOB tmp_blob = data_blob_null;
1767 /* the server might give us back two challenges */
1768 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1769 &tmp_blob);
1770 data_blob_free(&tmp_blob);
1771 } else {
1772 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1773 OID_NTLMSSP, &msg_in);
1775 state->turn += 1;
1777 if (!parse_ret) {
1778 DEBUG(3,("Failed to parse auth response\n"));
1779 if (NT_STATUS_IS_OK(status)
1780 || NT_STATUS_EQUAL(status,
1781 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1782 tevent_req_nterror(
1783 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1784 return;
1788 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1790 if (!NT_STATUS_IS_OK(status)
1791 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1792 TALLOC_FREE(state->ntlmssp_state);
1793 tevent_req_nterror(req, status);
1794 return;
1797 state->blob_out = spnego_gen_auth(state, blob_out);
1798 if (tevent_req_nomem(state->blob_out.data, req)) {
1799 return;
1802 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1803 state->blob_out);
1804 if (tevent_req_nomem(subreq, req)) {
1805 return;
1807 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1810 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1812 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1813 req, struct cli_session_setup_ntlmssp_state);
1814 NTSTATUS status;
1816 if (tevent_req_is_nterror(req, &status)) {
1817 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1818 return status;
1820 return NT_STATUS_OK;
1823 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1824 const char *user,
1825 const char *pass,
1826 const char *domain)
1828 struct tevent_context *ev;
1829 struct tevent_req *req;
1830 NTSTATUS status = NT_STATUS_NO_MEMORY;
1832 if (smbXcli_conn_has_async_calls(cli->conn)) {
1833 return NT_STATUS_INVALID_PARAMETER;
1835 ev = tevent_context_init(talloc_tos());
1836 if (ev == NULL) {
1837 goto fail;
1839 req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1840 if (req == NULL) {
1841 goto fail;
1843 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1844 goto fail;
1846 status = cli_session_setup_ntlmssp_recv(req);
1847 fail:
1848 TALLOC_FREE(ev);
1849 return status;
1852 /****************************************************************************
1853 Do a spnego encrypted session setup.
1855 user_domain: The shortname of the domain the user/machine is a member of.
1856 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1857 ****************************************************************************/
1859 static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
1860 const char *user,
1861 const char *pass,
1862 const char *user_domain,
1863 const char * dest_realm)
1865 char *principal = NULL;
1866 char *OIDs[ASN1_MAX_OIDS];
1867 int i;
1868 const DATA_BLOB *server_blob;
1869 DATA_BLOB blob = data_blob_null;
1870 const char *p = NULL;
1871 char *account = NULL;
1872 NTSTATUS status;
1874 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1875 if (server_blob) {
1876 blob = data_blob(server_blob->data, server_blob->length);
1879 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)blob.length));
1881 /* the server might not even do spnego */
1882 if (blob.length == 0) {
1883 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1884 goto ntlmssp;
1887 #if 0
1888 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1889 #endif
1891 /* The server sent us the first part of the SPNEGO exchange in the
1892 * negprot reply. It is WRONG to depend on the principal sent in the
1893 * negprot reply, but right now we do it. If we don't receive one,
1894 * we try to best guess, then fall back to NTLM. */
1895 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1896 OIDs[0] == NULL) {
1897 data_blob_free(&blob);
1898 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1900 data_blob_free(&blob);
1902 /* make sure the server understands kerberos */
1903 for (i=0;OIDs[i];i++) {
1904 if (i == 0)
1905 DEBUG(3,("got OID=%s\n", OIDs[i]));
1906 else
1907 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1908 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1909 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1910 cli->got_kerberos_mechanism = True;
1912 talloc_free(OIDs[i]);
1915 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1917 status = cli_set_username(cli, user);
1918 if (!NT_STATUS_IS_OK(status)) {
1919 TALLOC_FREE(principal);
1920 return ADS_ERROR_NT(status);
1923 #ifdef HAVE_KRB5
1924 /* If password is set we reauthenticate to kerberos server
1925 * and do not store results */
1927 if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
1928 ADS_STATUS rc;
1929 const char *remote_name = smbXcli_conn_remote_name(cli->conn);
1931 if (pass && *pass) {
1932 int ret;
1934 use_in_memory_ccache();
1935 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1937 if (ret){
1938 TALLOC_FREE(principal);
1939 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1940 if (cli->fallback_after_kerberos)
1941 goto ntlmssp;
1942 return ADS_ERROR_KRB5(ret);
1946 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1948 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1949 TALLOC_FREE(principal);
1952 if (principal == NULL &&
1953 !is_ipaddress(remote_name) &&
1954 !strequal(STAR_SMBSERVER,
1955 remote_name)) {
1956 DEBUG(3,("cli_session_setup_spnego: using target "
1957 "hostname not SPNEGO principal\n"));
1959 if (dest_realm) {
1960 char *realm = strupper_talloc(talloc_tos(), dest_realm);
1961 if (realm) {
1962 principal = talloc_asprintf(talloc_tos(),
1963 "cifs/%s@%s",
1964 remote_name,
1965 realm);
1966 TALLOC_FREE(realm);
1968 } else {
1969 principal = kerberos_get_principal_from_service_hostname(talloc_tos(),
1970 "cifs",
1971 remote_name,
1972 lp_realm());
1975 if (!principal) {
1976 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1978 DEBUG(3,("cli_session_setup_spnego: guessed "
1979 "server principal=%s\n",
1980 principal ? principal : "<null>"));
1983 if (principal) {
1984 rc = cli_session_setup_kerberos(cli, principal);
1985 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1986 TALLOC_FREE(principal);
1987 return rc;
1991 #endif
1993 TALLOC_FREE(principal);
1995 ntlmssp:
1997 account = talloc_strdup(talloc_tos(), user);
1998 if (!account) {
1999 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
2002 /* when falling back to ntlmssp while authenticating with a machine
2003 * account strip off the realm - gd */
2005 if ((p = strchr_m(user, '@')) != NULL) {
2006 account[PTR_DIFF(p,user)] = '\0';
2009 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
2012 /****************************************************************************
2013 Send a session setup. The username and workgroup is in UNIX character
2014 format and must be converted to DOS codepage format before sending. If the
2015 password is in plaintext, the same should be done.
2016 ****************************************************************************/
2018 NTSTATUS cli_session_setup(struct cli_state *cli,
2019 const char *user,
2020 const char *pass, int passlen,
2021 const char *ntpass, int ntpasslen,
2022 const char *workgroup)
2024 char *p;
2025 char *user2;
2026 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2028 if (user) {
2029 user2 = talloc_strdup(talloc_tos(), user);
2030 } else {
2031 user2 = talloc_strdup(talloc_tos(), "");
2033 if (user2 == NULL) {
2034 return NT_STATUS_NO_MEMORY;
2037 if (!workgroup) {
2038 workgroup = "";
2041 /* allow for workgroups as part of the username */
2042 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
2043 (p=strchr_m(user2,*lp_winbind_separator()))) {
2044 *p = 0;
2045 user = p+1;
2046 strupper_m(user2);
2047 workgroup = user2;
2050 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
2051 return NT_STATUS_OK;
2054 /* now work out what sort of session setup we are going to
2055 do. I have split this into separate functions to make the
2056 flow a bit easier to understand (tridge) */
2058 /* if its an older server then we have to use the older request format */
2060 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
2061 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2062 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2063 " or 'client ntlmv2 auth = yes'\n"));
2064 return NT_STATUS_ACCESS_DENIED;
2067 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2068 !lp_client_plaintext_auth() && (*pass)) {
2069 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2070 " or 'client ntlmv2 auth = yes'\n"));
2071 return NT_STATUS_ACCESS_DENIED;
2074 return cli_session_setup_lanman2(cli, user, pass, passlen,
2075 workgroup);
2078 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2079 const char *remote_realm = cli_state_remote_realm(cli);
2080 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2081 workgroup,
2082 remote_realm);
2083 if (!ADS_ERR_OK(status)) {
2084 DEBUG(3, ("SMB2-SPNEGO login failed: %s\n", ads_errstr(status)));
2085 return ads_ntstatus(status);
2087 return NT_STATUS_OK;
2090 /* if no user is supplied then we have to do an anonymous connection.
2091 passwords are ignored */
2093 if (!user || !*user)
2094 return cli_session_setup_guest(cli);
2096 /* if the server is share level then send a plaintext null
2097 password at this point. The password is sent in the tree
2098 connect */
2100 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
2101 return cli_session_setup_plain(cli, user, "", workgroup);
2103 /* if the server doesn't support encryption then we have to use
2104 plaintext. The second password is ignored */
2106 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2107 if (!lp_client_plaintext_auth() && (*pass)) {
2108 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2109 " or 'client ntlmv2 auth = yes'\n"));
2110 return NT_STATUS_ACCESS_DENIED;
2112 return cli_session_setup_plain(cli, user, pass, workgroup);
2115 /* if the server supports extended security then use SPNEGO */
2117 if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
2118 const char *remote_realm = cli_state_remote_realm(cli);
2119 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2120 workgroup,
2121 remote_realm);
2122 if (!ADS_ERR_OK(status)) {
2123 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2124 return ads_ntstatus(status);
2126 } else {
2127 NTSTATUS status;
2129 /* otherwise do a NT1 style session setup */
2130 status = cli_session_setup_nt1(cli, user, pass, passlen,
2131 ntpass, ntpasslen, workgroup);
2132 if (!NT_STATUS_IS_OK(status)) {
2133 DEBUG(3,("cli_session_setup: NT1 session setup "
2134 "failed: %s\n", nt_errstr(status)));
2135 return status;
2139 return NT_STATUS_OK;
2142 /****************************************************************************
2143 Send a uloggoff.
2144 *****************************************************************************/
2146 struct cli_ulogoff_state {
2147 struct cli_state *cli;
2148 uint16_t vwv[3];
2151 static void cli_ulogoff_done(struct tevent_req *subreq);
2153 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2154 struct tevent_context *ev,
2155 struct cli_state *cli)
2157 struct tevent_req *req, *subreq;
2158 struct cli_ulogoff_state *state;
2160 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2161 if (req == NULL) {
2162 return NULL;
2164 state->cli = cli;
2166 SCVAL(state->vwv+0, 0, 0xFF);
2167 SCVAL(state->vwv+1, 0, 0);
2168 SSVAL(state->vwv+2, 0, 0);
2170 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2171 0, NULL);
2172 if (tevent_req_nomem(subreq, req)) {
2173 return tevent_req_post(req, ev);
2175 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2176 return req;
2179 static void cli_ulogoff_done(struct tevent_req *subreq)
2181 struct tevent_req *req = tevent_req_callback_data(
2182 subreq, struct tevent_req);
2183 struct cli_ulogoff_state *state = tevent_req_data(
2184 req, struct cli_ulogoff_state);
2185 NTSTATUS status;
2187 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2188 if (!NT_STATUS_IS_OK(status)) {
2189 tevent_req_nterror(req, status);
2190 return;
2192 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2193 tevent_req_done(req);
2196 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2198 return tevent_req_simple_recv_ntstatus(req);
2201 NTSTATUS cli_ulogoff(struct cli_state *cli)
2203 struct tevent_context *ev;
2204 struct tevent_req *req;
2205 NTSTATUS status = NT_STATUS_NO_MEMORY;
2207 if (smbXcli_conn_has_async_calls(cli->conn)) {
2208 return NT_STATUS_INVALID_PARAMETER;
2210 ev = tevent_context_init(talloc_tos());
2211 if (ev == NULL) {
2212 goto fail;
2214 req = cli_ulogoff_send(ev, ev, cli);
2215 if (req == NULL) {
2216 goto fail;
2218 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2219 goto fail;
2221 status = cli_ulogoff_recv(req);
2222 fail:
2223 TALLOC_FREE(ev);
2224 return status;
2227 /****************************************************************************
2228 Send a tconX.
2229 ****************************************************************************/
2231 struct cli_tcon_andx_state {
2232 struct cli_state *cli;
2233 uint16_t vwv[4];
2234 struct iovec bytes;
2237 static void cli_tcon_andx_done(struct tevent_req *subreq);
2239 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2240 struct event_context *ev,
2241 struct cli_state *cli,
2242 const char *share, const char *dev,
2243 const char *pass, int passlen,
2244 struct tevent_req **psmbreq)
2246 struct tevent_req *req, *subreq;
2247 struct cli_tcon_andx_state *state;
2248 uint8_t p24[24];
2249 uint16_t *vwv;
2250 char *tmp = NULL;
2251 uint8_t *bytes;
2252 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2254 *psmbreq = NULL;
2256 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2257 if (req == NULL) {
2258 return NULL;
2260 state->cli = cli;
2261 vwv = state->vwv;
2263 cli->share = talloc_strdup(cli, share);
2264 if (!cli->share) {
2265 return NULL;
2268 /* in user level security don't send a password now */
2269 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2270 passlen = 1;
2271 pass = "";
2272 } else if (pass == NULL) {
2273 DEBUG(1, ("Server not using user level security and no "
2274 "password supplied.\n"));
2275 goto access_denied;
2278 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2279 *pass && passlen != 24) {
2280 if (!lp_client_lanman_auth()) {
2281 DEBUG(1, ("Server requested LANMAN password "
2282 "(share-level security) but "
2283 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2284 goto access_denied;
2288 * Non-encrypted passwords - convert to DOS codepage before
2289 * encryption.
2291 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2292 passlen = 24;
2293 pass = (const char *)p24;
2294 } else {
2295 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2296 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2297 == 0) {
2298 uint8_t *tmp_pass;
2300 if (!lp_client_plaintext_auth() && (*pass)) {
2301 DEBUG(1, ("Server requested PLAINTEXT "
2302 "password but "
2303 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2304 goto access_denied;
2308 * Non-encrypted passwords - convert to DOS codepage
2309 * before using.
2311 tmp_pass = talloc_array(talloc_tos(), uint8, 0);
2312 if (tevent_req_nomem(tmp_pass, req)) {
2313 return tevent_req_post(req, ev);
2315 tmp_pass = trans2_bytes_push_str(tmp_pass,
2316 false, /* always DOS */
2317 pass,
2318 passlen,
2319 NULL);
2320 if (tevent_req_nomem(tmp_pass, req)) {
2321 return tevent_req_post(req, ev);
2323 pass = (const char *)tmp_pass;
2324 passlen = talloc_get_size(tmp_pass);
2328 SCVAL(vwv+0, 0, 0xFF);
2329 SCVAL(vwv+0, 1, 0);
2330 SSVAL(vwv+1, 0, 0);
2331 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
2332 SSVAL(vwv+3, 0, passlen);
2334 if (passlen && pass) {
2335 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2336 } else {
2337 bytes = talloc_array(state, uint8_t, 0);
2341 * Add the sharename
2343 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2344 smbXcli_conn_remote_name(cli->conn), share);
2345 if (tmp == NULL) {
2346 TALLOC_FREE(req);
2347 return NULL;
2349 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2350 NULL);
2351 TALLOC_FREE(tmp);
2354 * Add the devicetype
2356 tmp = talloc_strdup_upper(talloc_tos(), dev);
2357 if (tmp == NULL) {
2358 TALLOC_FREE(req);
2359 return NULL;
2361 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2362 TALLOC_FREE(tmp);
2364 if (bytes == NULL) {
2365 TALLOC_FREE(req);
2366 return NULL;
2369 state->bytes.iov_base = (void *)bytes;
2370 state->bytes.iov_len = talloc_get_size(bytes);
2372 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2373 1, &state->bytes);
2374 if (subreq == NULL) {
2375 TALLOC_FREE(req);
2376 return NULL;
2378 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2379 *psmbreq = subreq;
2380 return req;
2382 access_denied:
2383 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2384 return tevent_req_post(req, ev);
2387 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2388 struct event_context *ev,
2389 struct cli_state *cli,
2390 const char *share, const char *dev,
2391 const char *pass, int passlen)
2393 struct tevent_req *req, *subreq;
2394 NTSTATUS status;
2396 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2397 &subreq);
2398 if (req == NULL) {
2399 return NULL;
2401 if (subreq == NULL) {
2402 return req;
2404 status = smb1cli_req_chain_submit(&subreq, 1);
2405 if (!NT_STATUS_IS_OK(status)) {
2406 tevent_req_nterror(req, status);
2407 return tevent_req_post(req, ev);
2409 return req;
2412 static void cli_tcon_andx_done(struct tevent_req *subreq)
2414 struct tevent_req *req = tevent_req_callback_data(
2415 subreq, struct tevent_req);
2416 struct cli_tcon_andx_state *state = tevent_req_data(
2417 req, struct cli_tcon_andx_state);
2418 struct cli_state *cli = state->cli;
2419 uint8_t *in;
2420 uint8_t *inhdr;
2421 uint8_t wct;
2422 uint16_t *vwv;
2423 uint32_t num_bytes;
2424 uint8_t *bytes;
2425 NTSTATUS status;
2427 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2428 &num_bytes, &bytes);
2429 TALLOC_FREE(subreq);
2430 if (!NT_STATUS_IS_OK(status)) {
2431 tevent_req_nterror(req, status);
2432 return;
2435 inhdr = in + NBT_HDR_SIZE;
2437 if (num_bytes) {
2438 if (clistr_pull_talloc(cli,
2439 (const char *)inhdr,
2440 SVAL(inhdr, HDR_FLG2),
2441 &cli->dev,
2442 bytes,
2443 num_bytes,
2444 STR_TERMINATE|STR_ASCII) == -1) {
2445 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2446 return;
2448 } else {
2449 cli->dev = talloc_strdup(cli, "");
2450 if (cli->dev == NULL) {
2451 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2452 return;
2456 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2457 /* almost certainly win95 - enable bug fixes */
2458 cli->win95 = True;
2462 * Make sure that we have the optional support 16-bit field. WCT > 2.
2463 * Avoids issues when connecting to Win9x boxes sharing files
2466 cli->dfsroot = false;
2468 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2469 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
2472 cli->smb1.tid = SVAL(inhdr, HDR_TID);
2473 tevent_req_done(req);
2476 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2478 return tevent_req_simple_recv_ntstatus(req);
2481 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2482 const char *dev, const char *pass, int passlen)
2484 TALLOC_CTX *frame = talloc_stackframe();
2485 struct event_context *ev;
2486 struct tevent_req *req;
2487 NTSTATUS status = NT_STATUS_OK;
2489 if (smbXcli_conn_has_async_calls(cli->conn)) {
2491 * Can't use sync call while an async call is in flight
2493 status = NT_STATUS_INVALID_PARAMETER;
2494 goto fail;
2497 ev = event_context_init(frame);
2498 if (ev == NULL) {
2499 status = NT_STATUS_NO_MEMORY;
2500 goto fail;
2503 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2504 if (req == NULL) {
2505 status = NT_STATUS_NO_MEMORY;
2506 goto fail;
2509 if (!tevent_req_poll(req, ev)) {
2510 status = map_nt_error_from_unix(errno);
2511 goto fail;
2514 status = cli_tcon_andx_recv(req);
2515 fail:
2516 TALLOC_FREE(frame);
2517 return status;
2520 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2521 const char *dev, const char *pass, int passlen)
2523 NTSTATUS status;
2524 uint16_t max_xmit = 0;
2525 uint16_t tid = 0;
2527 cli->share = talloc_strdup(cli, share);
2528 if (!cli->share) {
2529 return NT_STATUS_NO_MEMORY;
2532 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2533 return smb2cli_tcon(cli, share);
2536 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2537 return cli_tcon_andx(cli, share, dev, pass, passlen);
2540 status = cli_raw_tcon(cli, share, pass, dev, &max_xmit, &tid);
2541 if (!NT_STATUS_IS_OK(status)) {
2542 return status;
2544 cli->smb1.tid = tid;
2546 return NT_STATUS_OK;
2549 /****************************************************************************
2550 Send a tree disconnect.
2551 ****************************************************************************/
2553 struct cli_tdis_state {
2554 struct cli_state *cli;
2557 static void cli_tdis_done(struct tevent_req *subreq);
2559 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2560 struct tevent_context *ev,
2561 struct cli_state *cli)
2563 struct tevent_req *req, *subreq;
2564 struct cli_tdis_state *state;
2566 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2567 if (req == NULL) {
2568 return NULL;
2570 state->cli = cli;
2572 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2573 if (tevent_req_nomem(subreq, req)) {
2574 return tevent_req_post(req, ev);
2576 tevent_req_set_callback(subreq, cli_tdis_done, req);
2577 return req;
2580 static void cli_tdis_done(struct tevent_req *subreq)
2582 struct tevent_req *req = tevent_req_callback_data(
2583 subreq, struct tevent_req);
2584 struct cli_tdis_state *state = tevent_req_data(
2585 req, struct cli_tdis_state);
2586 NTSTATUS status;
2588 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2589 TALLOC_FREE(subreq);
2590 if (!NT_STATUS_IS_OK(status)) {
2591 tevent_req_nterror(req, status);
2592 return;
2594 state->cli->smb1.tid = UINT16_MAX;
2595 tevent_req_done(req);
2598 NTSTATUS cli_tdis_recv(struct tevent_req *req)
2600 return tevent_req_simple_recv_ntstatus(req);
2603 NTSTATUS cli_tdis(struct cli_state *cli)
2605 struct tevent_context *ev;
2606 struct tevent_req *req;
2607 NTSTATUS status = NT_STATUS_NO_MEMORY;
2609 if (smbXcli_conn_has_async_calls(cli->conn)) {
2610 return NT_STATUS_INVALID_PARAMETER;
2612 ev = tevent_context_init(talloc_tos());
2613 if (ev == NULL) {
2614 goto fail;
2616 req = cli_tdis_send(ev, ev, cli);
2617 if (req == NULL) {
2618 goto fail;
2620 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2621 goto fail;
2623 status = cli_tdis_recv(req);
2624 fail:
2625 TALLOC_FREE(ev);
2626 return status;
2629 static NTSTATUS cli_connect_sock(const char *host, int name_type,
2630 const struct sockaddr_storage *pss,
2631 const char *myname, uint16_t port,
2632 int sec_timeout, int *pfd, uint16_t *pport)
2634 TALLOC_CTX *frame = talloc_stackframe();
2635 const char *prog;
2636 unsigned int i, num_addrs;
2637 const char **called_names;
2638 const char **calling_names;
2639 int *called_types;
2640 NTSTATUS status;
2641 int fd;
2643 prog = getenv("LIBSMB_PROG");
2644 if (prog != NULL) {
2645 fd = sock_exec(prog);
2646 if (fd == -1) {
2647 return map_nt_error_from_unix(errno);
2649 port = 0;
2650 goto done;
2653 if ((pss == NULL) || is_zero_addr(pss)) {
2654 struct sockaddr_storage *addrs;
2655 status = resolve_name_list(talloc_tos(), host, name_type,
2656 &addrs, &num_addrs);
2657 if (!NT_STATUS_IS_OK(status)) {
2658 goto fail;
2660 pss = addrs;
2661 } else {
2662 num_addrs = 1;
2665 called_names = talloc_array(talloc_tos(), const char *, num_addrs);
2666 if (called_names == NULL) {
2667 status = NT_STATUS_NO_MEMORY;
2668 goto fail;
2670 called_types = talloc_array(talloc_tos(), int, num_addrs);
2671 if (called_types == NULL) {
2672 status = NT_STATUS_NO_MEMORY;
2673 goto fail;
2675 calling_names = talloc_array(talloc_tos(), const char *, num_addrs);
2676 if (calling_names == NULL) {
2677 status = NT_STATUS_NO_MEMORY;
2678 goto fail;
2680 for (i=0; i<num_addrs; i++) {
2681 called_names[i] = host;
2682 called_types[i] = name_type;
2683 calling_names[i] = myname;
2685 status = smbsock_any_connect(pss, called_names, called_types,
2686 calling_names, NULL, num_addrs, port,
2687 sec_timeout, &fd, NULL, &port);
2688 if (!NT_STATUS_IS_OK(status)) {
2689 goto fail;
2691 set_socket_options(fd, lp_socket_options());
2692 done:
2693 *pfd = fd;
2694 *pport = port;
2695 status = NT_STATUS_OK;
2696 fail:
2697 TALLOC_FREE(frame);
2698 return status;
2701 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2702 uint16_t port, int name_type, const char *myname,
2703 int signing_state, int flags, struct cli_state **pcli)
2705 TALLOC_CTX *frame = talloc_stackframe();
2706 struct cli_state *cli;
2707 NTSTATUS status = NT_STATUS_NO_MEMORY;
2708 int fd = -1;
2709 char *desthost;
2710 char *p;
2712 desthost = talloc_strdup(talloc_tos(), host);
2713 if (desthost == NULL) {
2714 goto fail;
2717 p = strchr(host, '#');
2718 if (p != NULL) {
2719 name_type = strtol(p+1, NULL, 16);
2720 host = talloc_strndup(talloc_tos(), host, p - host);
2721 if (host == NULL) {
2722 goto fail;
2726 status = cli_connect_sock(host, name_type, dest_ss, myname, port,
2727 20, &fd, &port);
2728 if (!NT_STATUS_IS_OK(status)) {
2729 goto fail;
2732 cli = cli_state_create(NULL, fd, desthost, NULL, signing_state, flags);
2733 if (cli == NULL) {
2734 close(fd);
2735 fd = -1;
2736 goto fail;
2739 *pcli = cli;
2740 status = NT_STATUS_OK;
2741 fail:
2742 TALLOC_FREE(frame);
2743 return status;
2747 establishes a connection to after the negprot.
2748 @param output_cli A fully initialised cli structure, non-null only on success
2749 @param dest_host The netbios name of the remote host
2750 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2751 @param port (optional) The destination port (0 for default)
2753 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2754 const char *my_name,
2755 const char *dest_host,
2756 const struct sockaddr_storage *dest_ss, int port,
2757 int signing_state, int flags)
2759 NTSTATUS nt_status;
2760 struct cli_state *cli;
2762 nt_status = cli_connect_nb(dest_host, dest_ss, port, 0x20, my_name,
2763 signing_state, flags, &cli);
2764 if (!NT_STATUS_IS_OK(nt_status)) {
2765 DEBUG(10, ("cli_connect_nb failed: %s\n",
2766 nt_errstr(nt_status)));
2767 return nt_status;
2770 nt_status = smbXcli_negprot(cli->conn, cli->timeout, PROTOCOL_CORE,
2771 PROTOCOL_NT1);
2772 if (!NT_STATUS_IS_OK(nt_status)) {
2773 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2774 cli_shutdown(cli);
2775 return nt_status;
2778 *output_cli = cli;
2779 return NT_STATUS_OK;
2784 establishes a connection right up to doing tconX, password specified.
2785 @param output_cli A fully initialised cli structure, non-null only on success
2786 @param dest_host The netbios name of the remote host
2787 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2788 @param port (optional) The destination port (0 for default)
2789 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2790 @param service_type The 'type' of serivice.
2791 @param user Username, unix string
2792 @param domain User's domain
2793 @param password User's password, unencrypted unix string.
2796 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2797 const char *my_name,
2798 const char *dest_host,
2799 const struct sockaddr_storage *dest_ss, int port,
2800 const char *service, const char *service_type,
2801 const char *user, const char *domain,
2802 const char *password, int flags,
2803 int signing_state)
2805 NTSTATUS nt_status;
2806 struct cli_state *cli = NULL;
2807 int pw_len = password ? strlen(password)+1 : 0;
2809 *output_cli = NULL;
2811 if (password == NULL) {
2812 password = "";
2815 nt_status = cli_start_connection(&cli, my_name, dest_host,
2816 dest_ss, port, signing_state,
2817 flags);
2819 if (!NT_STATUS_IS_OK(nt_status)) {
2820 return nt_status;
2823 nt_status = cli_session_setup(cli, user, password, pw_len, password,
2824 pw_len, domain);
2825 if (!NT_STATUS_IS_OK(nt_status)) {
2827 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2828 DEBUG(1,("failed session setup with %s\n",
2829 nt_errstr(nt_status)));
2830 cli_shutdown(cli);
2831 return nt_status;
2834 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2835 if (!NT_STATUS_IS_OK(nt_status)) {
2836 DEBUG(1,("anonymous failed session setup with %s\n",
2837 nt_errstr(nt_status)));
2838 cli_shutdown(cli);
2839 return nt_status;
2843 if (service) {
2844 nt_status = cli_tree_connect(cli, service, service_type,
2845 password, pw_len);
2846 if (!NT_STATUS_IS_OK(nt_status)) {
2847 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2848 cli_shutdown(cli);
2849 if (NT_STATUS_IS_OK(nt_status)) {
2850 nt_status = NT_STATUS_UNSUCCESSFUL;
2852 return nt_status;
2856 nt_status = cli_init_creds(cli, user, domain, password);
2857 if (!NT_STATUS_IS_OK(nt_status)) {
2858 cli_shutdown(cli);
2859 return nt_status;
2862 *output_cli = cli;
2863 return NT_STATUS_OK;
2866 /****************************************************************************
2867 Send an old style tcon.
2868 ****************************************************************************/
2869 NTSTATUS cli_raw_tcon(struct cli_state *cli,
2870 const char *service, const char *pass, const char *dev,
2871 uint16 *max_xmit, uint16 *tid)
2873 struct tevent_req *req;
2874 uint16_t *ret_vwv;
2875 uint8_t *bytes;
2876 NTSTATUS status;
2878 if (!lp_client_plaintext_auth() && (*pass)) {
2879 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2880 " or 'client ntlmv2 auth = yes'\n"));
2881 return NT_STATUS_ACCESS_DENIED;
2884 bytes = talloc_array(talloc_tos(), uint8_t, 0);
2885 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
2886 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
2887 service, strlen(service)+1, NULL);
2888 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
2889 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
2890 pass, strlen(pass)+1, NULL);
2891 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
2892 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
2893 dev, strlen(dev)+1, NULL);
2895 status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
2896 talloc_get_size(bytes), bytes, &req,
2897 2, NULL, &ret_vwv, NULL, NULL);
2898 if (!NT_STATUS_IS_OK(status)) {
2899 return status;
2902 *max_xmit = SVAL(ret_vwv + 0, 0);
2903 *tid = SVAL(ret_vwv + 1, 0);
2905 return NT_STATUS_OK;
2908 /* Return a cli_state pointing at the IPC$ share for the given server */
2910 struct cli_state *get_ipc_connect(char *server,
2911 struct sockaddr_storage *server_ss,
2912 const struct user_auth_info *user_info)
2914 struct cli_state *cli;
2915 NTSTATUS nt_status;
2916 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2918 if (user_info->use_kerberos) {
2919 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2922 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
2923 user_info->username ? user_info->username : "",
2924 lp_workgroup(),
2925 user_info->password ? user_info->password : "",
2926 flags,
2927 SMB_SIGNING_DEFAULT);
2929 if (NT_STATUS_IS_OK(nt_status)) {
2930 return cli;
2931 } else if (is_ipaddress(server)) {
2932 /* windows 9* needs a correct NMB name for connections */
2933 fstring remote_name;
2935 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2936 cli = get_ipc_connect(remote_name, server_ss, user_info);
2937 if (cli)
2938 return cli;
2941 return NULL;
2945 * Given the IP address of a master browser on the network, return its
2946 * workgroup and connect to it.
2948 * This function is provided to allow additional processing beyond what
2949 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2950 * browsers and obtain each master browsers' list of domains (in case the
2951 * first master browser is recently on the network and has not yet
2952 * synchronized with other master browsers and therefore does not yet have the
2953 * entire network browse list)
2956 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2957 struct sockaddr_storage *mb_ip,
2958 const struct user_auth_info *user_info,
2959 char **pp_workgroup_out)
2961 char addr[INET6_ADDRSTRLEN];
2962 fstring name;
2963 struct cli_state *cli;
2964 struct sockaddr_storage server_ss;
2966 *pp_workgroup_out = NULL;
2968 print_sockaddr(addr, sizeof(addr), mb_ip);
2969 DEBUG(99, ("Looking up name of master browser %s\n",
2970 addr));
2973 * Do a name status query to find out the name of the master browser.
2974 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2975 * master browser will not respond to a wildcard query (or, at least,
2976 * an NT4 server acting as the domain master browser will not).
2978 * We might be able to use ONLY the query on MSBROWSE, but that's not
2979 * yet been tested with all Windows versions, so until it is, leave
2980 * the original wildcard query as the first choice and fall back to
2981 * MSBROWSE if the wildcard query fails.
2983 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
2984 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
2986 DEBUG(99, ("Could not retrieve name status for %s\n",
2987 addr));
2988 return NULL;
2991 if (!find_master_ip(name, &server_ss)) {
2992 DEBUG(99, ("Could not find master ip for %s\n", name));
2993 return NULL;
2996 *pp_workgroup_out = talloc_strdup(ctx, name);
2998 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3000 print_sockaddr(addr, sizeof(addr), &server_ss);
3001 cli = get_ipc_connect(addr, &server_ss, user_info);
3003 return cli;
3007 * Return the IP address and workgroup of a master browser on the network, and
3008 * connect to it.
3011 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3012 const struct user_auth_info *user_info,
3013 char **pp_workgroup_out)
3015 struct sockaddr_storage *ip_list;
3016 struct cli_state *cli;
3017 int i, count;
3018 NTSTATUS status;
3020 *pp_workgroup_out = NULL;
3022 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3024 /* Go looking for workgroups by broadcasting on the local network */
3026 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3027 &ip_list, &count);
3028 if (!NT_STATUS_IS_OK(status)) {
3029 DEBUG(99, ("No master browsers responded: %s\n",
3030 nt_errstr(status)));
3031 return NULL;
3034 for (i = 0; i < count; i++) {
3035 char addr[INET6_ADDRSTRLEN];
3036 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3037 DEBUG(99, ("Found master browser %s\n", addr));
3039 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3040 user_info, pp_workgroup_out);
3041 if (cli)
3042 return(cli);
3045 return NULL;