source: trunk/server/source3/libsmb/cliconnect.c@ 920

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

Samba Server: apply latest security patches to trunk

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