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

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

Samba Server: updated trunk to 3.6.9

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