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

Last change on this file was 740, checked in by Silvan Scherrer, 13 years ago

Samba Server: update vendor to 3.6.0

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