source: vendor/current/source3/libsmb/cliconnect.c

Last change on this file was 989, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.7

File size: 98.9 KB
Line 
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
8
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.
13
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.
18
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/>.
21*/
22
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/credentials/credentials.h"
30#include "auth/gensec/gensec.h"
31#include "auth/ntlmssp/ntlmssp.h"
32#include "auth_generic.h"
33#include "libads/kerberos_proto.h"
34#include "krb5_env.h"
35#include "../lib/util/tevent_ntstatus.h"
36#include "async_smb.h"
37#include "libsmb/nmblib.h"
38#include "librpc/ndr/libndr.h"
39#include "../libcli/smb/smbXcli_base.h"
40
41#define STAR_SMBSERVER "*SMBSERVER"
42
43/********************************************************
44 Utility function to ensure we always return at least
45 a valid char * pointer to an empty string for the
46 cli->server_os, cli->server_type and cli->server_domain
47 strings.
48*******************************************************/
49
50static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
51 const uint8_t *hdr,
52 char **dest,
53 uint8_t *src,
54 size_t srclen,
55 ssize_t *destlen)
56{
57 *destlen = clistr_pull_talloc(mem_ctx,
58 (const char *)hdr,
59 SVAL(hdr, HDR_FLG2),
60 dest,
61 (char *)src,
62 srclen,
63 STR_TERMINATE);
64 if (*destlen == -1) {
65 return NT_STATUS_NO_MEMORY;
66 }
67
68 if (*dest == NULL) {
69 *dest = talloc_strdup(mem_ctx, "");
70 if (*dest == NULL) {
71 return NT_STATUS_NO_MEMORY;
72 }
73 }
74 return NT_STATUS_OK;
75}
76
77/****************************************************************************
78 Do an old lanman2 style session setup.
79****************************************************************************/
80
81struct cli_session_setup_lanman2_state {
82 struct cli_state *cli;
83 uint16_t vwv[10];
84 const char *user;
85};
86
87static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
88
89static struct tevent_req *cli_session_setup_lanman2_send(
90 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
91 struct cli_state *cli, const char *user,
92 const char *pass, size_t passlen,
93 const char *workgroup)
94{
95 struct tevent_req *req, *subreq;
96 struct cli_session_setup_lanman2_state *state;
97 DATA_BLOB lm_response = data_blob_null;
98 uint16_t *vwv;
99 uint8_t *bytes;
100 char *tmp;
101 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
102
103 req = tevent_req_create(mem_ctx, &state,
104 struct cli_session_setup_lanman2_state);
105 if (req == NULL) {
106 return NULL;
107 }
108 state->cli = cli;
109 state->user = user;
110 vwv = state->vwv;
111
112 /*
113 * if in share level security then don't send a password now
114 */
115 if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
116 passlen = 0;
117 }
118
119 if (passlen > 0
120 && (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
121 && passlen != 24) {
122 /*
123 * Encrypted mode needed, and non encrypted password
124 * supplied.
125 */
126 lm_response = data_blob(NULL, 24);
127 if (tevent_req_nomem(lm_response.data, req)) {
128 return tevent_req_post(req, ev);
129 }
130
131 if (!SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
132 (uint8_t *)lm_response.data)) {
133 DEBUG(1, ("Password is > 14 chars in length, and is "
134 "therefore incompatible with Lanman "
135 "authentication\n"));
136 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
137 return tevent_req_post(req, ev);
138 }
139 } else if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
140 && passlen == 24) {
141 /*
142 * Encrypted mode needed, and encrypted password
143 * supplied.
144 */
145 lm_response = data_blob(pass, passlen);
146 if (tevent_req_nomem(lm_response.data, req)) {
147 return tevent_req_post(req, ev);
148 }
149 } else if (passlen > 0) {
150 uint8_t *buf;
151 size_t converted_size;
152 /*
153 * Plaintext mode needed, assume plaintext supplied.
154 */
155 buf = talloc_array(talloc_tos(), uint8_t, 0);
156 buf = smb_bytes_push_str(buf, smbXcli_conn_use_unicode(cli->conn), pass, passlen+1,
157 &converted_size);
158 if (tevent_req_nomem(buf, req)) {
159 return tevent_req_post(req, ev);
160 }
161 lm_response = data_blob(pass, passlen);
162 TALLOC_FREE(buf);
163 if (tevent_req_nomem(lm_response.data, req)) {
164 return tevent_req_post(req, ev);
165 }
166 }
167
168 SCVAL(vwv+0, 0, 0xff);
169 SCVAL(vwv+0, 1, 0);
170 SSVAL(vwv+1, 0, 0);
171 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
172 SSVAL(vwv+3, 0, 2);
173 SSVAL(vwv+4, 0, 1);
174 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
175 SSVAL(vwv+7, 0, lm_response.length);
176
177 bytes = talloc_array(state, uint8_t, lm_response.length);
178 if (tevent_req_nomem(bytes, req)) {
179 return tevent_req_post(req, ev);
180 }
181 if (lm_response.length != 0) {
182 memcpy(bytes, lm_response.data, lm_response.length);
183 }
184 data_blob_free(&lm_response);
185
186 tmp = talloc_strdup_upper(talloc_tos(), user);
187 if (tevent_req_nomem(tmp, req)) {
188 return tevent_req_post(req, ev);
189 }
190 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
191 NULL);
192 TALLOC_FREE(tmp);
193
194 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
195 if (tevent_req_nomem(tmp, req)) {
196 return tevent_req_post(req, ev);
197 }
198 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
199 NULL);
200 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
201 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
202
203 if (tevent_req_nomem(bytes, req)) {
204 return tevent_req_post(req, ev);
205 }
206
207 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
208 talloc_get_size(bytes), bytes);
209 if (tevent_req_nomem(subreq, req)) {
210 return tevent_req_post(req, ev);
211 }
212 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
213 return req;
214}
215
216static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
217{
218 struct tevent_req *req = tevent_req_callback_data(
219 subreq, struct tevent_req);
220 struct cli_session_setup_lanman2_state *state = tevent_req_data(
221 req, struct cli_session_setup_lanman2_state);
222 struct cli_state *cli = state->cli;
223 uint32_t num_bytes;
224 uint8_t *in;
225 uint8_t *inhdr;
226 uint8_t *bytes;
227 uint8_t *p;
228 NTSTATUS status;
229 ssize_t ret;
230 uint8_t wct;
231 uint16_t *vwv;
232
233 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
234 &num_bytes, &bytes);
235 TALLOC_FREE(subreq);
236 if (!NT_STATUS_IS_OK(status)) {
237 tevent_req_nterror(req, status);
238 return;
239 }
240
241 inhdr = in + NBT_HDR_SIZE;
242 p = bytes;
243
244 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
245 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
246
247 status = smb_bytes_talloc_string(cli,
248 inhdr,
249 &cli->server_os,
250 p,
251 bytes+num_bytes-p,
252 &ret);
253
254 if (!NT_STATUS_IS_OK(status)) {
255 tevent_req_nterror(req, status);
256 return;
257 }
258 p += ret;
259
260 status = smb_bytes_talloc_string(cli,
261 inhdr,
262 &cli->server_type,
263 p,
264 bytes+num_bytes-p,
265 &ret);
266
267 if (!NT_STATUS_IS_OK(status)) {
268 tevent_req_nterror(req, status);
269 return;
270 }
271 p += ret;
272
273 status = smb_bytes_talloc_string(cli,
274 inhdr,
275 &cli->server_domain,
276 p,
277 bytes+num_bytes-p,
278 &ret);
279
280 if (!NT_STATUS_IS_OK(status)) {
281 tevent_req_nterror(req, status);
282 return;
283 }
284 p += ret;
285
286 tevent_req_done(req);
287}
288
289static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
290{
291 return tevent_req_simple_recv_ntstatus(req);
292}
293
294/****************************************************************************
295 Work out suitable capabilities to offer the server.
296****************************************************************************/
297
298static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
299 uint32_t sesssetup_capabilities)
300{
301 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
302
303 /*
304 * We only send capabilities based on the mask for:
305 * - client only flags
306 * - flags used in both directions
307 *
308 * We do not echo the server only flags, except some legacy flags.
309 *
310 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
311 * CAP_LARGE_WRITEX in order to allow us to do large reads
312 * against old Samba releases (<= 3.6.x).
313 */
314 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
315
316 /*
317 * Session Setup specific flags CAP_DYNAMIC_REAUTH
318 * and CAP_EXTENDED_SECURITY are passed by the caller.
319 * We need that in order to do guest logins even if
320 * CAP_EXTENDED_SECURITY is negotiated.
321 */
322 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
323 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
324 client_capabilities |= sesssetup_capabilities;
325
326 return client_capabilities;
327}
328
329/****************************************************************************
330 Do a NT1 guest session setup.
331****************************************************************************/
332
333struct cli_session_setup_guest_state {
334 struct cli_state *cli;
335 uint16_t vwv[13];
336 struct iovec bytes;
337};
338
339static void cli_session_setup_guest_done(struct tevent_req *subreq);
340
341struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
342 struct tevent_context *ev,
343 struct cli_state *cli,
344 struct tevent_req **psmbreq)
345{
346 struct tevent_req *req, *subreq;
347 struct cli_session_setup_guest_state *state;
348 uint16_t *vwv;
349 uint8_t *bytes;
350
351 req = tevent_req_create(mem_ctx, &state,
352 struct cli_session_setup_guest_state);
353 if (req == NULL) {
354 return NULL;
355 }
356 state->cli = cli;
357 vwv = state->vwv;
358
359 SCVAL(vwv+0, 0, 0xFF);
360 SCVAL(vwv+0, 1, 0);
361 SSVAL(vwv+1, 0, 0);
362 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
363 SSVAL(vwv+3, 0, 2);
364 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
365 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
366 SSVAL(vwv+7, 0, 0);
367 SSVAL(vwv+8, 0, 0);
368 SSVAL(vwv+9, 0, 0);
369 SSVAL(vwv+10, 0, 0);
370 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
371
372 bytes = talloc_array(state, uint8_t, 0);
373
374 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
375 NULL);
376 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
377 NULL);
378 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
379 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
380
381 if (bytes == NULL) {
382 TALLOC_FREE(req);
383 return NULL;
384 }
385
386 state->bytes.iov_base = (void *)bytes;
387 state->bytes.iov_len = talloc_get_size(bytes);
388
389 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
390 1, &state->bytes);
391 if (subreq == NULL) {
392 TALLOC_FREE(req);
393 return NULL;
394 }
395 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
396 *psmbreq = subreq;
397 return req;
398}
399
400struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
401 struct tevent_context *ev,
402 struct cli_state *cli)
403{
404 struct tevent_req *req, *subreq;
405 NTSTATUS status;
406
407 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
408 if (req == NULL) {
409 return NULL;
410 }
411
412 status = smb1cli_req_chain_submit(&subreq, 1);
413 if (!NT_STATUS_IS_OK(status)) {
414 tevent_req_nterror(req, status);
415 return tevent_req_post(req, ev);
416 }
417 return req;
418}
419
420static void cli_session_setup_guest_done(struct tevent_req *subreq)
421{
422 struct tevent_req *req = tevent_req_callback_data(
423 subreq, struct tevent_req);
424 struct cli_session_setup_guest_state *state = tevent_req_data(
425 req, struct cli_session_setup_guest_state);
426 struct cli_state *cli = state->cli;
427 uint32_t num_bytes;
428 uint8_t *in;
429 uint8_t *inhdr;
430 uint8_t *bytes;
431 uint8_t *p;
432 NTSTATUS status;
433 ssize_t ret;
434 uint8_t wct;
435 uint16_t *vwv;
436
437 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
438 &num_bytes, &bytes);
439 TALLOC_FREE(subreq);
440 if (!NT_STATUS_IS_OK(status)) {
441 tevent_req_nterror(req, status);
442 return;
443 }
444
445 inhdr = in + NBT_HDR_SIZE;
446 p = bytes;
447
448 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
449 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
450
451 status = smb_bytes_talloc_string(cli,
452 inhdr,
453 &cli->server_os,
454 p,
455 bytes+num_bytes-p,
456 &ret);
457
458 if (!NT_STATUS_IS_OK(status)) {
459 tevent_req_nterror(req, status);
460 return;
461 }
462 p += ret;
463
464 status = smb_bytes_talloc_string(cli,
465 inhdr,
466 &cli->server_type,
467 p,
468 bytes+num_bytes-p,
469 &ret);
470
471 if (!NT_STATUS_IS_OK(status)) {
472 tevent_req_nterror(req, status);
473 return;
474 }
475 p += ret;
476
477 status = smb_bytes_talloc_string(cli,
478 inhdr,
479 &cli->server_domain,
480 p,
481 bytes+num_bytes-p,
482 &ret);
483
484 if (!NT_STATUS_IS_OK(status)) {
485 tevent_req_nterror(req, status);
486 return;
487 }
488 p += ret;
489
490 tevent_req_done(req);
491}
492
493NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
494{
495 return tevent_req_simple_recv_ntstatus(req);
496}
497
498/****************************************************************************
499 Do a NT1 plaintext session setup.
500****************************************************************************/
501
502struct cli_session_setup_plain_state {
503 struct cli_state *cli;
504 uint16_t vwv[13];
505 const char *user;
506};
507
508static void cli_session_setup_plain_done(struct tevent_req *subreq);
509
510static struct tevent_req *cli_session_setup_plain_send(
511 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
512 struct cli_state *cli,
513 const char *user, const char *pass, const char *workgroup)
514{
515 struct tevent_req *req, *subreq;
516 struct cli_session_setup_plain_state *state;
517 uint16_t *vwv;
518 uint8_t *bytes;
519 size_t passlen;
520 char *version;
521
522 req = tevent_req_create(mem_ctx, &state,
523 struct cli_session_setup_plain_state);
524 if (req == NULL) {
525 return NULL;
526 }
527 state->cli = cli;
528 state->user = user;
529 vwv = state->vwv;
530
531 SCVAL(vwv+0, 0, 0xff);
532 SCVAL(vwv+0, 1, 0);
533 SSVAL(vwv+1, 0, 0);
534 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
535 SSVAL(vwv+3, 0, 2);
536 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
537 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
538 SSVAL(vwv+7, 0, 0);
539 SSVAL(vwv+8, 0, 0);
540 SSVAL(vwv+9, 0, 0);
541 SSVAL(vwv+10, 0, 0);
542 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
543
544 bytes = talloc_array(state, uint8_t, 0);
545 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), pass, strlen(pass)+1,
546 &passlen);
547 if (tevent_req_nomem(bytes, req)) {
548 return tevent_req_post(req, ev);
549 }
550 SSVAL(vwv + (smbXcli_conn_use_unicode(cli->conn) ? 8 : 7), 0, passlen);
551
552 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
553 user, strlen(user)+1, NULL);
554 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
555 workgroup, strlen(workgroup)+1, NULL);
556 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
557 "Unix", 5, NULL);
558
559 version = talloc_asprintf(talloc_tos(), "Samba %s",
560 samba_version_string());
561 if (tevent_req_nomem(version, req)){
562 return tevent_req_post(req, ev);
563 }
564 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
565 version, strlen(version)+1, NULL);
566 TALLOC_FREE(version);
567
568 if (tevent_req_nomem(bytes, req)) {
569 return tevent_req_post(req, ev);
570 }
571
572 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
573 talloc_get_size(bytes), bytes);
574 if (tevent_req_nomem(subreq, req)) {
575 return tevent_req_post(req, ev);
576 }
577 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
578 return req;
579}
580
581static void cli_session_setup_plain_done(struct tevent_req *subreq)
582{
583 struct tevent_req *req = tevent_req_callback_data(
584 subreq, struct tevent_req);
585 struct cli_session_setup_plain_state *state = tevent_req_data(
586 req, struct cli_session_setup_plain_state);
587 struct cli_state *cli = state->cli;
588 uint32_t num_bytes;
589 uint8_t *in;
590 uint8_t *inhdr;
591 uint8_t *bytes;
592 uint8_t *p;
593 NTSTATUS status;
594 ssize_t ret;
595 uint8_t wct;
596 uint16_t *vwv;
597
598 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
599 &num_bytes, &bytes);
600 TALLOC_FREE(subreq);
601 if (tevent_req_nterror(req, status)) {
602 return;
603 }
604
605 inhdr = in + NBT_HDR_SIZE;
606 p = bytes;
607
608 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
609 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
610
611 status = smb_bytes_talloc_string(cli,
612 inhdr,
613 &cli->server_os,
614 p,
615 bytes+num_bytes-p,
616 &ret);
617
618 if (!NT_STATUS_IS_OK(status)) {
619 tevent_req_nterror(req, status);
620 return;
621 }
622 p += ret;
623
624 status = smb_bytes_talloc_string(cli,
625 inhdr,
626 &cli->server_type,
627 p,
628 bytes+num_bytes-p,
629 &ret);
630
631 if (!NT_STATUS_IS_OK(status)) {
632 tevent_req_nterror(req, status);
633 return;
634 }
635 p += ret;
636
637 status = smb_bytes_talloc_string(cli,
638 inhdr,
639 &cli->server_domain,
640 p,
641 bytes+num_bytes-p,
642 &ret);
643
644 if (!NT_STATUS_IS_OK(status)) {
645 tevent_req_nterror(req, status);
646 return;
647 }
648 p += ret;
649
650 tevent_req_done(req);
651}
652
653static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
654{
655 return tevent_req_simple_recv_ntstatus(req);
656}
657
658/****************************************************************************
659 do a NT1 NTLM/LM encrypted session setup - for when extended security
660 is not negotiated.
661 @param cli client state to create do session setup on
662 @param user username
663 @param pass *either* cleartext password (passlen !=24) or LM response.
664 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
665 @param workgroup The user's domain.
666****************************************************************************/
667
668struct cli_session_setup_nt1_state {
669 struct cli_state *cli;
670 uint16_t vwv[13];
671 DATA_BLOB response;
672 DATA_BLOB session_key;
673 const char *user;
674};
675
676static void cli_session_setup_nt1_done(struct tevent_req *subreq);
677
678static struct tevent_req *cli_session_setup_nt1_send(
679 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
680 struct cli_state *cli, const char *user,
681 const char *pass, size_t passlen,
682 const char *ntpass, size_t ntpasslen,
683 const char *workgroup)
684{
685 struct tevent_req *req, *subreq;
686 struct cli_session_setup_nt1_state *state;
687 DATA_BLOB lm_response = data_blob_null;
688 DATA_BLOB nt_response = data_blob_null;
689 DATA_BLOB session_key = data_blob_null;
690 uint16_t *vwv;
691 uint8_t *bytes;
692 char *workgroup_upper;
693
694 req = tevent_req_create(mem_ctx, &state,
695 struct cli_session_setup_nt1_state);
696 if (req == NULL) {
697 return NULL;
698 }
699 state->cli = cli;
700 state->user = user;
701 vwv = state->vwv;
702
703 if (passlen == 0) {
704 /* do nothing - guest login */
705 } else if (passlen != 24) {
706 if (lp_client_ntlmv2_auth()) {
707 DATA_BLOB server_chal;
708 DATA_BLOB names_blob;
709
710 server_chal =
711 data_blob_const(smb1cli_conn_server_challenge(cli->conn),
712 8);
713
714 /*
715 * note that the 'workgroup' here is a best
716 * guess - we don't know the server's domain
717 * at this point. Windows clients also don't
718 * use hostname...
719 */
720 names_blob = NTLMv2_generate_names_blob(
721 NULL, NULL, workgroup);
722
723 if (tevent_req_nomem(names_blob.data, req)) {
724 return tevent_req_post(req, ev);
725 }
726
727 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
728 &server_chal, &names_blob,
729 &lm_response, &nt_response,
730 NULL, &session_key)) {
731 data_blob_free(&names_blob);
732 tevent_req_nterror(
733 req, NT_STATUS_ACCESS_DENIED);
734 return tevent_req_post(req, ev);
735 }
736 data_blob_free(&names_blob);
737
738 } else {
739 uchar nt_hash[16];
740 E_md4hash(pass, nt_hash);
741
742#ifdef LANMAN_ONLY
743 nt_response = data_blob_null;
744#else
745 nt_response = data_blob(NULL, 24);
746 if (tevent_req_nomem(nt_response.data, req)) {
747 return tevent_req_post(req, ev);
748 }
749
750 SMBNTencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
751 nt_response.data);
752#endif
753 /* non encrypted password supplied. Ignore ntpass. */
754 if (lp_client_lanman_auth()) {
755
756 lm_response = data_blob(NULL, 24);
757 if (tevent_req_nomem(lm_response.data, req)) {
758 return tevent_req_post(req, ev);
759 }
760
761 if (!SMBencrypt(pass,
762 smb1cli_conn_server_challenge(cli->conn),
763 lm_response.data)) {
764 /*
765 * Oops, the LM response is
766 * invalid, just put the NT
767 * response there instead
768 */
769 data_blob_free(&lm_response);
770 lm_response = data_blob(
771 nt_response.data,
772 nt_response.length);
773 }
774 } else {
775 /*
776 * LM disabled, place NT# in LM field
777 * instead
778 */
779 lm_response = data_blob(
780 nt_response.data, nt_response.length);
781 }
782
783 if (tevent_req_nomem(lm_response.data, req)) {
784 return tevent_req_post(req, ev);
785 }
786
787 session_key = data_blob(NULL, 16);
788 if (tevent_req_nomem(session_key.data, req)) {
789 return tevent_req_post(req, ev);
790 }
791#ifdef LANMAN_ONLY
792 E_deshash(pass, session_key.data);
793 memset(&session_key.data[8], '\0', 8);
794#else
795 SMBsesskeygen_ntv1(nt_hash, session_key.data);
796#endif
797 }
798 } else {
799 /* pre-encrypted password supplied. Only used for
800 security=server, can't do
801 signing because we don't have original key */
802
803 lm_response = data_blob(pass, passlen);
804 if (tevent_req_nomem(lm_response.data, req)) {
805 return tevent_req_post(req, ev);
806 }
807
808 nt_response = data_blob(ntpass, ntpasslen);
809 if (tevent_req_nomem(nt_response.data, req)) {
810 return tevent_req_post(req, ev);
811 }
812 }
813
814#ifdef LANMAN_ONLY
815 state->response = data_blob_talloc(
816 state, lm_response.data, lm_response.length);
817#else
818 state->response = data_blob_talloc(
819 state, nt_response.data, nt_response.length);
820#endif
821 if (tevent_req_nomem(state->response.data, req)) {
822 return tevent_req_post(req, ev);
823 }
824
825 if (session_key.data) {
826 state->session_key = data_blob_talloc(
827 state, session_key.data, session_key.length);
828 if (tevent_req_nomem(state->session_key.data, req)) {
829 return tevent_req_post(req, ev);
830 }
831 }
832 data_blob_free(&session_key);
833
834 SCVAL(vwv+0, 0, 0xff);
835 SCVAL(vwv+0, 1, 0);
836 SSVAL(vwv+1, 0, 0);
837 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
838 SSVAL(vwv+3, 0, 2);
839 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
840 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
841 SSVAL(vwv+7, 0, lm_response.length);
842 SSVAL(vwv+8, 0, nt_response.length);
843 SSVAL(vwv+9, 0, 0);
844 SSVAL(vwv+10, 0, 0);
845 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
846
847 bytes = talloc_array(state, uint8_t,
848 lm_response.length + nt_response.length);
849 if (tevent_req_nomem(bytes, req)) {
850 return tevent_req_post(req, ev);
851 }
852 if (lm_response.length != 0) {
853 memcpy(bytes, lm_response.data, lm_response.length);
854 }
855 if (nt_response.length != 0) {
856 memcpy(bytes + lm_response.length,
857 nt_response.data, nt_response.length);
858 }
859 data_blob_free(&lm_response);
860 data_blob_free(&nt_response);
861
862 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
863 user, strlen(user)+1, NULL);
864
865 /*
866 * Upper case here might help some NTLMv2 implementations
867 */
868 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
869 if (tevent_req_nomem(workgroup_upper, req)) {
870 return tevent_req_post(req, ev);
871 }
872 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
873 workgroup_upper, strlen(workgroup_upper)+1,
874 NULL);
875 TALLOC_FREE(workgroup_upper);
876
877 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
878 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
879 if (tevent_req_nomem(bytes, req)) {
880 return tevent_req_post(req, ev);
881 }
882
883 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
884 talloc_get_size(bytes), bytes);
885 if (tevent_req_nomem(subreq, req)) {
886 return tevent_req_post(req, ev);
887 }
888 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
889 return req;
890}
891
892static void cli_session_setup_nt1_done(struct tevent_req *subreq)
893{
894 struct tevent_req *req = tevent_req_callback_data(
895 subreq, struct tevent_req);
896 struct cli_session_setup_nt1_state *state = tevent_req_data(
897 req, struct cli_session_setup_nt1_state);
898 struct cli_state *cli = state->cli;
899 uint32_t num_bytes;
900 uint8_t *in;
901 uint8_t *inhdr;
902 uint8_t *bytes;
903 uint8_t *p;
904 NTSTATUS status;
905 ssize_t ret;
906 uint8_t wct;
907 uint16_t *vwv;
908
909 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
910 &num_bytes, &bytes);
911 TALLOC_FREE(subreq);
912 if (!NT_STATUS_IS_OK(status)) {
913 tevent_req_nterror(req, status);
914 return;
915 }
916
917 inhdr = in + NBT_HDR_SIZE;
918 p = bytes;
919
920 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
921 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
922
923 status = smb_bytes_talloc_string(cli,
924 inhdr,
925 &cli->server_os,
926 p,
927 bytes+num_bytes-p,
928 &ret);
929 if (!NT_STATUS_IS_OK(status)) {
930 tevent_req_nterror(req, status);
931 return;
932 }
933 p += ret;
934
935 status = smb_bytes_talloc_string(cli,
936 inhdr,
937 &cli->server_type,
938 p,
939 bytes+num_bytes-p,
940 &ret);
941 if (!NT_STATUS_IS_OK(status)) {
942 tevent_req_nterror(req, status);
943 return;
944 }
945 p += ret;
946
947 status = smb_bytes_talloc_string(cli,
948 inhdr,
949 &cli->server_domain,
950 p,
951 bytes+num_bytes-p,
952 &ret);
953 if (!NT_STATUS_IS_OK(status)) {
954 tevent_req_nterror(req, status);
955 return;
956 }
957 p += ret;
958
959 if (smb1cli_conn_activate_signing(cli->conn, state->session_key, state->response)
960 && !smb1cli_conn_check_signing(cli->conn, (uint8_t *)in, 1)) {
961 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
962 return;
963 }
964 if (state->session_key.data) {
965 struct smbXcli_session *session = state->cli->smb1.session;
966
967 status = smb1cli_session_set_session_key(session,
968 state->session_key);
969 if (tevent_req_nterror(req, status)) {
970 return;
971 }
972 }
973 tevent_req_done(req);
974}
975
976static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
977{
978 return tevent_req_simple_recv_ntstatus(req);
979}
980
981/* The following is calculated from :
982 * (smb_size-4) = 35
983 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
984 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
985 * end of packet.
986 */
987
988#define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
989
990struct cli_sesssetup_blob_state {
991 struct tevent_context *ev;
992 struct cli_state *cli;
993 DATA_BLOB blob;
994 uint16_t max_blob_size;
995 uint16_t vwv[12];
996 uint8_t *buf;
997
998 DATA_BLOB smb2_blob;
999 struct iovec *recv_iov;
1000
1001 NTSTATUS status;
1002 uint8_t *inbuf;
1003 DATA_BLOB ret_blob;
1004};
1005
1006static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1007 struct tevent_req **psubreq);
1008static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1009
1010static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1011 struct tevent_context *ev,
1012 struct cli_state *cli,
1013 DATA_BLOB blob)
1014{
1015 struct tevent_req *req, *subreq;
1016 struct cli_sesssetup_blob_state *state;
1017 uint32_t usable_space;
1018
1019 req = tevent_req_create(mem_ctx, &state,
1020 struct cli_sesssetup_blob_state);
1021 if (req == NULL) {
1022 return NULL;
1023 }
1024 state->ev = ev;
1025 state->blob = blob;
1026 state->cli = cli;
1027
1028 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1029 usable_space = UINT16_MAX;
1030 } else {
1031 usable_space = cli_state_available_size(cli,
1032 BASE_SESSSETUP_BLOB_PACKET_SIZE);
1033 }
1034
1035 if (usable_space == 0) {
1036 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1037 "(not possible to send %u bytes)\n",
1038 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
1039 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1040 return tevent_req_post(req, ev);
1041 }
1042 state->max_blob_size = MIN(usable_space, 0xFFFF);
1043
1044 if (!cli_sesssetup_blob_next(state, &subreq)) {
1045 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1046 return tevent_req_post(req, ev);
1047 }
1048 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1049 return req;
1050}
1051
1052static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1053 struct tevent_req **psubreq)
1054{
1055 struct tevent_req *subreq;
1056 uint16_t thistime;
1057
1058 thistime = MIN(state->blob.length, state->max_blob_size);
1059
1060 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1061
1062 state->smb2_blob.data = state->blob.data;
1063 state->smb2_blob.length = thistime;
1064
1065 state->blob.data += thistime;
1066 state->blob.length -= thistime;
1067
1068 subreq = smb2cli_session_setup_send(state, state->ev,
1069 state->cli->conn,
1070 state->cli->timeout,
1071 state->cli->smb2.session,
1072 0, /* in_flags */
1073 SMB2_CAP_DFS, /* in_capabilities */
1074 0, /* in_channel */
1075 0, /* in_previous_session_id */
1076 &state->smb2_blob);
1077 if (subreq == NULL) {
1078 return false;
1079 }
1080 *psubreq = subreq;
1081 return true;
1082 }
1083
1084 SCVAL(state->vwv+0, 0, 0xFF);
1085 SCVAL(state->vwv+0, 1, 0);
1086 SSVAL(state->vwv+1, 0, 0);
1087 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1088 SSVAL(state->vwv+3, 0, 2);
1089 SSVAL(state->vwv+4, 0, 1);
1090 SIVAL(state->vwv+5, 0, 0);
1091
1092 SSVAL(state->vwv+7, 0, thistime);
1093
1094 SSVAL(state->vwv+8, 0, 0);
1095 SSVAL(state->vwv+9, 0, 0);
1096 SIVAL(state->vwv+10, 0,
1097 cli_session_setup_capabilities(state->cli, CAP_EXTENDED_SECURITY));
1098
1099 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1100 thistime);
1101 if (state->buf == NULL) {
1102 return false;
1103 }
1104 state->blob.data += thistime;
1105 state->blob.length -= thistime;
1106
1107 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1108 "Unix", 5, NULL);
1109 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1110 "Samba", 6, NULL);
1111 if (state->buf == NULL) {
1112 return false;
1113 }
1114 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1115 12, state->vwv,
1116 talloc_get_size(state->buf), state->buf);
1117 if (subreq == NULL) {
1118 return false;
1119 }
1120 *psubreq = subreq;
1121 return true;
1122}
1123
1124static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1125{
1126 struct tevent_req *req = tevent_req_callback_data(
1127 subreq, struct tevent_req);
1128 struct cli_sesssetup_blob_state *state = tevent_req_data(
1129 req, struct cli_sesssetup_blob_state);
1130 struct cli_state *cli = state->cli;
1131 uint8_t wct;
1132 uint16_t *vwv;
1133 uint32_t num_bytes;
1134 uint8_t *bytes;
1135 NTSTATUS status;
1136 uint8_t *p;
1137 uint16_t blob_length;
1138 uint8_t *in;
1139 uint8_t *inhdr;
1140 ssize_t ret;
1141
1142 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1143 status = smb2cli_session_setup_recv(subreq, state,
1144 &state->recv_iov,
1145 &state->ret_blob);
1146 } else {
1147 status = cli_smb_recv(subreq, state, &in, 4, &wct, &vwv,
1148 &num_bytes, &bytes);
1149 TALLOC_FREE(state->buf);
1150 }
1151 TALLOC_FREE(subreq);
1152 if (!NT_STATUS_IS_OK(status)
1153 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1154 tevent_req_nterror(req, status);
1155 return;
1156 }
1157
1158 state->status = status;
1159
1160 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1161 goto next;
1162 }
1163
1164 state->inbuf = in;
1165 inhdr = in + NBT_HDR_SIZE;
1166 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
1167 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
1168
1169 blob_length = SVAL(vwv+3, 0);
1170 if (blob_length > num_bytes) {
1171 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1172 return;
1173 }
1174 state->ret_blob = data_blob_const(bytes, blob_length);
1175
1176 p = bytes + blob_length;
1177
1178 status = smb_bytes_talloc_string(cli,
1179 inhdr,
1180 &cli->server_os,
1181 p,
1182 bytes+num_bytes-p,
1183 &ret);
1184
1185 if (!NT_STATUS_IS_OK(status)) {
1186 tevent_req_nterror(req, status);
1187 return;
1188 }
1189 p += ret;
1190
1191 status = smb_bytes_talloc_string(cli,
1192 inhdr,
1193 &cli->server_type,
1194 p,
1195 bytes+num_bytes-p,
1196 &ret);
1197
1198 if (!NT_STATUS_IS_OK(status)) {
1199 tevent_req_nterror(req, status);
1200 return;
1201 }
1202 p += ret;
1203
1204 status = smb_bytes_talloc_string(cli,
1205 inhdr,
1206 &cli->server_domain,
1207 p,
1208 bytes+num_bytes-p,
1209 &ret);
1210
1211 if (!NT_STATUS_IS_OK(status)) {
1212 tevent_req_nterror(req, status);
1213 return;
1214 }
1215 p += ret;
1216
1217next:
1218 if (state->blob.length != 0) {
1219 /*
1220 * More to send
1221 */
1222 if (!cli_sesssetup_blob_next(state, &subreq)) {
1223 tevent_req_oom(req);
1224 return;
1225 }
1226 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1227 return;
1228 }
1229 tevent_req_done(req);
1230}
1231
1232static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1233 TALLOC_CTX *mem_ctx,
1234 DATA_BLOB *pblob,
1235 uint8_t **pinbuf,
1236 struct iovec **precv_iov)
1237{
1238 struct cli_sesssetup_blob_state *state = tevent_req_data(
1239 req, struct cli_sesssetup_blob_state);
1240 NTSTATUS status;
1241 uint8_t *inbuf;
1242 struct iovec *recv_iov;
1243
1244 if (tevent_req_is_nterror(req, &status)) {
1245 TALLOC_FREE(state->cli->smb2.session);
1246 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1247 return status;
1248 }
1249
1250 inbuf = talloc_move(mem_ctx, &state->inbuf);
1251 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
1252 if (pblob != NULL) {
1253 *pblob = state->ret_blob;
1254 }
1255 if (pinbuf != NULL) {
1256 *pinbuf = inbuf;
1257 }
1258 if (precv_iov != NULL) {
1259 *precv_iov = recv_iov;
1260 }
1261 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1262 return state->status;
1263}
1264
1265#ifdef HAVE_KRB5
1266
1267/****************************************************************************
1268 Use in-memory credentials cache
1269****************************************************************************/
1270
1271static void use_in_memory_ccache(void) {
1272 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1273}
1274
1275#endif /* HAVE_KRB5 */
1276
1277/****************************************************************************
1278 Do a spnego/NTLMSSP encrypted session setup.
1279****************************************************************************/
1280
1281struct cli_session_setup_gensec_state {
1282 struct tevent_context *ev;
1283 struct cli_state *cli;
1284 struct auth_generic_state *auth_generic;
1285 bool is_anonymous;
1286 DATA_BLOB blob_in;
1287 uint8_t *inbuf;
1288 struct iovec *recv_iov;
1289 DATA_BLOB blob_out;
1290 bool local_ready;
1291 bool remote_ready;
1292 DATA_BLOB session_key;
1293};
1294
1295static int cli_session_setup_gensec_state_destructor(
1296 struct cli_session_setup_gensec_state *state)
1297{
1298 TALLOC_FREE(state->auth_generic);
1299 data_blob_clear_free(&state->session_key);
1300 return 0;
1301}
1302
1303static void cli_session_setup_gensec_local_next(struct tevent_req *req);
1304static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
1305static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
1306static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
1307static void cli_session_setup_gensec_ready(struct tevent_req *req);
1308
1309static struct tevent_req *cli_session_setup_gensec_send(
1310 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1311 const char *user, const char *pass, const char *domain,
1312 enum credentials_use_kerberos krb5_state,
1313 const char *target_service,
1314 const char *target_hostname,
1315 const char *target_principal)
1316{
1317 struct tevent_req *req;
1318 struct cli_session_setup_gensec_state *state;
1319 NTSTATUS status;
1320 bool use_spnego_principal = lp_client_use_spnego_principal();
1321
1322 req = tevent_req_create(mem_ctx, &state,
1323 struct cli_session_setup_gensec_state);
1324 if (req == NULL) {
1325 return NULL;
1326 }
1327 state->ev = ev;
1328 state->cli = cli;
1329
1330 talloc_set_destructor(
1331 state, cli_session_setup_gensec_state_destructor);
1332
1333 if (user == NULL || strlen(user) == 0) {
1334 if (pass != NULL && strlen(pass) == 0) {
1335 /*
1336 * some callers pass "" as no password
1337 *
1338 * gensec only handles NULL as no password.
1339 */
1340 pass = NULL;
1341 }
1342 }
1343
1344 status = auth_generic_client_prepare(state, &state->auth_generic);
1345 if (tevent_req_nterror(req, status)) {
1346 return tevent_req_post(req, ev);
1347 }
1348
1349 gensec_want_feature(state->auth_generic->gensec_security,
1350 GENSEC_FEATURE_SESSION_KEY);
1351 if (cli->use_ccache) {
1352 gensec_want_feature(state->auth_generic->gensec_security,
1353 GENSEC_FEATURE_NTLM_CCACHE);
1354 if (pass != NULL && strlen(pass) == 0) {
1355 /*
1356 * some callers pass "" as no password
1357 *
1358 * GENSEC_FEATURE_NTLM_CCACHE only handles
1359 * NULL as no password.
1360 */
1361 pass = NULL;
1362 }
1363 }
1364
1365 status = auth_generic_set_username(state->auth_generic, user);
1366 if (tevent_req_nterror(req, status)) {
1367 return tevent_req_post(req, ev);
1368 }
1369
1370 status = auth_generic_set_domain(state->auth_generic, domain);
1371 if (tevent_req_nterror(req, status)) {
1372 return tevent_req_post(req, ev);
1373 }
1374
1375 if (cli->pw_nt_hash) {
1376 struct samr_Password nt_hash;
1377 size_t converted;
1378 bool ok;
1379
1380 if (pass == NULL) {
1381 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1382 return tevent_req_post(req, ev);
1383 }
1384
1385 converted = strhex_to_str((char *)nt_hash.hash,
1386 sizeof(nt_hash.hash),
1387 pass, strlen(pass));
1388 if (converted != sizeof(nt_hash.hash)) {
1389 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1390 return tevent_req_post(req, ev);
1391 }
1392
1393 ok = cli_credentials_set_nt_hash(state->auth_generic->credentials,
1394 &nt_hash, CRED_SPECIFIED);
1395 if (!ok) {
1396 tevent_req_oom(req);
1397 return tevent_req_post(req, ev);
1398 }
1399 } else {
1400 status = auth_generic_set_password(state->auth_generic, pass);
1401 if (tevent_req_nterror(req, status)) {
1402 return tevent_req_post(req, ev);
1403 }
1404 }
1405
1406 cli_credentials_set_kerberos_state(state->auth_generic->credentials,
1407 krb5_state);
1408
1409 if (krb5_state == CRED_DONT_USE_KERBEROS) {
1410 use_spnego_principal = false;
1411 }
1412
1413 if (target_service != NULL) {
1414 status = gensec_set_target_service(
1415 state->auth_generic->gensec_security,
1416 target_service);
1417 if (tevent_req_nterror(req, status)) {
1418 return tevent_req_post(req, ev);
1419 }
1420 }
1421
1422 if (target_hostname != NULL) {
1423 status = gensec_set_target_hostname(
1424 state->auth_generic->gensec_security,
1425 target_hostname);
1426 if (tevent_req_nterror(req, status)) {
1427 return tevent_req_post(req, ev);
1428 }
1429 }
1430
1431 if (target_principal != NULL) {
1432 status = gensec_set_target_principal(
1433 state->auth_generic->gensec_security,
1434 target_principal);
1435 if (tevent_req_nterror(req, status)) {
1436 return tevent_req_post(req, ev);
1437 }
1438 use_spnego_principal = false;
1439 } else if (target_service != NULL && target_hostname != NULL) {
1440 use_spnego_principal = false;
1441 }
1442
1443 if (use_spnego_principal) {
1444 const DATA_BLOB *b;
1445 b = smbXcli_conn_server_gss_blob(cli->conn);
1446 if (b != NULL) {
1447 state->blob_in = *b;
1448 }
1449 }
1450
1451 state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
1452
1453 status = auth_generic_client_start(state->auth_generic,
1454 GENSEC_OID_SPNEGO);
1455 if (tevent_req_nterror(req, status)) {
1456 return tevent_req_post(req, ev);
1457 }
1458
1459 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1460 state->cli->smb2.session = smbXcli_session_create(cli,
1461 cli->conn);
1462 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1463 return tevent_req_post(req, ev);
1464 }
1465 }
1466
1467 cli_session_setup_gensec_local_next(req);
1468 if (!tevent_req_is_in_progress(req)) {
1469 return tevent_req_post(req, ev);
1470 }
1471
1472 return req;
1473}
1474
1475static void cli_session_setup_gensec_local_next(struct tevent_req *req)
1476{
1477 struct cli_session_setup_gensec_state *state =
1478 tevent_req_data(req,
1479 struct cli_session_setup_gensec_state);
1480 struct tevent_req *subreq = NULL;
1481
1482 if (state->local_ready) {
1483 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1484 return;
1485 }
1486
1487 subreq = gensec_update_send(state, state->ev,
1488 state->auth_generic->gensec_security,
1489 state->blob_in);
1490 if (tevent_req_nomem(subreq, req)) {
1491 return;
1492 }
1493 tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
1494}
1495
1496static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
1497{
1498 struct tevent_req *req =
1499 tevent_req_callback_data(subreq,
1500 struct tevent_req);
1501 struct cli_session_setup_gensec_state *state =
1502 tevent_req_data(req,
1503 struct cli_session_setup_gensec_state);
1504 NTSTATUS status;
1505
1506 status = gensec_update_recv(subreq, state, &state->blob_out);
1507 TALLOC_FREE(subreq);
1508 state->blob_in = data_blob_null;
1509 if (!NT_STATUS_IS_OK(status) &&
1510 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1511 {
1512 tevent_req_nterror(req, status);
1513 return;
1514 }
1515
1516 if (NT_STATUS_IS_OK(status)) {
1517 state->local_ready = true;
1518 }
1519
1520 if (state->local_ready && state->remote_ready) {
1521 cli_session_setup_gensec_ready(req);
1522 return;
1523 }
1524
1525 cli_session_setup_gensec_remote_next(req);
1526}
1527
1528static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
1529{
1530 struct cli_session_setup_gensec_state *state =
1531 tevent_req_data(req,
1532 struct cli_session_setup_gensec_state);
1533 struct tevent_req *subreq = NULL;
1534
1535 if (state->remote_ready) {
1536 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1537 return;
1538 }
1539
1540 subreq = cli_sesssetup_blob_send(state, state->ev,
1541 state->cli, state->blob_out);
1542 if (tevent_req_nomem(subreq, req)) {
1543 return;
1544 }
1545 tevent_req_set_callback(subreq,
1546 cli_session_setup_gensec_remote_done,
1547 req);
1548}
1549
1550static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
1551{
1552 struct tevent_req *req =
1553 tevent_req_callback_data(subreq,
1554 struct tevent_req);
1555 struct cli_session_setup_gensec_state *state =
1556 tevent_req_data(req,
1557 struct cli_session_setup_gensec_state);
1558 NTSTATUS status;
1559
1560 TALLOC_FREE(state->inbuf);
1561 TALLOC_FREE(state->recv_iov);
1562
1563 status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
1564 &state->inbuf, &state->recv_iov);
1565 TALLOC_FREE(subreq);
1566 data_blob_free(&state->blob_out);
1567 if (!NT_STATUS_IS_OK(status) &&
1568 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1569 {
1570 tevent_req_nterror(req, status);
1571 return;
1572 }
1573
1574 if (NT_STATUS_IS_OK(status)) {
1575 struct smbXcli_session *session = NULL;
1576 bool is_guest = false;
1577
1578 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1579 session = state->cli->smb2.session;
1580 } else {
1581 session = state->cli->smb1.session;
1582 }
1583
1584 is_guest = smbXcli_session_is_guest(session);
1585 if (is_guest) {
1586 /*
1587 * We can't finish the gensec handshake, we don't
1588 * have a negotiated session key.
1589 *
1590 * So just pretend we are completely done.
1591 *
1592 * Note that smbXcli_session_is_guest()
1593 * always returns false if we require signing.
1594 */
1595 state->blob_in = data_blob_null;
1596 state->local_ready = true;
1597 }
1598
1599 state->remote_ready = true;
1600 }
1601
1602 if (state->local_ready && state->remote_ready) {
1603 cli_session_setup_gensec_ready(req);
1604 return;
1605 }
1606
1607 cli_session_setup_gensec_local_next(req);
1608}
1609
1610static void cli_session_setup_gensec_ready(struct tevent_req *req)
1611{
1612 struct cli_session_setup_gensec_state *state =
1613 tevent_req_data(req,
1614 struct cli_session_setup_gensec_state);
1615 const char *server_domain = NULL;
1616 NTSTATUS status;
1617
1618 if (state->blob_in.length != 0) {
1619 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1620 return;
1621 }
1622
1623 if (state->blob_out.length != 0) {
1624 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1625 return;
1626 }
1627
1628 /*
1629 * gensec_ntlmssp_server_domain() returns NULL
1630 * if NTLMSSP is not used.
1631 *
1632 * We can remove this later
1633 * and leave the server domain empty for SMB2 and above
1634 * in future releases.
1635 */
1636 server_domain = gensec_ntlmssp_server_domain(
1637 state->auth_generic->gensec_security);
1638
1639 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
1640 TALLOC_FREE(state->cli->server_domain);
1641 state->cli->server_domain = talloc_strdup(state->cli,
1642 server_domain);
1643 if (state->cli->server_domain == NULL) {
1644 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1645 return;
1646 }
1647 }
1648
1649 if (state->is_anonymous) {
1650 /*
1651 * Windows server does not set the
1652 * SMB2_SESSION_FLAG_IS_NULL flag.
1653 *
1654 * This fix makes sure we do not try
1655 * to verify a signature on the final
1656 * session setup response.
1657 */
1658 tevent_req_done(req);
1659 return;
1660 }
1661
1662 status = gensec_session_key(state->auth_generic->gensec_security,
1663 state, &state->session_key);
1664 if (tevent_req_nterror(req, status)) {
1665 return;
1666 }
1667
1668 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1669 struct smbXcli_session *session = state->cli->smb2.session;
1670
1671 status = smb2cli_session_set_session_key(session,
1672 state->session_key,
1673 state->recv_iov);
1674 if (tevent_req_nterror(req, status)) {
1675 return;
1676 }
1677 } else {
1678 struct smbXcli_session *session = state->cli->smb1.session;
1679 bool active;
1680
1681 status = smb1cli_session_set_session_key(session,
1682 state->session_key);
1683 if (tevent_req_nterror(req, status)) {
1684 return;
1685 }
1686
1687 active = smb1cli_conn_activate_signing(state->cli->conn,
1688 state->session_key,
1689 data_blob_null);
1690 if (active) {
1691 bool ok;
1692
1693 ok = smb1cli_conn_check_signing(state->cli->conn,
1694 state->inbuf, 1);
1695 if (!ok) {
1696 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1697 return;
1698 }
1699 }
1700 }
1701
1702 tevent_req_done(req);
1703}
1704
1705static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1706{
1707 struct cli_session_setup_gensec_state *state =
1708 tevent_req_data(req,
1709 struct cli_session_setup_gensec_state);
1710 NTSTATUS status;
1711
1712 if (tevent_req_is_nterror(req, &status)) {
1713 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1714 return status;
1715 }
1716 return NT_STATUS_OK;
1717}
1718
1719#ifdef HAVE_KRB5
1720
1721static char *cli_session_setup_get_principal(
1722 TALLOC_CTX *mem_ctx, const char *spnego_principal,
1723 const char *remote_name, const char *dest_realm)
1724{
1725 char *principal = NULL;
1726
1727 if (!lp_client_use_spnego_principal() ||
1728 strequal(spnego_principal, ADS_IGNORE_PRINCIPAL)) {
1729 spnego_principal = NULL;
1730 }
1731 if (spnego_principal != NULL) {
1732 DEBUG(3, ("cli_session_setup_spnego: using spnego provided "
1733 "principal %s\n", spnego_principal));
1734 return talloc_strdup(mem_ctx, spnego_principal);
1735 }
1736 if (is_ipaddress(remote_name) ||
1737 strequal(remote_name, STAR_SMBSERVER)) {
1738 return NULL;
1739 }
1740
1741 DEBUG(3, ("cli_session_setup_spnego: using target "
1742 "hostname not SPNEGO principal\n"));
1743
1744 if (dest_realm) {
1745 char *realm = strupper_talloc(talloc_tos(), dest_realm);
1746 if (realm == NULL) {
1747 return NULL;
1748 }
1749 principal = talloc_asprintf(talloc_tos(), "cifs/%s@%s",
1750 remote_name, realm);
1751 TALLOC_FREE(realm);
1752 } else {
1753 principal = kerberos_get_principal_from_service_hostname(
1754 talloc_tos(), "cifs", remote_name, lp_realm());
1755 }
1756 DEBUG(3, ("cli_session_setup_spnego: guessed server principal=%s\n",
1757 principal ? principal : "<null>"));
1758
1759 return principal;
1760}
1761#endif
1762
1763static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1764 const char *principal)
1765{
1766 char *account, *p;
1767
1768 account = talloc_strdup(mem_ctx, principal);
1769 if (account == NULL) {
1770 return NULL;
1771 }
1772 p = strchr_m(account, '@');
1773 if (p != NULL) {
1774 *p = '\0';
1775 }
1776 return account;
1777}
1778
1779/****************************************************************************
1780 Do a spnego encrypted session setup.
1781
1782 user_domain: The shortname of the domain the user/machine is a member of.
1783 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1784****************************************************************************/
1785
1786struct cli_session_setup_spnego_state {
1787 struct tevent_context *ev;
1788 struct cli_state *cli;
1789 const char *target_hostname;
1790 const char *user;
1791 const char *account;
1792 const char *pass;
1793 const char *user_domain;
1794 const char *dest_realm;
1795 ADS_STATUS result;
1796};
1797
1798#ifdef HAVE_KRB5
1799static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq);
1800#endif
1801
1802static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq);
1803
1804static struct tevent_req *cli_session_setup_spnego_send(
1805 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1806 const char *user, const char *pass, const char *user_domain)
1807{
1808 struct tevent_req *req, *subreq;
1809 struct cli_session_setup_spnego_state *state;
1810 char *principal = NULL;
1811 char *OIDs[ASN1_MAX_OIDS];
1812 int i;
1813 const char *dest_realm = cli_state_remote_realm(cli);
1814 const DATA_BLOB *server_blob;
1815
1816 req = tevent_req_create(mem_ctx, &state,
1817 struct cli_session_setup_spnego_state);
1818 if (req == NULL) {
1819 return NULL;
1820 }
1821 state->ev = ev;
1822 state->cli = cli;
1823 state->user = user;
1824 state->pass = pass;
1825 state->user_domain = user_domain;
1826 state->dest_realm = dest_realm;
1827
1828 state->account = cli_session_setup_get_account(state, user);
1829 if (tevent_req_nomem(state->account, req)) {
1830 return tevent_req_post(req, ev);
1831 }
1832
1833 state->target_hostname = smbXcli_conn_remote_name(cli->conn);
1834 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1835
1836 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
1837 (unsigned long)server_blob->length));
1838
1839 /* the server might not even do spnego */
1840 if (server_blob->length == 0) {
1841 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1842 goto ntlmssp;
1843 }
1844
1845#if 0
1846 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1847#endif
1848
1849 /* The server sent us the first part of the SPNEGO exchange in the
1850 * negprot reply. It is WRONG to depend on the principal sent in the
1851 * negprot reply, but right now we do it. If we don't receive one,
1852 * we try to best guess, then fall back to NTLM. */
1853 if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
1854 &principal, NULL) ||
1855 OIDs[0] == NULL) {
1856 state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1857 tevent_req_done(req);
1858 return tevent_req_post(req, ev);
1859 }
1860
1861 /* make sure the server understands kerberos */
1862 for (i=0;OIDs[i];i++) {
1863 if (i == 0)
1864 DEBUG(3,("got OID=%s\n", OIDs[i]));
1865 else
1866 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1867 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1868 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1869 cli->got_kerberos_mechanism = True;
1870 }
1871 talloc_free(OIDs[i]);
1872 }
1873
1874 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1875
1876#ifdef HAVE_KRB5
1877 /* If password is set we reauthenticate to kerberos server
1878 * and do not store results */
1879
1880 if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
1881 char *tmp;
1882
1883 tmp = cli_session_setup_get_principal(
1884 talloc_tos(), principal, state->target_hostname, dest_realm);
1885 TALLOC_FREE(principal);
1886 principal = tmp;
1887
1888 if (pass && *pass) {
1889 int ret;
1890
1891 use_in_memory_ccache();
1892 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1893
1894 if (ret){
1895 DEBUG(0, ("Kinit for %s to access %s failed: %s\n", user, principal, error_message(ret)));
1896 TALLOC_FREE(principal);
1897 if (cli->fallback_after_kerberos)
1898 goto ntlmssp;
1899 state->result = ADS_ERROR_KRB5(ret);
1900 tevent_req_done(req);
1901 return tevent_req_post(req, ev);
1902 }
1903 }
1904
1905 if (principal) {
1906 subreq = cli_session_setup_gensec_send(
1907 state, ev, cli,
1908 state->account, pass, user_domain,
1909 CRED_MUST_USE_KERBEROS,
1910 "cifs", state->target_hostname, principal);
1911 if (tevent_req_nomem(subreq, req)) {
1912 return tevent_req_post(req, ev);
1913 }
1914 tevent_req_set_callback(
1915 subreq, cli_session_setup_spnego_done_krb,
1916 req);
1917 return req;
1918 }
1919 }
1920#endif
1921
1922ntlmssp:
1923 subreq = cli_session_setup_gensec_send(
1924 state, state->ev, state->cli,
1925 state->account, state->pass, state->user_domain,
1926 CRED_DONT_USE_KERBEROS,
1927 "cifs", state->target_hostname, NULL);
1928 if (tevent_req_nomem(subreq, req)) {
1929 return tevent_req_post(req, ev);
1930 }
1931 tevent_req_set_callback(
1932 subreq, cli_session_setup_spnego_done_ntlmssp, req);
1933 return req;
1934}
1935
1936#ifdef HAVE_KRB5
1937static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq)
1938{
1939 struct tevent_req *req = tevent_req_callback_data(
1940 subreq, struct tevent_req);
1941 struct cli_session_setup_spnego_state *state = tevent_req_data(
1942 req, struct cli_session_setup_spnego_state);
1943 NTSTATUS status;
1944
1945 status = cli_session_setup_gensec_recv(subreq);
1946 TALLOC_FREE(subreq);
1947 state->result = ADS_ERROR_NT(status);
1948
1949 if (ADS_ERR_OK(state->result) ||
1950 !state->cli->fallback_after_kerberos) {
1951 tevent_req_done(req);
1952 return;
1953 }
1954
1955 subreq = cli_session_setup_gensec_send(
1956 state, state->ev, state->cli,
1957 state->account, state->pass, state->user_domain,
1958 CRED_DONT_USE_KERBEROS,
1959 "cifs", state->target_hostname, NULL);
1960 if (tevent_req_nomem(subreq, req)) {
1961 return;
1962 }
1963 tevent_req_set_callback(subreq, cli_session_setup_spnego_done_ntlmssp,
1964 req);
1965}
1966#endif
1967
1968static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq)
1969{
1970 struct tevent_req *req = tevent_req_callback_data(
1971 subreq, struct tevent_req);
1972 struct cli_session_setup_spnego_state *state = tevent_req_data(
1973 req, struct cli_session_setup_spnego_state);
1974 NTSTATUS status;
1975
1976 status = cli_session_setup_gensec_recv(subreq);
1977 TALLOC_FREE(subreq);
1978 state->result = ADS_ERROR_NT(status);
1979 tevent_req_done(req);
1980}
1981
1982static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1983{
1984 struct cli_session_setup_spnego_state *state = tevent_req_data(
1985 req, struct cli_session_setup_spnego_state);
1986
1987 return state->result;
1988}
1989
1990struct cli_session_setup_state {
1991 uint8_t dummy;
1992};
1993
1994static void cli_session_setup_done_lanman2(struct tevent_req *subreq);
1995static void cli_session_setup_done_spnego(struct tevent_req *subreq);
1996static void cli_session_setup_done_guest(struct tevent_req *subreq);
1997static void cli_session_setup_done_plain(struct tevent_req *subreq);
1998static void cli_session_setup_done_nt1(struct tevent_req *subreq);
1999
2000/****************************************************************************
2001 Send a session setup. The username and workgroup is in UNIX character
2002 format and must be converted to DOS codepage format before sending. If the
2003 password is in plaintext, the same should be done.
2004****************************************************************************/
2005
2006struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
2007 struct tevent_context *ev,
2008 struct cli_state *cli,
2009 const char *user,
2010 const char *pass, int passlen,
2011 const char *ntpass, int ntpasslen,
2012 const char *workgroup)
2013{
2014 struct tevent_req *req, *subreq;
2015 struct cli_session_setup_state *state;
2016 char *p;
2017 char *user2;
2018 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2019
2020 req = tevent_req_create(mem_ctx, &state,
2021 struct cli_session_setup_state);
2022 if (req == NULL) {
2023 return NULL;
2024 }
2025
2026 if (user) {
2027 user2 = talloc_strdup(state, user);
2028 } else {
2029 user2 = talloc_strdup(state, "");
2030 }
2031 if (user2 == NULL) {
2032 tevent_req_oom(req);
2033 return tevent_req_post(req, ev);
2034 }
2035
2036 if (!workgroup) {
2037 workgroup = "";
2038 }
2039
2040 /* allow for workgroups as part of the username */
2041 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
2042 (p=strchr_m(user2,*lp_winbind_separator()))) {
2043 *p = 0;
2044 user = p+1;
2045 if (!strupper_m(user2)) {
2046 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2047 return tevent_req_post(req, ev);
2048 }
2049 workgroup = user2;
2050 }
2051
2052 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
2053 tevent_req_done(req);
2054 return tevent_req_post(req, ev);
2055 }
2056
2057 /* now work out what sort of session setup we are going to
2058 do. I have split this into separate functions to make the
2059 flow a bit easier to understand (tridge) */
2060
2061 /* if its an older server then we have to use the older request format */
2062
2063 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
2064 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2065 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2066 " or 'client ntlmv2 auth = yes'\n"));
2067 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2068 return tevent_req_post(req, ev);
2069 }
2070
2071 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2072 !lp_client_plaintext_auth() && (*pass)) {
2073 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2074 " or 'client ntlmv2 auth = yes'\n"));
2075 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2076 return tevent_req_post(req, ev);
2077 }
2078
2079 subreq = cli_session_setup_lanman2_send(
2080 state, ev, cli, user, pass, passlen, workgroup);
2081 if (tevent_req_nomem(subreq, req)) {
2082 return tevent_req_post(req, ev);
2083 }
2084 tevent_req_set_callback(subreq, cli_session_setup_done_lanman2,
2085 req);
2086 return req;
2087 }
2088
2089 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2090 subreq = cli_session_setup_spnego_send(
2091 state, ev, cli, user, pass, workgroup);
2092 if (tevent_req_nomem(subreq, req)) {
2093 return tevent_req_post(req, ev);
2094 }
2095 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2096 req);
2097 return req;
2098 }
2099
2100 /*
2101 * if the server supports extended security then use SPNEGO
2102 * even for anonymous connections.
2103 */
2104 if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
2105 subreq = cli_session_setup_spnego_send(
2106 state, ev, cli, user, pass, workgroup);
2107 if (tevent_req_nomem(subreq, req)) {
2108 return tevent_req_post(req, ev);
2109 }
2110 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2111 req);
2112 return req;
2113 }
2114
2115 /* if no user is supplied then we have to do an anonymous connection.
2116 passwords are ignored */
2117
2118 if (!user || !*user) {
2119 subreq = cli_session_setup_guest_send(state, ev, cli);
2120 if (tevent_req_nomem(subreq, req)) {
2121 return tevent_req_post(req, ev);
2122 }
2123 tevent_req_set_callback(subreq, cli_session_setup_done_guest,
2124 req);
2125 return req;
2126 }
2127
2128 /* if the server is share level then send a plaintext null
2129 password at this point. The password is sent in the tree
2130 connect */
2131
2132 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
2133 subreq = cli_session_setup_plain_send(
2134 state, ev, cli, user, "", workgroup);
2135 if (tevent_req_nomem(subreq, req)) {
2136 return tevent_req_post(req, ev);
2137 }
2138 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2139 req);
2140 return req;
2141 }
2142
2143 /* if the server doesn't support encryption then we have to use
2144 plaintext. The second password is ignored */
2145
2146 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2147 if (!lp_client_plaintext_auth() && (*pass)) {
2148 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2149 " or 'client ntlmv2 auth = yes'\n"));
2150 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2151 return tevent_req_post(req, ev);
2152 }
2153 subreq = cli_session_setup_plain_send(
2154 state, ev, cli, user, pass, workgroup);
2155 if (tevent_req_nomem(subreq, req)) {
2156 return tevent_req_post(req, ev);
2157 }
2158 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2159 req);
2160 return req;
2161 }
2162
2163 {
2164 /* otherwise do a NT1 style session setup */
2165 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
2166 /*
2167 * Don't send an NTLMv2 response without NTLMSSP
2168 * if we want to use spnego support
2169 */
2170 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
2171 " but 'client use spnego = yes"
2172 " and 'client ntlmv2 auth = yes'\n"));
2173 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2174 return tevent_req_post(req, ev);
2175 }
2176
2177 subreq = cli_session_setup_nt1_send(
2178 state, ev, cli, user, pass, passlen, ntpass, ntpasslen,
2179 workgroup);
2180 if (tevent_req_nomem(subreq, req)) {
2181 return tevent_req_post(req, ev);
2182 }
2183 tevent_req_set_callback(subreq, cli_session_setup_done_nt1,
2184 req);
2185 return req;
2186 }
2187
2188 tevent_req_done(req);
2189 return tevent_req_post(req, ev);
2190}
2191
2192static void cli_session_setup_done_lanman2(struct tevent_req *subreq)
2193{
2194 struct tevent_req *req = tevent_req_callback_data(
2195 subreq, struct tevent_req);
2196 NTSTATUS status;
2197
2198 status = cli_session_setup_lanman2_recv(subreq);
2199 TALLOC_FREE(subreq);
2200 if (!NT_STATUS_IS_OK(status)) {
2201 tevent_req_nterror(req, status);
2202 return;
2203 }
2204 tevent_req_done(req);
2205}
2206
2207static void cli_session_setup_done_spnego(struct tevent_req *subreq)
2208{
2209 struct tevent_req *req = tevent_req_callback_data(
2210 subreq, struct tevent_req);
2211 ADS_STATUS status;
2212
2213 status = cli_session_setup_spnego_recv(subreq);
2214 TALLOC_FREE(subreq);
2215 if (!ADS_ERR_OK(status)) {
2216 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2217 tevent_req_nterror(req, ads_ntstatus(status));
2218 return;
2219 }
2220 tevent_req_done(req);
2221}
2222
2223static void cli_session_setup_done_guest(struct tevent_req *subreq)
2224{
2225 struct tevent_req *req = tevent_req_callback_data(
2226 subreq, struct tevent_req);
2227 NTSTATUS status;
2228
2229 status = cli_session_setup_guest_recv(subreq);
2230 TALLOC_FREE(subreq);
2231 if (!NT_STATUS_IS_OK(status)) {
2232 tevent_req_nterror(req, status);
2233 return;
2234 }
2235 tevent_req_done(req);
2236}
2237
2238static void cli_session_setup_done_plain(struct tevent_req *subreq)
2239{
2240 struct tevent_req *req = tevent_req_callback_data(
2241 subreq, struct tevent_req);
2242 NTSTATUS status;
2243
2244 status = cli_session_setup_plain_recv(subreq);
2245 TALLOC_FREE(subreq);
2246 if (!NT_STATUS_IS_OK(status)) {
2247 tevent_req_nterror(req, status);
2248 return;
2249 }
2250 tevent_req_done(req);
2251}
2252
2253static void cli_session_setup_done_nt1(struct tevent_req *subreq)
2254{
2255 struct tevent_req *req = tevent_req_callback_data(
2256 subreq, struct tevent_req);
2257 NTSTATUS status;
2258
2259 status = cli_session_setup_nt1_recv(subreq);
2260 TALLOC_FREE(subreq);
2261 if (!NT_STATUS_IS_OK(status)) {
2262 DEBUG(3, ("cli_session_setup: NT1 session setup "
2263 "failed: %s\n", nt_errstr(status)));
2264 tevent_req_nterror(req, status);
2265 return;
2266 }
2267 tevent_req_done(req);
2268}
2269
2270NTSTATUS cli_session_setup_recv(struct tevent_req *req)
2271{
2272 return tevent_req_simple_recv_ntstatus(req);
2273}
2274
2275NTSTATUS cli_session_setup(struct cli_state *cli,
2276 const char *user,
2277 const char *pass, int passlen,
2278 const char *ntpass, int ntpasslen,
2279 const char *workgroup)
2280{
2281 struct tevent_context *ev;
2282 struct tevent_req *req;
2283 NTSTATUS status = NT_STATUS_NO_MEMORY;
2284
2285 if (smbXcli_conn_has_async_calls(cli->conn)) {
2286 return NT_STATUS_INVALID_PARAMETER;
2287 }
2288 ev = samba_tevent_context_init(talloc_tos());
2289 if (ev == NULL) {
2290 goto fail;
2291 }
2292 req = cli_session_setup_send(ev, ev, cli, user, pass, passlen,
2293 ntpass, ntpasslen, workgroup);
2294 if (req == NULL) {
2295 goto fail;
2296 }
2297 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2298 goto fail;
2299 }
2300 status = cli_session_setup_recv(req);
2301 fail:
2302 TALLOC_FREE(ev);
2303 return status;
2304}
2305
2306/****************************************************************************
2307 Send a uloggoff.
2308*****************************************************************************/
2309
2310struct cli_ulogoff_state {
2311 struct cli_state *cli;
2312 uint16_t vwv[3];
2313};
2314
2315static void cli_ulogoff_done(struct tevent_req *subreq);
2316
2317static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2318 struct tevent_context *ev,
2319 struct cli_state *cli)
2320{
2321 struct tevent_req *req, *subreq;
2322 struct cli_ulogoff_state *state;
2323
2324 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2325 if (req == NULL) {
2326 return NULL;
2327 }
2328 state->cli = cli;
2329
2330 SCVAL(state->vwv+0, 0, 0xFF);
2331 SCVAL(state->vwv+1, 0, 0);
2332 SSVAL(state->vwv+2, 0, 0);
2333
2334 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2335 0, NULL);
2336 if (tevent_req_nomem(subreq, req)) {
2337 return tevent_req_post(req, ev);
2338 }
2339 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2340 return req;
2341}
2342
2343static void cli_ulogoff_done(struct tevent_req *subreq)
2344{
2345 struct tevent_req *req = tevent_req_callback_data(
2346 subreq, struct tevent_req);
2347 struct cli_ulogoff_state *state = tevent_req_data(
2348 req, struct cli_ulogoff_state);
2349 NTSTATUS status;
2350
2351 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2352 if (!NT_STATUS_IS_OK(status)) {
2353 tevent_req_nterror(req, status);
2354 return;
2355 }
2356 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2357 tevent_req_done(req);
2358}
2359
2360static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2361{
2362 return tevent_req_simple_recv_ntstatus(req);
2363}
2364
2365NTSTATUS cli_ulogoff(struct cli_state *cli)
2366{
2367 struct tevent_context *ev;
2368 struct tevent_req *req;
2369 NTSTATUS status = NT_STATUS_NO_MEMORY;
2370
2371 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2372 status = smb2cli_logoff(cli->conn,
2373 cli->timeout,
2374 cli->smb2.session);
2375 if (!NT_STATUS_IS_OK(status)) {
2376 return status;
2377 }
2378 smb2cli_session_set_id_and_flags(cli->smb2.session,
2379 UINT64_MAX, 0);
2380 return NT_STATUS_OK;
2381 }
2382
2383 if (smbXcli_conn_has_async_calls(cli->conn)) {
2384 return NT_STATUS_INVALID_PARAMETER;
2385 }
2386 ev = samba_tevent_context_init(talloc_tos());
2387 if (ev == NULL) {
2388 goto fail;
2389 }
2390 req = cli_ulogoff_send(ev, ev, cli);
2391 if (req == NULL) {
2392 goto fail;
2393 }
2394 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2395 goto fail;
2396 }
2397 status = cli_ulogoff_recv(req);
2398fail:
2399 TALLOC_FREE(ev);
2400 return status;
2401}
2402
2403/****************************************************************************
2404 Send a tconX.
2405****************************************************************************/
2406
2407struct cli_tcon_andx_state {
2408 struct cli_state *cli;
2409 uint16_t vwv[4];
2410 struct iovec bytes;
2411};
2412
2413static void cli_tcon_andx_done(struct tevent_req *subreq);
2414
2415struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2416 struct tevent_context *ev,
2417 struct cli_state *cli,
2418 const char *share, const char *dev,
2419 const char *pass, int passlen,
2420 struct tevent_req **psmbreq)
2421{
2422 struct tevent_req *req, *subreq;
2423 struct cli_tcon_andx_state *state;
2424 uint8_t p24[24];
2425 uint16_t *vwv;
2426 char *tmp = NULL;
2427 uint8_t *bytes;
2428 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2429 uint16_t tcon_flags = 0;
2430
2431 *psmbreq = NULL;
2432
2433 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2434 if (req == NULL) {
2435 return NULL;
2436 }
2437 state->cli = cli;
2438 vwv = state->vwv;
2439
2440 cli->share = talloc_strdup(cli, share);
2441 if (!cli->share) {
2442 return NULL;
2443 }
2444
2445 /* in user level security don't send a password now */
2446 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2447 passlen = 1;
2448 pass = "";
2449 } else if (pass == NULL) {
2450 DEBUG(1, ("Server not using user level security and no "
2451 "password supplied.\n"));
2452 goto access_denied;
2453 }
2454
2455 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2456 *pass && passlen != 24) {
2457 if (!lp_client_lanman_auth()) {
2458 DEBUG(1, ("Server requested LANMAN password "
2459 "(share-level security) but "
2460 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2461 goto access_denied;
2462 }
2463
2464 /*
2465 * Non-encrypted passwords - convert to DOS codepage before
2466 * encryption.
2467 */
2468 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2469 passlen = 24;
2470 pass = (const char *)p24;
2471 } else {
2472 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2473 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2474 == 0) {
2475 uint8_t *tmp_pass;
2476
2477 if (!lp_client_plaintext_auth() && (*pass)) {
2478 DEBUG(1, ("Server requested PLAINTEXT "
2479 "password but "
2480 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2481 goto access_denied;
2482 }
2483
2484 /*
2485 * Non-encrypted passwords - convert to DOS codepage
2486 * before using.
2487 */
2488 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
2489 if (tevent_req_nomem(tmp_pass, req)) {
2490 return tevent_req_post(req, ev);
2491 }
2492 tmp_pass = trans2_bytes_push_str(tmp_pass,
2493 false, /* always DOS */
2494 pass,
2495 passlen,
2496 NULL);
2497 if (tevent_req_nomem(tmp_pass, req)) {
2498 return tevent_req_post(req, ev);
2499 }
2500 pass = (const char *)tmp_pass;
2501 passlen = talloc_get_size(tmp_pass);
2502 }
2503 }
2504
2505 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2506 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2507
2508 SCVAL(vwv+0, 0, 0xFF);
2509 SCVAL(vwv+0, 1, 0);
2510 SSVAL(vwv+1, 0, 0);
2511 SSVAL(vwv+2, 0, tcon_flags);
2512 SSVAL(vwv+3, 0, passlen);
2513
2514 if (passlen && pass) {
2515 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2516 } else {
2517 bytes = talloc_array(state, uint8_t, 0);
2518 }
2519
2520 /*
2521 * Add the sharename
2522 */
2523 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2524 smbXcli_conn_remote_name(cli->conn), share);
2525 if (tmp == NULL) {
2526 TALLOC_FREE(req);
2527 return NULL;
2528 }
2529 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2530 NULL);
2531 TALLOC_FREE(tmp);
2532
2533 /*
2534 * Add the devicetype
2535 */
2536 tmp = talloc_strdup_upper(talloc_tos(), dev);
2537 if (tmp == NULL) {
2538 TALLOC_FREE(req);
2539 return NULL;
2540 }
2541 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2542 TALLOC_FREE(tmp);
2543
2544 if (bytes == NULL) {
2545 TALLOC_FREE(req);
2546 return NULL;
2547 }
2548
2549 state->bytes.iov_base = (void *)bytes;
2550 state->bytes.iov_len = talloc_get_size(bytes);
2551
2552 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2553 1, &state->bytes);
2554 if (subreq == NULL) {
2555 TALLOC_FREE(req);
2556 return NULL;
2557 }
2558 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2559 *psmbreq = subreq;
2560 return req;
2561
2562 access_denied:
2563 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2564 return tevent_req_post(req, ev);
2565}
2566
2567struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2568 struct tevent_context *ev,
2569 struct cli_state *cli,
2570 const char *share, const char *dev,
2571 const char *pass, int passlen)
2572{
2573 struct tevent_req *req, *subreq;
2574 NTSTATUS status;
2575
2576 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2577 &subreq);
2578 if (req == NULL) {
2579 return NULL;
2580 }
2581 if (subreq == NULL) {
2582 return req;
2583 }
2584 status = smb1cli_req_chain_submit(&subreq, 1);
2585 if (!NT_STATUS_IS_OK(status)) {
2586 tevent_req_nterror(req, status);
2587 return tevent_req_post(req, ev);
2588 }
2589 return req;
2590}
2591
2592static void cli_tcon_andx_done(struct tevent_req *subreq)
2593{
2594 struct tevent_req *req = tevent_req_callback_data(
2595 subreq, struct tevent_req);
2596 struct cli_tcon_andx_state *state = tevent_req_data(
2597 req, struct cli_tcon_andx_state);
2598 struct cli_state *cli = state->cli;
2599 uint8_t *in;
2600 uint8_t *inhdr;
2601 uint8_t wct;
2602 uint16_t *vwv;
2603 uint32_t num_bytes;
2604 uint8_t *bytes;
2605 NTSTATUS status;
2606 uint16_t optional_support = 0;
2607
2608 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2609 &num_bytes, &bytes);
2610 TALLOC_FREE(subreq);
2611 if (!NT_STATUS_IS_OK(status)) {
2612 tevent_req_nterror(req, status);
2613 return;
2614 }
2615
2616 inhdr = in + NBT_HDR_SIZE;
2617
2618 if (num_bytes) {
2619 if (clistr_pull_talloc(cli,
2620 (const char *)inhdr,
2621 SVAL(inhdr, HDR_FLG2),
2622 &cli->dev,
2623 bytes,
2624 num_bytes,
2625 STR_TERMINATE|STR_ASCII) == -1) {
2626 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2627 return;
2628 }
2629 } else {
2630 cli->dev = talloc_strdup(cli, "");
2631 if (cli->dev == NULL) {
2632 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2633 return;
2634 }
2635 }
2636
2637 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2638 /* almost certainly win95 - enable bug fixes */
2639 cli->win95 = True;
2640 }
2641
2642 /*
2643 * Make sure that we have the optional support 16-bit field. WCT > 2.
2644 * Avoids issues when connecting to Win9x boxes sharing files
2645 */
2646
2647 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2648 optional_support = SVAL(vwv+2, 0);
2649 }
2650
2651 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2652 smb1cli_session_protect_session_key(cli->smb1.session);
2653 }
2654
2655 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2656 SVAL(inhdr, HDR_TID),
2657 optional_support,
2658 0, /* maximal_access */
2659 0, /* guest_maximal_access */
2660 NULL, /* service */
2661 NULL); /* fs_type */
2662
2663 tevent_req_done(req);
2664}
2665
2666NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2667{
2668 return tevent_req_simple_recv_ntstatus(req);
2669}
2670
2671NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2672 const char *dev, const char *pass, int passlen)
2673{
2674 TALLOC_CTX *frame = talloc_stackframe();
2675 struct tevent_context *ev;
2676 struct tevent_req *req;
2677 NTSTATUS status = NT_STATUS_NO_MEMORY;
2678
2679 if (smbXcli_conn_has_async_calls(cli->conn)) {
2680 /*
2681 * Can't use sync call while an async call is in flight
2682 */
2683 status = NT_STATUS_INVALID_PARAMETER;
2684 goto fail;
2685 }
2686
2687 ev = samba_tevent_context_init(frame);
2688 if (ev == NULL) {
2689 goto fail;
2690 }
2691
2692 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2693 if (req == NULL) {
2694 goto fail;
2695 }
2696
2697 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2698 goto fail;
2699 }
2700
2701 status = cli_tcon_andx_recv(req);
2702 fail:
2703 TALLOC_FREE(frame);
2704 return status;
2705}
2706
2707struct cli_tree_connect_state {
2708 struct cli_state *cli;
2709};
2710
2711static struct tevent_req *cli_raw_tcon_send(
2712 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2713 const char *service, const char *pass, const char *dev);
2714static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2715 uint16_t *max_xmit, uint16_t *tid);
2716
2717static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2718static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2719static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2720
2721static struct tevent_req *cli_tree_connect_send(
2722 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2723 const char *share, const char *dev, const char *pass, int passlen)
2724{
2725 struct tevent_req *req, *subreq;
2726 struct cli_tree_connect_state *state;
2727
2728 req = tevent_req_create(mem_ctx, &state,
2729 struct cli_tree_connect_state);
2730 if (req == NULL) {
2731 return NULL;
2732 }
2733 state->cli = cli;
2734
2735 cli->share = talloc_strdup(cli, share);
2736 if (tevent_req_nomem(cli->share, req)) {
2737 return tevent_req_post(req, ev);
2738 }
2739
2740 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2741 char *unc;
2742
2743 cli->smb2.tcon = smbXcli_tcon_create(cli);
2744 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2745 return tevent_req_post(req, ev);
2746 }
2747
2748 unc = talloc_asprintf(state, "\\\\%s\\%s",
2749 smbXcli_conn_remote_name(cli->conn),
2750 share);
2751 if (tevent_req_nomem(unc, req)) {
2752 return tevent_req_post(req, ev);
2753 }
2754
2755 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2756 cli->smb2.session, cli->smb2.tcon,
2757 0, /* flags */
2758 unc);
2759 if (tevent_req_nomem(subreq, req)) {
2760 return tevent_req_post(req, ev);
2761 }
2762 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2763 req);
2764 return req;
2765 }
2766
2767 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2768 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2769 pass, passlen);
2770 if (tevent_req_nomem(subreq, req)) {
2771 return tevent_req_post(req, ev);
2772 }
2773 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2774 req);
2775 return req;
2776 }
2777
2778 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2779 if (tevent_req_nomem(subreq, req)) {
2780 return tevent_req_post(req, ev);
2781 }
2782 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2783
2784 return req;
2785}
2786
2787static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2788{
2789 tevent_req_simple_finish_ntstatus(
2790 subreq, smb2cli_tcon_recv(subreq));
2791}
2792
2793static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2794{
2795 tevent_req_simple_finish_ntstatus(
2796 subreq, cli_tcon_andx_recv(subreq));
2797}
2798
2799static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2800{
2801 struct tevent_req *req = tevent_req_callback_data(
2802 subreq, struct tevent_req);
2803 struct cli_tree_connect_state *state = tevent_req_data(
2804 req, struct cli_tree_connect_state);
2805 NTSTATUS status;
2806 uint16_t max_xmit = 0;
2807 uint16_t tid = 0;
2808
2809 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2810 if (tevent_req_nterror(req, status)) {
2811 return;
2812 }
2813
2814 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2815 tid,
2816 0, /* optional_support */
2817 0, /* maximal_access */
2818 0, /* guest_maximal_access */
2819 NULL, /* service */
2820 NULL); /* fs_type */
2821
2822 tevent_req_done(req);
2823}
2824
2825static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2826{
2827 return tevent_req_simple_recv_ntstatus(req);
2828}
2829
2830NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2831 const char *dev, const char *pass, int passlen)
2832{
2833 struct tevent_context *ev;
2834 struct tevent_req *req;
2835 NTSTATUS status = NT_STATUS_NO_MEMORY;
2836
2837 if (smbXcli_conn_has_async_calls(cli->conn)) {
2838 return NT_STATUS_INVALID_PARAMETER;
2839 }
2840 ev = samba_tevent_context_init(talloc_tos());
2841 if (ev == NULL) {
2842 goto fail;
2843 }
2844 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2845 if (req == NULL) {
2846 goto fail;
2847 }
2848 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2849 goto fail;
2850 }
2851 status = cli_tree_connect_recv(req);
2852fail:
2853 TALLOC_FREE(ev);
2854 return status;
2855}
2856
2857/****************************************************************************
2858 Send a tree disconnect.
2859****************************************************************************/
2860
2861struct cli_tdis_state {
2862 struct cli_state *cli;
2863};
2864
2865static void cli_tdis_done(struct tevent_req *subreq);
2866
2867static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2868 struct tevent_context *ev,
2869 struct cli_state *cli)
2870{
2871 struct tevent_req *req, *subreq;
2872 struct cli_tdis_state *state;
2873
2874 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2875 if (req == NULL) {
2876 return NULL;
2877 }
2878 state->cli = cli;
2879
2880 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2881 if (tevent_req_nomem(subreq, req)) {
2882 return tevent_req_post(req, ev);
2883 }
2884 tevent_req_set_callback(subreq, cli_tdis_done, req);
2885 return req;
2886}
2887
2888static void cli_tdis_done(struct tevent_req *subreq)
2889{
2890 struct tevent_req *req = tevent_req_callback_data(
2891 subreq, struct tevent_req);
2892 struct cli_tdis_state *state = tevent_req_data(
2893 req, struct cli_tdis_state);
2894 NTSTATUS status;
2895
2896 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2897 TALLOC_FREE(subreq);
2898 if (!NT_STATUS_IS_OK(status)) {
2899 tevent_req_nterror(req, status);
2900 return;
2901 }
2902 cli_state_set_tid(state->cli, UINT16_MAX);
2903 tevent_req_done(req);
2904}
2905
2906static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2907{
2908 return tevent_req_simple_recv_ntstatus(req);
2909}
2910
2911NTSTATUS cli_tdis(struct cli_state *cli)
2912{
2913 struct tevent_context *ev;
2914 struct tevent_req *req;
2915 NTSTATUS status = NT_STATUS_NO_MEMORY;
2916
2917 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2918 return smb2cli_tdis(cli->conn,
2919 cli->timeout,
2920 cli->smb2.session,
2921 cli->smb2.tcon);
2922 }
2923
2924 if (smbXcli_conn_has_async_calls(cli->conn)) {
2925 return NT_STATUS_INVALID_PARAMETER;
2926 }
2927 ev = samba_tevent_context_init(talloc_tos());
2928 if (ev == NULL) {
2929 goto fail;
2930 }
2931 req = cli_tdis_send(ev, ev, cli);
2932 if (req == NULL) {
2933 goto fail;
2934 }
2935 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2936 goto fail;
2937 }
2938 status = cli_tdis_recv(req);
2939fail:
2940 TALLOC_FREE(ev);
2941 return status;
2942}
2943
2944struct cli_connect_sock_state {
2945 const char **called_names;
2946 const char **calling_names;
2947 int *called_types;
2948 int fd;
2949 uint16_t port;
2950};
2951
2952static void cli_connect_sock_done(struct tevent_req *subreq);
2953
2954/*
2955 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2956 * nonzero address.
2957 */
2958
2959static struct tevent_req *cli_connect_sock_send(
2960 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2961 const char *host, int name_type, const struct sockaddr_storage *pss,
2962 const char *myname, uint16_t port)
2963{
2964 struct tevent_req *req, *subreq;
2965 struct cli_connect_sock_state *state;
2966 const char *prog;
2967 struct sockaddr_storage *addrs;
2968 unsigned i, num_addrs;
2969 NTSTATUS status;
2970
2971 req = tevent_req_create(mem_ctx, &state,
2972 struct cli_connect_sock_state);
2973 if (req == NULL) {
2974 return NULL;
2975 }
2976
2977 prog = getenv("LIBSMB_PROG");
2978 if (prog != NULL) {
2979 state->fd = sock_exec(prog);
2980 if (state->fd == -1) {
2981 status = map_nt_error_from_unix(errno);
2982 tevent_req_nterror(req, status);
2983 } else {
2984 state->port = 0;
2985 tevent_req_done(req);
2986 }
2987 return tevent_req_post(req, ev);
2988 }
2989
2990 if ((pss == NULL) || is_zero_addr(pss)) {
2991
2992 /*
2993 * Here we cheat. resolve_name_list is not async at all. So
2994 * this call will only be really async if the name lookup has
2995 * been done externally.
2996 */
2997
2998 status = resolve_name_list(state, host, name_type,
2999 &addrs, &num_addrs);
3000 if (!NT_STATUS_IS_OK(status)) {
3001 tevent_req_nterror(req, status);
3002 return tevent_req_post(req, ev);
3003 }
3004 } else {
3005 addrs = talloc_array(state, struct sockaddr_storage, 1);
3006 if (tevent_req_nomem(addrs, req)) {
3007 return tevent_req_post(req, ev);
3008 }
3009 addrs[0] = *pss;
3010 num_addrs = 1;
3011 }
3012
3013 state->called_names = talloc_array(state, const char *, num_addrs);
3014 if (tevent_req_nomem(state->called_names, req)) {
3015 return tevent_req_post(req, ev);
3016 }
3017 state->called_types = talloc_array(state, int, num_addrs);
3018 if (tevent_req_nomem(state->called_types, req)) {
3019 return tevent_req_post(req, ev);
3020 }
3021 state->calling_names = talloc_array(state, const char *, num_addrs);
3022 if (tevent_req_nomem(state->calling_names, req)) {
3023 return tevent_req_post(req, ev);
3024 }
3025 for (i=0; i<num_addrs; i++) {
3026 state->called_names[i] = host;
3027 state->called_types[i] = name_type;
3028 state->calling_names[i] = myname;
3029 }
3030
3031 subreq = smbsock_any_connect_send(
3032 state, ev, addrs, state->called_names, state->called_types,
3033 state->calling_names, NULL, num_addrs, port);
3034 if (tevent_req_nomem(subreq, req)) {
3035 return tevent_req_post(req, ev);
3036 }
3037 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
3038 return req;
3039}
3040
3041static void cli_connect_sock_done(struct tevent_req *subreq)
3042{
3043 struct tevent_req *req = tevent_req_callback_data(
3044 subreq, struct tevent_req);
3045 struct cli_connect_sock_state *state = tevent_req_data(
3046 req, struct cli_connect_sock_state);
3047 NTSTATUS status;
3048
3049 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
3050 &state->port);
3051 TALLOC_FREE(subreq);
3052 if (tevent_req_nterror(req, status)) {
3053 return;
3054 }
3055 set_socket_options(state->fd, lp_socket_options());
3056 tevent_req_done(req);
3057}
3058
3059static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
3060 int *pfd, uint16_t *pport)
3061{
3062 struct cli_connect_sock_state *state = tevent_req_data(
3063 req, struct cli_connect_sock_state);
3064 NTSTATUS status;
3065
3066 if (tevent_req_is_nterror(req, &status)) {
3067 return status;
3068 }
3069 *pfd = state->fd;
3070 *pport = state->port;
3071 return NT_STATUS_OK;
3072}
3073
3074struct cli_connect_nb_state {
3075 const char *desthost;
3076 int signing_state;
3077 int flags;
3078 struct cli_state *cli;
3079};
3080
3081static void cli_connect_nb_done(struct tevent_req *subreq);
3082
3083static struct tevent_req *cli_connect_nb_send(
3084 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3085 const char *host, const struct sockaddr_storage *dest_ss,
3086 uint16_t port, int name_type, const char *myname,
3087 int signing_state, int flags)
3088{
3089 struct tevent_req *req, *subreq;
3090 struct cli_connect_nb_state *state;
3091
3092 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
3093 if (req == NULL) {
3094 return NULL;
3095 }
3096 state->signing_state = signing_state;
3097 state->flags = flags;
3098
3099 if (host != NULL) {
3100 char *p = strchr(host, '#');
3101
3102 if (p != NULL) {
3103 name_type = strtol(p+1, NULL, 16);
3104 host = talloc_strndup(state, host, p - host);
3105 if (tevent_req_nomem(host, req)) {
3106 return tevent_req_post(req, ev);
3107 }
3108 }
3109
3110 state->desthost = host;
3111 } else if (dest_ss != NULL) {
3112 state->desthost = print_canonical_sockaddr(state, dest_ss);
3113 if (tevent_req_nomem(state->desthost, req)) {
3114 return tevent_req_post(req, ev);
3115 }
3116 } else {
3117 /* No host or dest_ss given. Error out. */
3118 tevent_req_error(req, EINVAL);
3119 return tevent_req_post(req, ev);
3120 }
3121
3122 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
3123 myname, port);
3124 if (tevent_req_nomem(subreq, req)) {
3125 return tevent_req_post(req, ev);
3126 }
3127 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
3128 return req;
3129}
3130
3131static void cli_connect_nb_done(struct tevent_req *subreq)
3132{
3133 struct tevent_req *req = tevent_req_callback_data(
3134 subreq, struct tevent_req);
3135 struct cli_connect_nb_state *state = tevent_req_data(
3136 req, struct cli_connect_nb_state);
3137 NTSTATUS status;
3138 int fd = 0;
3139 uint16_t port;
3140
3141 status = cli_connect_sock_recv(subreq, &fd, &port);
3142 TALLOC_FREE(subreq);
3143 if (tevent_req_nterror(req, status)) {
3144 return;
3145 }
3146
3147 state->cli = cli_state_create(state, fd, state->desthost, NULL,
3148 state->signing_state, state->flags);
3149 if (tevent_req_nomem(state->cli, req)) {
3150 close(fd);
3151 return;
3152 }
3153 tevent_req_done(req);
3154}
3155
3156static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
3157 struct cli_state **pcli)
3158{
3159 struct cli_connect_nb_state *state = tevent_req_data(
3160 req, struct cli_connect_nb_state);
3161 NTSTATUS status;
3162
3163 if (tevent_req_is_nterror(req, &status)) {
3164 return status;
3165 }
3166 *pcli = talloc_move(NULL, &state->cli);
3167 return NT_STATUS_OK;
3168}
3169
3170NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
3171 uint16_t port, int name_type, const char *myname,
3172 int signing_state, int flags, struct cli_state **pcli)
3173{
3174 struct tevent_context *ev;
3175 struct tevent_req *req;
3176 NTSTATUS status = NT_STATUS_NO_MEMORY;
3177
3178 ev = samba_tevent_context_init(talloc_tos());
3179 if (ev == NULL) {
3180 goto fail;
3181 }
3182 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
3183 myname, signing_state, flags);
3184 if (req == NULL) {
3185 goto fail;
3186 }
3187 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
3188 goto fail;
3189 }
3190 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3191 goto fail;
3192 }
3193 status = cli_connect_nb_recv(req, pcli);
3194fail:
3195 TALLOC_FREE(ev);
3196 return status;
3197}
3198
3199struct cli_start_connection_state {
3200 struct tevent_context *ev;
3201 struct cli_state *cli;
3202 int min_protocol;
3203 int max_protocol;
3204};
3205
3206static void cli_start_connection_connected(struct tevent_req *subreq);
3207static void cli_start_connection_done(struct tevent_req *subreq);
3208
3209/**
3210 establishes a connection to after the negprot.
3211 @param output_cli A fully initialised cli structure, non-null only on success
3212 @param dest_host The netbios name of the remote host
3213 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3214 @param port (optional) The destination port (0 for default)
3215*/
3216
3217static struct tevent_req *cli_start_connection_send(
3218 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3219 const char *my_name, const char *dest_host,
3220 const struct sockaddr_storage *dest_ss, int port,
3221 int signing_state, int flags)
3222{
3223 struct tevent_req *req, *subreq;
3224 struct cli_start_connection_state *state;
3225
3226 req = tevent_req_create(mem_ctx, &state,
3227 struct cli_start_connection_state);
3228 if (req == NULL) {
3229 return NULL;
3230 }
3231 state->ev = ev;
3232
3233 if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
3234 state->min_protocol = lp_client_ipc_min_protocol();
3235 state->max_protocol = lp_client_ipc_max_protocol();
3236 } else {
3237 state->min_protocol = lp_client_min_protocol();
3238 state->max_protocol = lp_client_max_protocol();
3239 }
3240
3241 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
3242 0x20, my_name, signing_state, flags);
3243 if (tevent_req_nomem(subreq, req)) {
3244 return tevent_req_post(req, ev);
3245 }
3246 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
3247 return req;
3248}
3249
3250static void cli_start_connection_connected(struct tevent_req *subreq)
3251{
3252 struct tevent_req *req = tevent_req_callback_data(
3253 subreq, struct tevent_req);
3254 struct cli_start_connection_state *state = tevent_req_data(
3255 req, struct cli_start_connection_state);
3256 NTSTATUS status;
3257
3258 status = cli_connect_nb_recv(subreq, &state->cli);
3259 TALLOC_FREE(subreq);
3260 if (tevent_req_nterror(req, status)) {
3261 return;
3262 }
3263
3264 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
3265 state->cli->timeout,
3266 state->min_protocol,
3267 state->max_protocol);
3268 if (tevent_req_nomem(subreq, req)) {
3269 return;
3270 }
3271 tevent_req_set_callback(subreq, cli_start_connection_done, req);
3272}
3273
3274static void cli_start_connection_done(struct tevent_req *subreq)
3275{
3276 struct tevent_req *req = tevent_req_callback_data(
3277 subreq, struct tevent_req);
3278 struct cli_start_connection_state *state = tevent_req_data(
3279 req, struct cli_start_connection_state);
3280 NTSTATUS status;
3281
3282 status = smbXcli_negprot_recv(subreq);
3283 TALLOC_FREE(subreq);
3284 if (tevent_req_nterror(req, status)) {
3285 return;
3286 }
3287
3288 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3289 /* Ensure we ask for some initial credits. */
3290 smb2cli_conn_set_max_credits(state->cli->conn,
3291 DEFAULT_SMB2_MAX_CREDITS);
3292 }
3293
3294 tevent_req_done(req);
3295}
3296
3297static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
3298 struct cli_state **output_cli)
3299{
3300 struct cli_start_connection_state *state = tevent_req_data(
3301 req, struct cli_start_connection_state);
3302 NTSTATUS status;
3303
3304 if (tevent_req_is_nterror(req, &status)) {
3305 return status;
3306 }
3307 *output_cli = state->cli;
3308
3309 return NT_STATUS_OK;
3310}
3311
3312NTSTATUS cli_start_connection(struct cli_state **output_cli,
3313 const char *my_name,
3314 const char *dest_host,
3315 const struct sockaddr_storage *dest_ss, int port,
3316 int signing_state, int flags)
3317{
3318 struct tevent_context *ev;
3319 struct tevent_req *req;
3320 NTSTATUS status = NT_STATUS_NO_MEMORY;
3321
3322 ev = samba_tevent_context_init(talloc_tos());
3323 if (ev == NULL) {
3324 goto fail;
3325 }
3326 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
3327 port, signing_state, flags);
3328 if (req == NULL) {
3329 goto fail;
3330 }
3331 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3332 goto fail;
3333 }
3334 status = cli_start_connection_recv(req, output_cli);
3335fail:
3336 TALLOC_FREE(ev);
3337 return status;
3338}
3339
3340/**
3341 establishes a connection right up to doing tconX, password specified.
3342 @param output_cli A fully initialised cli structure, non-null only on success
3343 @param dest_host The netbios name of the remote host
3344 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3345 @param port (optional) The destination port (0 for default)
3346 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3347 @param service_type The 'type' of serivice.
3348 @param user Username, unix string
3349 @param domain User's domain
3350 @param password User's password, unencrypted unix string.
3351*/
3352
3353struct cli_full_connection_state {
3354 struct tevent_context *ev;
3355 const char *service;
3356 const char *service_type;
3357 const char *user;
3358 const char *domain;
3359 const char *password;
3360 int pw_len;
3361 int flags;
3362 struct cli_state *cli;
3363};
3364
3365static int cli_full_connection_state_destructor(
3366 struct cli_full_connection_state *s);
3367static void cli_full_connection_started(struct tevent_req *subreq);
3368static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
3369static void cli_full_connection_done(struct tevent_req *subreq);
3370
3371struct tevent_req *cli_full_connection_send(
3372 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3373 const char *my_name, const char *dest_host,
3374 const struct sockaddr_storage *dest_ss, int port,
3375 const char *service, const char *service_type,
3376 const char *user, const char *domain,
3377 const char *password, int flags, int signing_state)
3378{
3379 struct tevent_req *req, *subreq;
3380 struct cli_full_connection_state *state;
3381
3382 req = tevent_req_create(mem_ctx, &state,
3383 struct cli_full_connection_state);
3384 if (req == NULL) {
3385 return NULL;
3386 }
3387 talloc_set_destructor(state, cli_full_connection_state_destructor);
3388
3389 state->ev = ev;
3390 state->service = service;
3391 state->service_type = service_type;
3392 state->user = user;
3393 state->domain = domain;
3394 state->password = password;
3395 state->flags = flags;
3396
3397 state->pw_len = state->password ? strlen(state->password)+1 : 0;
3398 if (state->password == NULL) {
3399 state->password = "";
3400 }
3401
3402 subreq = cli_start_connection_send(
3403 state, ev, my_name, dest_host, dest_ss, port,
3404 signing_state, flags);
3405 if (tevent_req_nomem(subreq, req)) {
3406 return tevent_req_post(req, ev);
3407 }
3408 tevent_req_set_callback(subreq, cli_full_connection_started, req);
3409 return req;
3410}
3411
3412static int cli_full_connection_state_destructor(
3413 struct cli_full_connection_state *s)
3414{
3415 if (s->cli != NULL) {
3416 cli_shutdown(s->cli);
3417 s->cli = NULL;
3418 }
3419 return 0;
3420}
3421
3422static void cli_full_connection_started(struct tevent_req *subreq)
3423{
3424 struct tevent_req *req = tevent_req_callback_data(
3425 subreq, struct tevent_req);
3426 struct cli_full_connection_state *state = tevent_req_data(
3427 req, struct cli_full_connection_state);
3428 NTSTATUS status;
3429
3430 status = cli_start_connection_recv(subreq, &state->cli);
3431 TALLOC_FREE(subreq);
3432 if (tevent_req_nterror(req, status)) {
3433 return;
3434 }
3435 subreq = cli_session_setup_send(
3436 state, state->ev, state->cli, state->user,
3437 state->password, state->pw_len, state->password, state->pw_len,
3438 state->domain);
3439 if (tevent_req_nomem(subreq, req)) {
3440 return;
3441 }
3442 tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
3443}
3444
3445static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
3446{
3447 struct tevent_req *req = tevent_req_callback_data(
3448 subreq, struct tevent_req);
3449 struct cli_full_connection_state *state = tevent_req_data(
3450 req, struct cli_full_connection_state);
3451 NTSTATUS status;
3452
3453 status = cli_session_setup_recv(subreq);
3454 TALLOC_FREE(subreq);
3455
3456 if (!NT_STATUS_IS_OK(status) &&
3457 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3458
3459 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3460
3461 subreq = cli_session_setup_send(
3462 state, state->ev, state->cli, "", "", 0, "", 0,
3463 state->domain);
3464 if (tevent_req_nomem(subreq, req)) {
3465 return;
3466 }
3467 tevent_req_set_callback(
3468 subreq, cli_full_connection_sess_set_up, req);
3469 return;
3470 }
3471
3472 if (tevent_req_nterror(req, status)) {
3473 return;
3474 }
3475
3476 if (state->service != NULL) {
3477 subreq = cli_tree_connect_send(
3478 state, state->ev, state->cli,
3479 state->service, state->service_type,
3480 state->password, state->pw_len);
3481 if (tevent_req_nomem(subreq, req)) {
3482 return;
3483 }
3484 tevent_req_set_callback(subreq, cli_full_connection_done, req);
3485 return;
3486 }
3487
3488 tevent_req_done(req);
3489}
3490
3491static void cli_full_connection_done(struct tevent_req *subreq)
3492{
3493 struct tevent_req *req = tevent_req_callback_data(
3494 subreq, struct tevent_req);
3495 NTSTATUS status;
3496
3497 status = cli_tree_connect_recv(subreq);
3498 TALLOC_FREE(subreq);
3499 if (tevent_req_nterror(req, status)) {
3500 return;
3501 }
3502
3503 tevent_req_done(req);
3504}
3505
3506NTSTATUS cli_full_connection_recv(struct tevent_req *req,
3507 struct cli_state **output_cli)
3508{
3509 struct cli_full_connection_state *state = tevent_req_data(
3510 req, struct cli_full_connection_state);
3511 NTSTATUS status;
3512
3513 if (tevent_req_is_nterror(req, &status)) {
3514 return status;
3515 }
3516 *output_cli = state->cli;
3517 talloc_set_destructor(state, NULL);
3518 return NT_STATUS_OK;
3519}
3520
3521NTSTATUS cli_full_connection(struct cli_state **output_cli,
3522 const char *my_name,
3523 const char *dest_host,
3524 const struct sockaddr_storage *dest_ss, int port,
3525 const char *service, const char *service_type,
3526 const char *user, const char *domain,
3527 const char *password, int flags,
3528 int signing_state)
3529{
3530 struct tevent_context *ev;
3531 struct tevent_req *req;
3532 NTSTATUS status = NT_STATUS_NO_MEMORY;
3533
3534 ev = samba_tevent_context_init(talloc_tos());
3535 if (ev == NULL) {
3536 goto fail;
3537 }
3538 req = cli_full_connection_send(
3539 ev, ev, my_name, dest_host, dest_ss, port, service,
3540 service_type, user, domain, password, flags, signing_state);
3541 if (req == NULL) {
3542 goto fail;
3543 }
3544 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3545 goto fail;
3546 }
3547 status = cli_full_connection_recv(req, output_cli);
3548 fail:
3549 TALLOC_FREE(ev);
3550 return status;
3551}
3552
3553/****************************************************************************
3554 Send an old style tcon.
3555****************************************************************************/
3556struct cli_raw_tcon_state {
3557 uint16_t *ret_vwv;
3558};
3559
3560static void cli_raw_tcon_done(struct tevent_req *subreq);
3561
3562static struct tevent_req *cli_raw_tcon_send(
3563 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3564 const char *service, const char *pass, const char *dev)
3565{
3566 struct tevent_req *req, *subreq;
3567 struct cli_raw_tcon_state *state;
3568 uint8_t *bytes;
3569
3570 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3571 if (req == NULL) {
3572 return NULL;
3573 }
3574
3575 if (!lp_client_plaintext_auth() && (*pass)) {
3576 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3577 " or 'client ntlmv2 auth = yes'\n"));
3578 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3579 return tevent_req_post(req, ev);
3580 }
3581
3582 bytes = talloc_array(state, uint8_t, 0);
3583 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3584 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3585 service, strlen(service)+1, NULL);
3586 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3587 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3588 pass, strlen(pass)+1, NULL);
3589 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3590 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3591 dev, strlen(dev)+1, NULL);
3592
3593 if (tevent_req_nomem(bytes, req)) {
3594 return tevent_req_post(req, ev);
3595 }
3596
3597 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, NULL,
3598 talloc_get_size(bytes), bytes);
3599 if (tevent_req_nomem(subreq, req)) {
3600 return tevent_req_post(req, ev);
3601 }
3602 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3603 return req;
3604}
3605
3606static void cli_raw_tcon_done(struct tevent_req *subreq)
3607{
3608 struct tevent_req *req = tevent_req_callback_data(
3609 subreq, struct tevent_req);
3610 struct cli_raw_tcon_state *state = tevent_req_data(
3611 req, struct cli_raw_tcon_state);
3612 NTSTATUS status;
3613
3614 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3615 NULL, NULL);
3616 TALLOC_FREE(subreq);
3617 if (tevent_req_nterror(req, status)) {
3618 return;
3619 }
3620 tevent_req_done(req);
3621}
3622
3623static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3624 uint16_t *max_xmit, uint16_t *tid)
3625{
3626 struct cli_raw_tcon_state *state = tevent_req_data(
3627 req, struct cli_raw_tcon_state);
3628 NTSTATUS status;
3629
3630 if (tevent_req_is_nterror(req, &status)) {
3631 return status;
3632 }
3633 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3634 *tid = SVAL(state->ret_vwv + 1, 0);
3635 return NT_STATUS_OK;
3636}
3637
3638NTSTATUS cli_raw_tcon(struct cli_state *cli,
3639 const char *service, const char *pass, const char *dev,
3640 uint16_t *max_xmit, uint16_t *tid)
3641{
3642 struct tevent_context *ev;
3643 struct tevent_req *req;
3644 NTSTATUS status = NT_STATUS_NO_MEMORY;
3645
3646 ev = samba_tevent_context_init(talloc_tos());
3647 if (ev == NULL) {
3648 goto fail;
3649 }
3650 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3651 if (req == NULL) {
3652 goto fail;
3653 }
3654 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3655 goto fail;
3656 }
3657 status = cli_raw_tcon_recv(req, max_xmit, tid);
3658fail:
3659 TALLOC_FREE(ev);
3660 return status;
3661}
3662
3663/* Return a cli_state pointing at the IPC$ share for the given server */
3664
3665struct cli_state *get_ipc_connect(char *server,
3666 struct sockaddr_storage *server_ss,
3667 const struct user_auth_info *user_info)
3668{
3669 struct cli_state *cli;
3670 NTSTATUS nt_status;
3671 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3672
3673 if (user_info->use_kerberos) {
3674 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3675 }
3676
3677 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3678 user_info->username ? user_info->username : "",
3679 lp_workgroup(),
3680 user_info->password ? user_info->password : "",
3681 flags,
3682 SMB_SIGNING_DEFAULT);
3683
3684 if (NT_STATUS_IS_OK(nt_status)) {
3685 return cli;
3686 } else if (is_ipaddress(server)) {
3687 /* windows 9* needs a correct NMB name for connections */
3688 fstring remote_name;
3689
3690 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3691 cli = get_ipc_connect(remote_name, server_ss, user_info);
3692 if (cli)
3693 return cli;
3694 }
3695 }
3696 return NULL;
3697}
3698
3699/*
3700 * Given the IP address of a master browser on the network, return its
3701 * workgroup and connect to it.
3702 *
3703 * This function is provided to allow additional processing beyond what
3704 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3705 * browsers and obtain each master browsers' list of domains (in case the
3706 * first master browser is recently on the network and has not yet
3707 * synchronized with other master browsers and therefore does not yet have the
3708 * entire network browse list)
3709 */
3710
3711struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3712 struct sockaddr_storage *mb_ip,
3713 const struct user_auth_info *user_info,
3714 char **pp_workgroup_out)
3715{
3716 char addr[INET6_ADDRSTRLEN];
3717 fstring name;
3718 struct cli_state *cli;
3719 struct sockaddr_storage server_ss;
3720
3721 *pp_workgroup_out = NULL;
3722
3723 print_sockaddr(addr, sizeof(addr), mb_ip);
3724 DEBUG(99, ("Looking up name of master browser %s\n",
3725 addr));
3726
3727 /*
3728 * Do a name status query to find out the name of the master browser.
3729 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3730 * master browser will not respond to a wildcard query (or, at least,
3731 * an NT4 server acting as the domain master browser will not).
3732 *
3733 * We might be able to use ONLY the query on MSBROWSE, but that's not
3734 * yet been tested with all Windows versions, so until it is, leave
3735 * the original wildcard query as the first choice and fall back to
3736 * MSBROWSE if the wildcard query fails.
3737 */
3738 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3739 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3740
3741 DEBUG(99, ("Could not retrieve name status for %s\n",
3742 addr));
3743 return NULL;
3744 }
3745
3746 if (!find_master_ip(name, &server_ss)) {
3747 DEBUG(99, ("Could not find master ip for %s\n", name));
3748 return NULL;
3749 }
3750
3751 *pp_workgroup_out = talloc_strdup(ctx, name);
3752
3753 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3754
3755 print_sockaddr(addr, sizeof(addr), &server_ss);
3756 cli = get_ipc_connect(addr, &server_ss, user_info);
3757
3758 return cli;
3759}
3760
3761/*
3762 * Return the IP address and workgroup of a master browser on the network, and
3763 * connect to it.
3764 */
3765
3766struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3767 const struct user_auth_info *user_info,
3768 char **pp_workgroup_out)
3769{
3770 struct sockaddr_storage *ip_list;
3771 struct cli_state *cli;
3772 int i, count;
3773 NTSTATUS status;
3774
3775 *pp_workgroup_out = NULL;
3776
3777 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3778
3779 /* Go looking for workgroups by broadcasting on the local network */
3780
3781 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3782 &ip_list, &count);
3783 if (!NT_STATUS_IS_OK(status)) {
3784 DEBUG(99, ("No master browsers responded: %s\n",
3785 nt_errstr(status)));
3786 return NULL;
3787 }
3788
3789 for (i = 0; i < count; i++) {
3790 char addr[INET6_ADDRSTRLEN];
3791 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3792 DEBUG(99, ("Found master browser %s\n", addr));
3793
3794 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3795 user_info, pp_workgroup_out);
3796 if (cli)
3797 return(cli);
3798 }
3799
3800 return NULL;
3801}
Note: See TracBrowser for help on using the repository browser.