s4-dsdb/syntax: Map remote ATTIDs for Class OID syntax
[Samba.git] / source3 / libsmb / cliconnect.c
blob1e11e158f71cdee6b7ebe62390fe2359783031e3
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
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "popt_common.h"
23 #include "../libcli/auth/libcli_auth.h"
24 #include "../libcli/auth/spnego.h"
25 #include "smb_krb5.h"
26 #include "../libcli/auth/ntlmssp.h"
27 #include "libads/kerberos_proto.h"
28 #include "krb5_env.h"
29 #include "async_smb.h"
31 static const struct {
32 int prot;
33 const char name[24];
34 } prots[10] = {
35 {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
36 {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
37 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
38 {PROTOCOL_LANMAN1, "LANMAN1.0"},
39 {PROTOCOL_LANMAN2, "LM1.2X002"},
40 {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
41 {PROTOCOL_LANMAN2, "LANMAN2.1"},
42 {PROTOCOL_LANMAN2, "Samba"},
43 {PROTOCOL_NT1, "NT LANMAN 1.0"},
44 {PROTOCOL_NT1, "NT LM 0.12"},
47 #define STAR_SMBSERVER "*SMBSERVER"
49 /**
50 * Set the user session key for a connection
51 * @param cli The cli structure to add it too
52 * @param session_key The session key used. (A copy of this is taken for the cli struct)
56 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
58 cli->user_session_key = data_blob(session_key.data, session_key.length);
61 /****************************************************************************
62 Do an old lanman2 style session setup.
63 ****************************************************************************/
65 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
66 const char *user,
67 const char *pass, size_t passlen,
68 const char *workgroup)
70 DATA_BLOB session_key = data_blob_null;
71 DATA_BLOB lm_response = data_blob_null;
72 NTSTATUS status;
73 fstring pword;
74 char *p;
76 if (passlen > sizeof(pword)-1) {
77 return NT_STATUS_INVALID_PARAMETER;
80 /* LANMAN servers predate NT status codes and Unicode and ignore those
81 smb flags so we must disable the corresponding default capabilities
82 that would otherwise cause the Unicode and NT Status flags to be
83 set (and even returned by the server) */
85 cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
87 /* if in share level security then don't send a password now */
88 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
89 passlen = 0;
91 if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
92 /* Encrypted mode needed, and non encrypted password supplied. */
93 lm_response = data_blob(NULL, 24);
94 if (!SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data)) {
95 DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n"));
96 return NT_STATUS_ACCESS_DENIED;
98 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
99 /* Encrypted mode needed, and encrypted password supplied. */
100 lm_response = data_blob(pass, passlen);
101 } else if (passlen > 0) {
102 /* Plaintext mode needed, assume plaintext supplied. */
103 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
104 lm_response = data_blob(pass, passlen);
107 /* send a session setup command */
108 memset(cli->outbuf,'\0',smb_size);
109 cli_set_message(cli->outbuf,10, 0, True);
110 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
111 cli_setup_packet(cli);
113 SCVAL(cli->outbuf,smb_vwv0,0xFF);
114 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
115 SSVAL(cli->outbuf,smb_vwv3,2);
116 SSVAL(cli->outbuf,smb_vwv4,1);
117 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
118 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
120 p = smb_buf(cli->outbuf);
121 memcpy(p,lm_response.data,lm_response.length);
122 p += lm_response.length;
123 p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
124 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
125 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
126 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
127 cli_setup_bcc(cli, p);
129 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
130 return cli_nt_error(cli);
133 show_msg(cli->inbuf);
135 if (cli_is_error(cli)) {
136 return cli_nt_error(cli);
139 /* use the returned vuid from now on */
140 cli->vuid = SVAL(cli->inbuf,smb_uid);
141 status = cli_set_username(cli, user);
142 if (!NT_STATUS_IS_OK(status)) {
143 return status;
146 if (session_key.data) {
147 /* Have plaintext orginal */
148 cli_set_session_key(cli, session_key);
151 return NT_STATUS_OK;
154 /****************************************************************************
155 Work out suitable capabilities to offer the server.
156 ****************************************************************************/
158 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
160 uint32 capabilities = CAP_NT_SMBS;
162 if (!cli->force_dos_errors)
163 capabilities |= CAP_STATUS32;
165 if (cli->use_level_II_oplocks)
166 capabilities |= CAP_LEVEL_II_OPLOCKS;
168 capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
169 return capabilities;
172 /****************************************************************************
173 Do a NT1 guest session setup.
174 ****************************************************************************/
176 struct cli_session_setup_guest_state {
177 struct cli_state *cli;
178 uint16_t vwv[16];
179 struct iovec bytes;
182 static void cli_session_setup_guest_done(struct tevent_req *subreq);
184 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
185 struct event_context *ev,
186 struct cli_state *cli,
187 struct tevent_req **psmbreq)
189 struct tevent_req *req, *subreq;
190 struct cli_session_setup_guest_state *state;
191 uint16_t *vwv;
192 uint8_t *bytes;
194 req = tevent_req_create(mem_ctx, &state,
195 struct cli_session_setup_guest_state);
196 if (req == NULL) {
197 return NULL;
199 state->cli = cli;
200 vwv = state->vwv;
202 SCVAL(vwv+0, 0, 0xFF);
203 SCVAL(vwv+0, 1, 0);
204 SSVAL(vwv+1, 0, 0);
205 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
206 SSVAL(vwv+3, 0, 2);
207 SSVAL(vwv+4, 0, cli->pid);
208 SIVAL(vwv+5, 0, cli->sesskey);
209 SSVAL(vwv+7, 0, 0);
210 SSVAL(vwv+8, 0, 0);
211 SSVAL(vwv+9, 0, 0);
212 SSVAL(vwv+10, 0, 0);
213 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
215 bytes = talloc_array(state, uint8_t, 0);
217 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
218 NULL);
219 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
220 NULL);
221 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
222 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
224 if (bytes == NULL) {
225 TALLOC_FREE(req);
226 return NULL;
229 state->bytes.iov_base = (void *)bytes;
230 state->bytes.iov_len = talloc_get_size(bytes);
232 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
233 1, &state->bytes);
234 if (subreq == NULL) {
235 TALLOC_FREE(req);
236 return NULL;
238 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
239 *psmbreq = subreq;
240 return req;
243 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
244 struct event_context *ev,
245 struct cli_state *cli)
247 struct tevent_req *req, *subreq;
248 NTSTATUS status;
250 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
251 if (req == NULL) {
252 return NULL;
255 status = cli_smb_req_send(subreq);
256 if (NT_STATUS_IS_OK(status)) {
257 tevent_req_nterror(req, status);
258 return tevent_req_post(req, ev);
260 return req;
263 static void cli_session_setup_guest_done(struct tevent_req *subreq)
265 struct tevent_req *req = tevent_req_callback_data(
266 subreq, struct tevent_req);
267 struct cli_session_setup_guest_state *state = tevent_req_data(
268 req, struct cli_session_setup_guest_state);
269 struct cli_state *cli = state->cli;
270 uint32_t num_bytes;
271 uint8_t *in;
272 char *inbuf;
273 uint8_t *bytes;
274 uint8_t *p;
275 NTSTATUS status;
277 status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
278 &num_bytes, &bytes);
279 TALLOC_FREE(subreq);
280 if (!NT_STATUS_IS_OK(status)) {
281 tevent_req_nterror(req, status);
282 return;
285 inbuf = (char *)in;
286 p = bytes;
288 cli->vuid = SVAL(inbuf, smb_uid);
290 p += clistr_pull(inbuf, cli->server_os, (char *)p, sizeof(fstring),
291 bytes+num_bytes-p, STR_TERMINATE);
292 p += clistr_pull(inbuf, cli->server_type, (char *)p, sizeof(fstring),
293 bytes+num_bytes-p, STR_TERMINATE);
294 p += clistr_pull(inbuf, cli->server_domain, (char *)p, sizeof(fstring),
295 bytes+num_bytes-p, STR_TERMINATE);
297 if (strstr(cli->server_type, "Samba")) {
298 cli->is_samba = True;
301 status = cli_set_username(cli, "");
302 if (!NT_STATUS_IS_OK(status)) {
303 tevent_req_nterror(req, status);
304 return;
306 tevent_req_done(req);
309 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
311 return tevent_req_simple_recv_ntstatus(req);
314 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
316 TALLOC_CTX *frame = talloc_stackframe();
317 struct event_context *ev;
318 struct tevent_req *req;
319 NTSTATUS status = NT_STATUS_OK;
321 if (cli_has_async_calls(cli)) {
323 * Can't use sync call while an async call is in flight
325 status = NT_STATUS_INVALID_PARAMETER;
326 goto fail;
329 ev = event_context_init(frame);
330 if (ev == NULL) {
331 status = NT_STATUS_NO_MEMORY;
332 goto fail;
335 req = cli_session_setup_guest_send(frame, ev, cli);
336 if (req == NULL) {
337 status = NT_STATUS_NO_MEMORY;
338 goto fail;
341 if (!tevent_req_poll(req, ev)) {
342 status = map_nt_error_from_unix(errno);
343 goto fail;
346 status = cli_session_setup_guest_recv(req);
347 fail:
348 TALLOC_FREE(frame);
349 if (!NT_STATUS_IS_OK(status)) {
350 cli_set_error(cli, status);
352 return status;
355 /****************************************************************************
356 Do a NT1 plaintext session setup.
357 ****************************************************************************/
359 static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
360 const char *user, const char *pass,
361 const char *workgroup)
363 uint32 capabilities = cli_session_setup_capabilities(cli);
364 char *p;
365 NTSTATUS status;
366 fstring lanman;
368 fstr_sprintf( lanman, "Samba %s", samba_version_string());
370 memset(cli->outbuf, '\0', smb_size);
371 cli_set_message(cli->outbuf,13,0,True);
372 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
373 cli_setup_packet(cli);
375 SCVAL(cli->outbuf,smb_vwv0,0xFF);
376 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
377 SSVAL(cli->outbuf,smb_vwv3,2);
378 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
379 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
380 SSVAL(cli->outbuf,smb_vwv8,0);
381 SIVAL(cli->outbuf,smb_vwv11,capabilities);
382 p = smb_buf(cli->outbuf);
384 /* check wether to send the ASCII or UNICODE version of the password */
386 if ( (capabilities & CAP_UNICODE) == 0 ) {
387 p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
388 SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
390 else {
391 /* For ucs2 passwords clistr_push calls ucs2_align, which causes
392 * the space taken by the unicode password to be one byte too
393 * long (as we're on an odd byte boundary here). Reduce the
394 * count by 1 to cope with this. Fixes smbclient against NetApp
395 * servers which can't cope. Fix from
396 * bryan.kolodziej@allenlund.com in bug #3840.
398 p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
399 SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))-1);
402 p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
403 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
404 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
405 p += clistr_push(cli, p, lanman, -1, STR_TERMINATE);
406 cli_setup_bcc(cli, p);
408 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
409 return cli_nt_error(cli);
412 show_msg(cli->inbuf);
414 if (cli_is_error(cli)) {
415 return cli_nt_error(cli);
418 cli->vuid = SVAL(cli->inbuf,smb_uid);
419 p = smb_buf(cli->inbuf);
420 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
421 -1, STR_TERMINATE);
422 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
423 -1, STR_TERMINATE);
424 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
425 -1, STR_TERMINATE);
426 status = cli_set_username(cli, user);
427 if (!NT_STATUS_IS_OK(status)) {
428 return status;
430 if (strstr(cli->server_type, "Samba")) {
431 cli->is_samba = True;
434 return NT_STATUS_OK;
437 /****************************************************************************
438 do a NT1 NTLM/LM encrypted session setup - for when extended security
439 is not negotiated.
440 @param cli client state to create do session setup on
441 @param user username
442 @param pass *either* cleartext password (passlen !=24) or LM response.
443 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
444 @param workgroup The user's domain.
445 ****************************************************************************/
447 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
448 const char *pass, size_t passlen,
449 const char *ntpass, size_t ntpasslen,
450 const char *workgroup)
452 uint32 capabilities = cli_session_setup_capabilities(cli);
453 DATA_BLOB lm_response = data_blob_null;
454 DATA_BLOB nt_response = data_blob_null;
455 DATA_BLOB session_key = data_blob_null;
456 NTSTATUS result;
457 char *p;
458 bool ok;
460 if (passlen == 0) {
461 /* do nothing - guest login */
462 } else if (passlen != 24) {
463 if (lp_client_ntlmv2_auth()) {
464 DATA_BLOB server_chal;
465 DATA_BLOB names_blob;
466 server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8));
468 /* note that the 'workgroup' here is a best guess - we don't know
469 the server's domain at this point. The 'server name' is also
470 dodgy...
472 names_blob = NTLMv2_generate_names_blob(NULL, cli->called.name, workgroup);
474 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass, &server_chal,
475 &names_blob,
476 &lm_response, &nt_response, NULL, &session_key)) {
477 data_blob_free(&names_blob);
478 data_blob_free(&server_chal);
479 return NT_STATUS_ACCESS_DENIED;
481 data_blob_free(&names_blob);
482 data_blob_free(&server_chal);
484 } else {
485 uchar nt_hash[16];
486 E_md4hash(pass, nt_hash);
488 #ifdef LANMAN_ONLY
489 nt_response = data_blob_null;
490 #else
491 nt_response = data_blob(NULL, 24);
492 SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
493 #endif
494 /* non encrypted password supplied. Ignore ntpass. */
495 if (lp_client_lanman_auth()) {
496 lm_response = data_blob(NULL, 24);
497 if (!SMBencrypt(pass,cli->secblob.data, lm_response.data)) {
498 /* Oops, the LM response is invalid, just put
499 the NT response there instead */
500 data_blob_free(&lm_response);
501 lm_response = data_blob(nt_response.data, nt_response.length);
503 } else {
504 /* LM disabled, place NT# in LM field instead */
505 lm_response = data_blob(nt_response.data, nt_response.length);
508 session_key = data_blob(NULL, 16);
509 #ifdef LANMAN_ONLY
510 E_deshash(pass, session_key.data);
511 memset(&session_key.data[8], '\0', 8);
512 #else
513 SMBsesskeygen_ntv1(nt_hash, session_key.data);
514 #endif
516 cli_temp_set_signing(cli);
517 } else {
518 /* pre-encrypted password supplied. Only used for
519 security=server, can't do
520 signing because we don't have original key */
522 lm_response = data_blob(pass, passlen);
523 nt_response = data_blob(ntpass, ntpasslen);
526 /* send a session setup command */
527 memset(cli->outbuf,'\0',smb_size);
529 cli_set_message(cli->outbuf,13,0,True);
530 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
531 cli_setup_packet(cli);
533 SCVAL(cli->outbuf,smb_vwv0,0xFF);
534 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
535 SSVAL(cli->outbuf,smb_vwv3,2);
536 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
537 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
538 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
539 SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
540 SIVAL(cli->outbuf,smb_vwv11,capabilities);
541 p = smb_buf(cli->outbuf);
542 if (lm_response.length) {
543 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
545 if (nt_response.length) {
546 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
548 p += clistr_push(cli, p, user, -1, STR_TERMINATE);
550 /* Upper case here might help some NTLMv2 implementations */
551 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
552 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
553 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
554 cli_setup_bcc(cli, p);
556 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
557 result = cli_nt_error(cli);
558 goto end;
561 /* show_msg(cli->inbuf); */
563 if (cli_is_error(cli)) {
564 result = cli_nt_error(cli);
565 goto end;
568 #ifdef LANMAN_ONLY
569 ok = cli_simple_set_signing(cli, session_key, lm_response);
570 #else
571 ok = cli_simple_set_signing(cli, session_key, nt_response);
572 #endif
573 if (ok) {
574 if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
575 result = NT_STATUS_ACCESS_DENIED;
576 goto end;
580 /* use the returned vuid from now on */
581 cli->vuid = SVAL(cli->inbuf,smb_uid);
583 p = smb_buf(cli->inbuf);
584 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
585 -1, STR_TERMINATE);
586 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
587 -1, STR_TERMINATE);
588 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
589 -1, STR_TERMINATE);
591 if (strstr(cli->server_type, "Samba")) {
592 cli->is_samba = True;
595 result = cli_set_username(cli, user);
596 if (!NT_STATUS_IS_OK(result)) {
597 goto end;
600 if (session_key.data) {
601 /* Have plaintext orginal */
602 cli_set_session_key(cli, session_key);
605 result = NT_STATUS_OK;
606 end:
607 data_blob_free(&lm_response);
608 data_blob_free(&nt_response);
609 data_blob_free(&session_key);
610 return result;
613 /* The following is calculated from :
614 * (smb_size-4) = 35
615 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
616 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
617 * end of packet.
620 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
622 struct cli_sesssetup_blob_state {
623 struct tevent_context *ev;
624 struct cli_state *cli;
625 DATA_BLOB blob;
626 uint16_t max_blob_size;
627 uint16_t vwv[12];
628 uint8_t *buf;
630 NTSTATUS status;
631 char *inbuf;
632 DATA_BLOB ret_blob;
635 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
636 struct tevent_req **psubreq);
637 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
639 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
640 struct tevent_context *ev,
641 struct cli_state *cli,
642 DATA_BLOB blob)
644 struct tevent_req *req, *subreq;
645 struct cli_sesssetup_blob_state *state;
647 req = tevent_req_create(mem_ctx, &state,
648 struct cli_sesssetup_blob_state);
649 if (req == NULL) {
650 return NULL;
652 state->ev = ev;
653 state->blob = blob;
654 state->cli = cli;
656 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
657 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
658 "(was %u, need minimum %u)\n",
659 (unsigned int)cli->max_xmit,
660 BASE_SESSSETUP_BLOB_PACKET_SIZE));
661 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
662 return tevent_req_post(req, ev);
664 state->max_blob_size =
665 MIN(cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE, 0xFFFF);
667 if (!cli_sesssetup_blob_next(state, &subreq)) {
668 tevent_req_nomem(NULL, req);
669 return tevent_req_post(req, ev);
671 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
672 return req;
675 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
676 struct tevent_req **psubreq)
678 struct tevent_req *subreq;
679 uint16_t thistime;
681 SCVAL(state->vwv+0, 0, 0xFF);
682 SCVAL(state->vwv+0, 1, 0);
683 SSVAL(state->vwv+1, 0, 0);
684 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
685 SSVAL(state->vwv+3, 0, 2);
686 SSVAL(state->vwv+4, 0, 1);
687 SIVAL(state->vwv+5, 0, 0);
689 thistime = MIN(state->blob.length, state->max_blob_size);
690 SSVAL(state->vwv+7, 0, thistime);
692 SSVAL(state->vwv+8, 0, 0);
693 SSVAL(state->vwv+9, 0, 0);
694 SIVAL(state->vwv+10, 0,
695 cli_session_setup_capabilities(state->cli)
696 | CAP_EXTENDED_SECURITY);
698 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
699 thistime);
700 if (state->buf == NULL) {
701 return false;
703 state->blob.data += thistime;
704 state->blob.length -= thistime;
706 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
707 "Unix", 5, NULL);
708 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
709 "Samba", 6, NULL);
710 if (state->buf == NULL) {
711 return false;
713 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
714 12, state->vwv,
715 talloc_get_size(state->buf), state->buf);
716 if (subreq == NULL) {
717 return false;
719 *psubreq = subreq;
720 return true;
723 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
725 struct tevent_req *req = tevent_req_callback_data(
726 subreq, struct tevent_req);
727 struct cli_sesssetup_blob_state *state = tevent_req_data(
728 req, struct cli_sesssetup_blob_state);
729 struct cli_state *cli = state->cli;
730 uint8_t wct;
731 uint16_t *vwv;
732 uint32_t num_bytes;
733 uint8_t *bytes;
734 NTSTATUS status;
735 uint8_t *p;
736 uint16_t blob_length;
737 uint8_t *inbuf;
739 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
740 &num_bytes, &bytes);
741 TALLOC_FREE(subreq);
742 if (!NT_STATUS_IS_OK(status)
743 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
744 tevent_req_nterror(req, status);
745 return;
748 state->status = status;
749 TALLOC_FREE(state->buf);
751 state->inbuf = (char *)inbuf;
752 cli->vuid = SVAL(state->inbuf, smb_uid);
754 blob_length = SVAL(vwv+3, 0);
755 if (blob_length > num_bytes) {
756 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
757 return;
759 state->ret_blob = data_blob_const(bytes, blob_length);
761 p = bytes + blob_length;
763 p += clistr_pull(state->inbuf, cli->server_os,
764 (char *)p, sizeof(fstring),
765 bytes+num_bytes-p, STR_TERMINATE);
766 p += clistr_pull(state->inbuf, cli->server_type,
767 (char *)p, sizeof(fstring),
768 bytes+num_bytes-p, STR_TERMINATE);
769 p += clistr_pull(state->inbuf, cli->server_domain,
770 (char *)p, sizeof(fstring),
771 bytes+num_bytes-p, STR_TERMINATE);
773 if (strstr(cli->server_type, "Samba")) {
774 cli->is_samba = True;
777 if (state->blob.length != 0) {
779 * More to send
781 if (!cli_sesssetup_blob_next(state, &subreq)) {
782 tevent_req_nomem(NULL, req);
783 return;
785 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
786 return;
788 tevent_req_done(req);
791 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
792 TALLOC_CTX *mem_ctx,
793 DATA_BLOB *pblob,
794 char **pinbuf)
796 struct cli_sesssetup_blob_state *state = tevent_req_data(
797 req, struct cli_sesssetup_blob_state);
798 NTSTATUS status;
799 char *inbuf;
801 if (tevent_req_is_nterror(req, &status)) {
802 state->cli->vuid = 0;
803 return status;
806 inbuf = talloc_move(mem_ctx, &state->inbuf);
807 if (pblob != NULL) {
808 *pblob = state->ret_blob;
810 if (pinbuf != NULL) {
811 *pinbuf = inbuf;
813 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
814 return state->status;
817 #ifdef HAVE_KRB5
819 /****************************************************************************
820 Use in-memory credentials cache
821 ****************************************************************************/
823 static void use_in_memory_ccache(void) {
824 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
827 /****************************************************************************
828 Do a spnego/kerberos encrypted session setup.
829 ****************************************************************************/
831 struct cli_session_setup_kerberos_state {
832 struct cli_state *cli;
833 DATA_BLOB negTokenTarg;
834 DATA_BLOB session_key_krb5;
835 ADS_STATUS ads_status;
838 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
840 static struct tevent_req *cli_session_setup_kerberos_send(
841 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
842 const char *principal, const char *workgroup)
844 struct tevent_req *req, *subreq;
845 struct cli_session_setup_kerberos_state *state;
846 int rc;
848 DEBUG(2,("Doing kerberos session setup\n"));
850 req = tevent_req_create(mem_ctx, &state,
851 struct cli_session_setup_kerberos_state);
852 if (req == NULL) {
853 return NULL;
855 state->cli = cli;
856 state->ads_status = ADS_SUCCESS;
858 cli_temp_set_signing(cli);
861 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
862 * we have to acquire a ticket. To be fixed later :-)
864 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
865 &state->session_key_krb5, 0, NULL);
866 if (rc) {
867 DEBUG(1, ("cli_session_setup_kerberos: "
868 "spnego_gen_krb5_negTokenInit failed: %s\n",
869 error_message(rc)));
870 state->ads_status = ADS_ERROR_KRB5(rc);
871 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
872 return tevent_req_post(req, ev);
875 #if 0
876 file_save("negTokenTarg.dat", state->negTokenTarg.data,
877 state->negTokenTarg.length);
878 #endif
880 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
881 if (tevent_req_nomem(subreq, req)) {
882 return tevent_req_post(req, ev);
884 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
885 return req;
888 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
890 struct tevent_req *req = tevent_req_callback_data(
891 subreq, struct tevent_req);
892 struct cli_session_setup_kerberos_state *state = tevent_req_data(
893 req, struct cli_session_setup_kerberos_state);
894 char *inbuf = NULL;
895 NTSTATUS status;
897 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), NULL, &inbuf);
898 if (!NT_STATUS_IS_OK(status)) {
899 TALLOC_FREE(subreq);
900 tevent_req_nterror(req, status);
901 return;
904 cli_set_session_key(state->cli, state->session_key_krb5);
906 if (cli_simple_set_signing(state->cli, state->session_key_krb5,
907 data_blob_null)
908 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
909 TALLOC_FREE(subreq);
910 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
911 return;
913 TALLOC_FREE(subreq);
914 tevent_req_done(req);
917 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
919 struct cli_session_setup_kerberos_state *state = tevent_req_data(
920 req, struct cli_session_setup_kerberos_state);
921 NTSTATUS status;
923 if (tevent_req_is_nterror(req, &status)) {
924 return ADS_ERROR_NT(status);
926 return state->ads_status;
929 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
930 const char *principal,
931 const char *workgroup)
933 struct tevent_context *ev;
934 struct tevent_req *req;
935 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
937 if (cli_has_async_calls(cli)) {
938 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
940 ev = tevent_context_init(talloc_tos());
941 if (ev == NULL) {
942 goto fail;
944 req = cli_session_setup_kerberos_send(ev, ev, cli, principal,
945 workgroup);
946 if (req == NULL) {
947 goto fail;
949 if (!tevent_req_poll(req, ev)) {
950 status = ADS_ERROR_SYSTEM(errno);
951 goto fail;
953 status = cli_session_setup_kerberos_recv(req);
954 fail:
955 TALLOC_FREE(ev);
956 return status;
958 #endif /* HAVE_KRB5 */
960 /****************************************************************************
961 Do a spnego/NTLMSSP encrypted session setup.
962 ****************************************************************************/
964 struct cli_session_setup_ntlmssp_state {
965 struct tevent_context *ev;
966 struct cli_state *cli;
967 struct ntlmssp_state *ntlmssp_state;
968 int turn;
969 DATA_BLOB blob_out;
972 static int cli_session_setup_ntlmssp_state_destructor(
973 struct cli_session_setup_ntlmssp_state *state)
975 if (state->ntlmssp_state != NULL) {
976 TALLOC_FREE(state->ntlmssp_state);
978 return 0;
981 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
983 static struct tevent_req *cli_session_setup_ntlmssp_send(
984 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
985 const char *user, const char *pass, const char *domain)
987 struct tevent_req *req, *subreq;
988 struct cli_session_setup_ntlmssp_state *state;
989 NTSTATUS status;
990 DATA_BLOB blob_out;
991 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
993 req = tevent_req_create(mem_ctx, &state,
994 struct cli_session_setup_ntlmssp_state);
995 if (req == NULL) {
996 return NULL;
998 state->ev = ev;
999 state->cli = cli;
1000 state->turn = 1;
1002 state->ntlmssp_state = NULL;
1003 talloc_set_destructor(
1004 state, cli_session_setup_ntlmssp_state_destructor);
1006 cli_temp_set_signing(cli);
1008 status = ntlmssp_client_start(state,
1009 global_myname(),
1010 lp_workgroup(),
1011 lp_client_ntlmv2_auth(),
1012 &state->ntlmssp_state);
1013 if (!NT_STATUS_IS_OK(status)) {
1014 goto fail;
1016 ntlmssp_want_feature(state->ntlmssp_state,
1017 NTLMSSP_FEATURE_SESSION_KEY);
1018 if (cli->use_ccache) {
1019 ntlmssp_want_feature(state->ntlmssp_state,
1020 NTLMSSP_FEATURE_CCACHE);
1022 status = ntlmssp_set_username(state->ntlmssp_state, user);
1023 if (!NT_STATUS_IS_OK(status)) {
1024 goto fail;
1026 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1027 if (!NT_STATUS_IS_OK(status)) {
1028 goto fail;
1030 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1031 if (!NT_STATUS_IS_OK(status)) {
1032 goto fail;
1034 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1035 &blob_out);
1036 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1037 goto fail;
1040 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1041 data_blob_free(&blob_out);
1043 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1044 if (tevent_req_nomem(subreq, req)) {
1045 return tevent_req_post(req, ev);
1047 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1048 return req;
1049 fail:
1050 tevent_req_nterror(req, status);
1051 return tevent_req_post(req, ev);
1054 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1056 struct tevent_req *req = tevent_req_callback_data(
1057 subreq, struct tevent_req);
1058 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1059 req, struct cli_session_setup_ntlmssp_state);
1060 DATA_BLOB blob_in, msg_in, blob_out;
1061 char *inbuf = NULL;
1062 bool parse_ret;
1063 NTSTATUS status;
1065 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1066 &inbuf);
1067 TALLOC_FREE(subreq);
1068 data_blob_free(&state->blob_out);
1070 if (NT_STATUS_IS_OK(status)) {
1071 if (state->cli->server_domain[0] == '\0') {
1072 fstrcpy(state->cli->server_domain,
1073 state->ntlmssp_state->server.netbios_domain);
1075 cli_set_session_key(
1076 state->cli, state->ntlmssp_state->session_key);
1078 if (cli_simple_set_signing(
1079 state->cli, state->ntlmssp_state->session_key,
1080 data_blob_null)
1081 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1082 TALLOC_FREE(subreq);
1083 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1084 return;
1086 TALLOC_FREE(subreq);
1087 TALLOC_FREE(state->ntlmssp_state);
1088 tevent_req_done(req);
1089 return;
1091 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1092 tevent_req_nterror(req, status);
1093 return;
1096 if (blob_in.length == 0) {
1097 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1098 return;
1101 if ((state->turn == 1)
1102 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1103 DATA_BLOB tmp_blob = data_blob_null;
1104 /* the server might give us back two challenges */
1105 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1106 &tmp_blob);
1107 data_blob_free(&tmp_blob);
1108 } else {
1109 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1110 OID_NTLMSSP, &msg_in);
1112 state->turn += 1;
1114 if (!parse_ret) {
1115 DEBUG(3,("Failed to parse auth response\n"));
1116 if (NT_STATUS_IS_OK(status)
1117 || NT_STATUS_EQUAL(status,
1118 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1119 tevent_req_nterror(
1120 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1121 return;
1125 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1127 if (!NT_STATUS_IS_OK(status)
1128 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1129 TALLOC_FREE(subreq);
1130 TALLOC_FREE(state->ntlmssp_state);
1131 tevent_req_nterror(req, status);
1132 return;
1135 state->blob_out = spnego_gen_auth(state, blob_out);
1136 TALLOC_FREE(subreq);
1137 if (tevent_req_nomem(state->blob_out.data, req)) {
1138 return;
1141 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1142 state->blob_out);
1143 if (tevent_req_nomem(subreq, req)) {
1144 return;
1146 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1149 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1151 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1152 req, struct cli_session_setup_ntlmssp_state);
1153 NTSTATUS status;
1155 if (tevent_req_is_nterror(req, &status)) {
1156 state->cli->vuid = 0;
1157 return status;
1159 return NT_STATUS_OK;
1162 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1163 const char *user,
1164 const char *pass,
1165 const char *domain)
1167 struct tevent_context *ev;
1168 struct tevent_req *req;
1169 NTSTATUS status = NT_STATUS_NO_MEMORY;
1171 if (cli_has_async_calls(cli)) {
1172 return NT_STATUS_INVALID_PARAMETER;
1174 ev = tevent_context_init(talloc_tos());
1175 if (ev == NULL) {
1176 goto fail;
1178 req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1179 if (req == NULL) {
1180 goto fail;
1182 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1183 goto fail;
1185 status = cli_session_setup_ntlmssp_recv(req);
1186 fail:
1187 TALLOC_FREE(ev);
1188 if (!NT_STATUS_IS_OK(status)) {
1189 cli_set_error(cli, status);
1191 return status;
1194 /****************************************************************************
1195 Do a spnego encrypted session setup.
1197 user_domain: The shortname of the domain the user/machine is a member of.
1198 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1199 ****************************************************************************/
1201 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
1202 const char *pass, const char *user_domain,
1203 const char * dest_realm)
1205 char *principal = NULL;
1206 char *OIDs[ASN1_MAX_OIDS];
1207 int i;
1208 DATA_BLOB blob;
1209 const char *p = NULL;
1210 char *account = NULL;
1211 NTSTATUS status;
1213 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
1215 /* the server might not even do spnego */
1216 if (cli->secblob.length <= 16) {
1217 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1218 goto ntlmssp;
1221 #if 0
1222 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1223 #endif
1225 /* there is 16 bytes of GUID before the real spnego packet starts */
1226 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1228 /* The server sent us the first part of the SPNEGO exchange in the
1229 * negprot reply. It is WRONG to depend on the principal sent in the
1230 * negprot reply, but right now we do it. If we don't receive one,
1231 * we try to best guess, then fall back to NTLM. */
1232 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1233 OIDs[0] == NULL) {
1234 data_blob_free(&blob);
1235 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1237 data_blob_free(&blob);
1239 /* make sure the server understands kerberos */
1240 for (i=0;OIDs[i];i++) {
1241 if (i == 0)
1242 DEBUG(3,("got OID=%s\n", OIDs[i]));
1243 else
1244 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1245 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1246 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1247 cli->got_kerberos_mechanism = True;
1249 talloc_free(OIDs[i]);
1252 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1254 status = cli_set_username(cli, user);
1255 if (!NT_STATUS_IS_OK(status)) {
1256 TALLOC_FREE(principal);
1257 return ADS_ERROR_NT(status);
1260 #ifdef HAVE_KRB5
1261 /* If password is set we reauthenticate to kerberos server
1262 * and do not store results */
1264 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1265 ADS_STATUS rc;
1267 if (pass && *pass) {
1268 int ret;
1270 use_in_memory_ccache();
1271 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1273 if (ret){
1274 TALLOC_FREE(principal);
1275 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1276 if (cli->fallback_after_kerberos)
1277 goto ntlmssp;
1278 return ADS_ERROR_KRB5(ret);
1282 /* If we get a bad principal, try to guess it if
1283 we have a valid host NetBIOS name.
1285 if (strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1286 TALLOC_FREE(principal);
1289 if (principal == NULL &&
1290 !is_ipaddress(cli->desthost) &&
1291 !strequal(STAR_SMBSERVER,
1292 cli->desthost)) {
1293 char *realm = NULL;
1294 char *machine = NULL;
1295 char *host = NULL;
1296 DEBUG(3,("cli_session_setup_spnego: got a "
1297 "bad server principal, trying to guess ...\n"));
1299 host = strchr_m(cli->desthost, '.');
1300 if (host) {
1301 /* We had a '.' in the name. */
1302 machine = SMB_STRNDUP(cli->desthost,
1303 host - cli->desthost);
1304 } else {
1305 machine = SMB_STRDUP(cli->desthost);
1307 if (machine == NULL) {
1308 TALLOC_FREE(principal);
1309 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1312 if (dest_realm) {
1313 realm = SMB_STRDUP(dest_realm);
1314 strupper_m(realm);
1315 } else {
1316 if (host) {
1317 /* DNS name. */
1318 realm = kerberos_get_realm_from_hostname(cli->desthost);
1319 } else {
1320 /* NetBIOS name - use our realm. */
1321 realm = kerberos_get_default_realm_from_ccache();
1325 if (realm && *realm) {
1326 if (host) {
1327 /* DNS name. */
1328 principal = talloc_asprintf(talloc_tos(),
1329 "cifs/%s@%s",
1330 cli->desthost,
1331 realm);
1332 } else {
1333 /* NetBIOS name, use machine account. */
1334 principal = talloc_asprintf(talloc_tos(),
1335 "%s$@%s",
1336 machine,
1337 realm);
1339 if (!principal) {
1340 SAFE_FREE(machine);
1341 SAFE_FREE(realm);
1342 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1344 DEBUG(3,("cli_session_setup_spnego: guessed "
1345 "server principal=%s\n",
1346 principal ? principal : "<null>"));
1348 SAFE_FREE(machine);
1349 SAFE_FREE(realm);
1352 if (principal) {
1353 rc = cli_session_setup_kerberos(cli, principal,
1354 dest_realm);
1355 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1356 TALLOC_FREE(principal);
1357 return rc;
1361 #endif
1363 TALLOC_FREE(principal);
1365 ntlmssp:
1367 account = talloc_strdup(talloc_tos(), user);
1368 if (!account) {
1369 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1372 /* when falling back to ntlmssp while authenticating with a machine
1373 * account strip off the realm - gd */
1375 if ((p = strchr_m(user, '@')) != NULL) {
1376 account[PTR_DIFF(p,user)] = '\0';
1379 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1382 /****************************************************************************
1383 Send a session setup. The username and workgroup is in UNIX character
1384 format and must be converted to DOS codepage format before sending. If the
1385 password is in plaintext, the same should be done.
1386 ****************************************************************************/
1388 NTSTATUS cli_session_setup(struct cli_state *cli,
1389 const char *user,
1390 const char *pass, int passlen,
1391 const char *ntpass, int ntpasslen,
1392 const char *workgroup)
1394 char *p;
1395 fstring user2;
1397 if (user) {
1398 fstrcpy(user2, user);
1399 } else {
1400 user2[0] ='\0';
1403 if (!workgroup) {
1404 workgroup = "";
1407 /* allow for workgroups as part of the username */
1408 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1409 (p=strchr_m(user2,*lp_winbind_separator()))) {
1410 *p = 0;
1411 user = p+1;
1412 workgroup = user2;
1415 if (cli->protocol < PROTOCOL_LANMAN1) {
1416 return NT_STATUS_OK;
1419 /* now work out what sort of session setup we are going to
1420 do. I have split this into separate functions to make the
1421 flow a bit easier to understand (tridge) */
1423 /* if its an older server then we have to use the older request format */
1425 if (cli->protocol < PROTOCOL_NT1) {
1426 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1427 DEBUG(1, ("Server requested LM password but 'client lanman auth'"
1428 " is disabled\n"));
1429 return NT_STATUS_ACCESS_DENIED;
1432 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1433 !lp_client_plaintext_auth() && (*pass)) {
1434 DEBUG(1, ("Server requested plaintext password but "
1435 "'client plaintext auth' is disabled\n"));
1436 return NT_STATUS_ACCESS_DENIED;
1439 return cli_session_setup_lanman2(cli, user, pass, passlen,
1440 workgroup);
1443 /* if no user is supplied then we have to do an anonymous connection.
1444 passwords are ignored */
1446 if (!user || !*user)
1447 return cli_session_setup_guest(cli);
1449 /* if the server is share level then send a plaintext null
1450 password at this point. The password is sent in the tree
1451 connect */
1453 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
1454 return cli_session_setup_plaintext(cli, user, "", workgroup);
1456 /* if the server doesn't support encryption then we have to use
1457 plaintext. The second password is ignored */
1459 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1460 if (!lp_client_plaintext_auth() && (*pass)) {
1461 DEBUG(1, ("Server requested plaintext password but "
1462 "'client plaintext auth' is disabled\n"));
1463 return NT_STATUS_ACCESS_DENIED;
1465 return cli_session_setup_plaintext(cli, user, pass, workgroup);
1468 /* if the server supports extended security then use SPNEGO */
1470 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
1471 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
1472 workgroup, NULL);
1473 if (!ADS_ERR_OK(status)) {
1474 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1475 return ads_ntstatus(status);
1477 } else {
1478 NTSTATUS status;
1480 /* otherwise do a NT1 style session setup */
1481 status = cli_session_setup_nt1(cli, user, pass, passlen,
1482 ntpass, ntpasslen, workgroup);
1483 if (!NT_STATUS_IS_OK(status)) {
1484 DEBUG(3,("cli_session_setup: NT1 session setup "
1485 "failed: %s\n", nt_errstr(status)));
1486 return status;
1490 if (strstr(cli->server_type, "Samba")) {
1491 cli->is_samba = True;
1494 return NT_STATUS_OK;
1497 /****************************************************************************
1498 Send a uloggoff.
1499 *****************************************************************************/
1501 struct cli_ulogoff_state {
1502 struct cli_state *cli;
1503 uint16_t vwv[3];
1506 static void cli_ulogoff_done(struct tevent_req *subreq);
1508 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1509 struct tevent_context *ev,
1510 struct cli_state *cli)
1512 struct tevent_req *req, *subreq;
1513 struct cli_ulogoff_state *state;
1515 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1516 if (req == NULL) {
1517 return NULL;
1519 state->cli = cli;
1521 SCVAL(state->vwv+0, 0, 0xFF);
1522 SCVAL(state->vwv+1, 0, 0);
1523 SSVAL(state->vwv+2, 0, 0);
1525 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
1526 0, NULL);
1527 if (tevent_req_nomem(subreq, req)) {
1528 return tevent_req_post(req, ev);
1530 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1531 return req;
1534 static void cli_ulogoff_done(struct tevent_req *subreq)
1536 struct tevent_req *req = tevent_req_callback_data(
1537 subreq, struct tevent_req);
1538 struct cli_ulogoff_state *state = tevent_req_data(
1539 req, struct cli_ulogoff_state);
1540 NTSTATUS status;
1542 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1543 if (!NT_STATUS_IS_OK(status)) {
1544 tevent_req_nterror(req, status);
1545 return;
1547 state->cli->vuid = -1;
1548 tevent_req_done(req);
1551 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1553 return tevent_req_simple_recv_ntstatus(req);
1556 NTSTATUS cli_ulogoff(struct cli_state *cli)
1558 struct tevent_context *ev;
1559 struct tevent_req *req;
1560 NTSTATUS status = NT_STATUS_NO_MEMORY;
1562 if (cli_has_async_calls(cli)) {
1563 return NT_STATUS_INVALID_PARAMETER;
1565 ev = tevent_context_init(talloc_tos());
1566 if (ev == NULL) {
1567 goto fail;
1569 req = cli_ulogoff_send(ev, ev, cli);
1570 if (req == NULL) {
1571 goto fail;
1573 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1574 goto fail;
1576 status = cli_ulogoff_recv(req);
1577 fail:
1578 TALLOC_FREE(ev);
1579 if (!NT_STATUS_IS_OK(status)) {
1580 cli_set_error(cli, status);
1582 return status;
1585 /****************************************************************************
1586 Send a tconX.
1587 ****************************************************************************/
1589 struct cli_tcon_andx_state {
1590 struct cli_state *cli;
1591 uint16_t vwv[4];
1592 struct iovec bytes;
1595 static void cli_tcon_andx_done(struct tevent_req *subreq);
1597 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1598 struct event_context *ev,
1599 struct cli_state *cli,
1600 const char *share, const char *dev,
1601 const char *pass, int passlen,
1602 struct tevent_req **psmbreq)
1604 struct tevent_req *req, *subreq;
1605 struct cli_tcon_andx_state *state;
1606 fstring pword;
1607 uint16_t *vwv;
1608 char *tmp = NULL;
1609 uint8_t *bytes;
1611 *psmbreq = NULL;
1613 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1614 if (req == NULL) {
1615 return NULL;
1617 state->cli = cli;
1618 vwv = state->vwv;
1620 fstrcpy(cli->share, share);
1622 /* in user level security don't send a password now */
1623 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1624 passlen = 1;
1625 pass = "";
1626 } else if (pass == NULL) {
1627 DEBUG(1, ("Server not using user level security and no "
1628 "password supplied.\n"));
1629 goto access_denied;
1632 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1633 *pass && passlen != 24) {
1634 if (!lp_client_lanman_auth()) {
1635 DEBUG(1, ("Server requested LANMAN password "
1636 "(share-level security) but "
1637 "'client lanman auth' is disabled\n"));
1638 goto access_denied;
1642 * Non-encrypted passwords - convert to DOS codepage before
1643 * encryption.
1645 passlen = 24;
1646 SMBencrypt(pass, cli->secblob.data, (uchar *)pword);
1647 } else {
1648 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1649 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1650 == 0) {
1651 if (!lp_client_plaintext_auth() && (*pass)) {
1652 DEBUG(1, ("Server requested plaintext "
1653 "password but 'client plaintext "
1654 "auth' is disabled\n"));
1655 goto access_denied;
1659 * Non-encrypted passwords - convert to DOS codepage
1660 * before using.
1662 passlen = clistr_push(cli, pword, pass, sizeof(pword),
1663 STR_TERMINATE);
1664 if (passlen == -1) {
1665 DEBUG(1, ("clistr_push(pword) failed\n"));
1666 goto access_denied;
1668 } else {
1669 if (passlen) {
1670 memcpy(pword, pass, passlen);
1675 SCVAL(vwv+0, 0, 0xFF);
1676 SCVAL(vwv+0, 1, 0);
1677 SSVAL(vwv+1, 0, 0);
1678 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
1679 SSVAL(vwv+3, 0, passlen);
1681 if (passlen) {
1682 bytes = (uint8_t *)talloc_memdup(state, pword, passlen);
1683 } else {
1684 bytes = talloc_array(state, uint8_t, 0);
1688 * Add the sharename
1690 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1691 cli->desthost, share);
1692 if (tmp == NULL) {
1693 TALLOC_FREE(req);
1694 return NULL;
1696 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
1697 NULL);
1698 TALLOC_FREE(tmp);
1701 * Add the devicetype
1703 tmp = talloc_strdup_upper(talloc_tos(), dev);
1704 if (tmp == NULL) {
1705 TALLOC_FREE(req);
1706 return NULL;
1708 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
1709 TALLOC_FREE(tmp);
1711 if (bytes == NULL) {
1712 TALLOC_FREE(req);
1713 return NULL;
1716 state->bytes.iov_base = (void *)bytes;
1717 state->bytes.iov_len = talloc_get_size(bytes);
1719 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
1720 1, &state->bytes);
1721 if (subreq == NULL) {
1722 TALLOC_FREE(req);
1723 return NULL;
1725 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
1726 *psmbreq = subreq;
1727 return req;
1729 access_denied:
1730 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1731 return tevent_req_post(req, ev);
1734 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
1735 struct event_context *ev,
1736 struct cli_state *cli,
1737 const char *share, const char *dev,
1738 const char *pass, int passlen)
1740 struct tevent_req *req, *subreq;
1741 NTSTATUS status;
1743 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
1744 &subreq);
1745 if (req == NULL) {
1746 return NULL;
1748 if (subreq == NULL) {
1749 return req;
1751 status = cli_smb_req_send(subreq);
1752 if (!NT_STATUS_IS_OK(status)) {
1753 tevent_req_nterror(req, status);
1754 return tevent_req_post(req, ev);
1756 return req;
1759 static void cli_tcon_andx_done(struct tevent_req *subreq)
1761 struct tevent_req *req = tevent_req_callback_data(
1762 subreq, struct tevent_req);
1763 struct cli_tcon_andx_state *state = tevent_req_data(
1764 req, struct cli_tcon_andx_state);
1765 struct cli_state *cli = state->cli;
1766 uint8_t *in;
1767 char *inbuf;
1768 uint8_t wct;
1769 uint16_t *vwv;
1770 uint32_t num_bytes;
1771 uint8_t *bytes;
1772 NTSTATUS status;
1774 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
1775 &num_bytes, &bytes);
1776 TALLOC_FREE(subreq);
1777 if (!NT_STATUS_IS_OK(status)) {
1778 tevent_req_nterror(req, status);
1779 return;
1782 inbuf = (char *)in;
1784 clistr_pull(inbuf, cli->dev, bytes, sizeof(fstring), num_bytes,
1785 STR_TERMINATE|STR_ASCII);
1787 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
1788 /* almost certainly win95 - enable bug fixes */
1789 cli->win95 = True;
1793 * Make sure that we have the optional support 16-bit field. WCT > 2.
1794 * Avoids issues when connecting to Win9x boxes sharing files
1797 cli->dfsroot = false;
1799 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
1800 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
1803 cli->cnum = SVAL(inbuf,smb_tid);
1804 tevent_req_done(req);
1807 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
1809 return tevent_req_simple_recv_ntstatus(req);
1812 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
1813 const char *dev, const char *pass, int passlen)
1815 TALLOC_CTX *frame = talloc_stackframe();
1816 struct event_context *ev;
1817 struct tevent_req *req;
1818 NTSTATUS status = NT_STATUS_OK;
1820 if (cli_has_async_calls(cli)) {
1822 * Can't use sync call while an async call is in flight
1824 status = NT_STATUS_INVALID_PARAMETER;
1825 goto fail;
1828 ev = event_context_init(frame);
1829 if (ev == NULL) {
1830 status = NT_STATUS_NO_MEMORY;
1831 goto fail;
1834 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
1835 if (req == NULL) {
1836 status = NT_STATUS_NO_MEMORY;
1837 goto fail;
1840 if (!tevent_req_poll(req, ev)) {
1841 status = map_nt_error_from_unix(errno);
1842 goto fail;
1845 status = cli_tcon_andx_recv(req);
1846 fail:
1847 TALLOC_FREE(frame);
1848 if (!NT_STATUS_IS_OK(status)) {
1849 cli_set_error(cli, status);
1851 return status;
1854 /****************************************************************************
1855 Send a tree disconnect.
1856 ****************************************************************************/
1858 struct cli_tdis_state {
1859 struct cli_state *cli;
1862 static void cli_tdis_done(struct tevent_req *subreq);
1864 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
1865 struct tevent_context *ev,
1866 struct cli_state *cli)
1868 struct tevent_req *req, *subreq;
1869 struct cli_tdis_state *state;
1871 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
1872 if (req == NULL) {
1873 return NULL;
1875 state->cli = cli;
1877 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
1878 if (tevent_req_nomem(subreq, req)) {
1879 return tevent_req_post(req, ev);
1881 tevent_req_set_callback(subreq, cli_tdis_done, req);
1882 return req;
1885 static void cli_tdis_done(struct tevent_req *subreq)
1887 struct tevent_req *req = tevent_req_callback_data(
1888 subreq, struct tevent_req);
1889 struct cli_tdis_state *state = tevent_req_data(
1890 req, struct cli_tdis_state);
1891 NTSTATUS status;
1893 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1894 TALLOC_FREE(subreq);
1895 if (!NT_STATUS_IS_OK(status)) {
1896 tevent_req_nterror(req, status);
1897 return;
1899 state->cli->cnum = -1;
1900 tevent_req_done(req);
1903 NTSTATUS cli_tdis_recv(struct tevent_req *req)
1905 return tevent_req_simple_recv_ntstatus(req);
1908 NTSTATUS cli_tdis(struct cli_state *cli)
1910 struct tevent_context *ev;
1911 struct tevent_req *req;
1912 NTSTATUS status = NT_STATUS_NO_MEMORY;
1914 if (cli_has_async_calls(cli)) {
1915 return NT_STATUS_INVALID_PARAMETER;
1917 ev = tevent_context_init(talloc_tos());
1918 if (ev == NULL) {
1919 goto fail;
1921 req = cli_tdis_send(ev, ev, cli);
1922 if (req == NULL) {
1923 goto fail;
1925 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1926 goto fail;
1928 status = cli_tdis_recv(req);
1929 fail:
1930 TALLOC_FREE(ev);
1931 if (!NT_STATUS_IS_OK(status)) {
1932 cli_set_error(cli, status);
1934 return status;
1937 /****************************************************************************
1938 Send a negprot command.
1939 ****************************************************************************/
1941 void cli_negprot_sendsync(struct cli_state *cli)
1943 char *p;
1944 int numprots;
1946 if (cli->protocol < PROTOCOL_NT1)
1947 cli->use_spnego = False;
1949 memset(cli->outbuf,'\0',smb_size);
1951 /* setup the protocol strings */
1952 cli_set_message(cli->outbuf,0,0,True);
1954 p = smb_buf(cli->outbuf);
1955 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1956 if (prots[numprots].prot > cli->protocol) {
1957 break;
1959 *p++ = 2;
1960 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1963 SCVAL(cli->outbuf,smb_com,SMBnegprot);
1964 cli_setup_bcc(cli, p);
1965 cli_setup_packet(cli);
1967 SCVAL(smb_buf(cli->outbuf),0,2);
1969 cli_send_smb(cli);
1972 /****************************************************************************
1973 Send a negprot command.
1974 ****************************************************************************/
1976 struct cli_negprot_state {
1977 struct cli_state *cli;
1980 static void cli_negprot_done(struct tevent_req *subreq);
1982 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
1983 struct event_context *ev,
1984 struct cli_state *cli)
1986 struct tevent_req *req, *subreq;
1987 struct cli_negprot_state *state;
1988 uint8_t *bytes = NULL;
1989 int numprots;
1990 uint16_t cnum;
1992 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
1993 if (req == NULL) {
1994 return NULL;
1996 state->cli = cli;
1998 if (cli->protocol < PROTOCOL_NT1)
1999 cli->use_spnego = False;
2001 /* setup the protocol strings */
2002 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
2003 uint8_t c = 2;
2004 if (prots[numprots].prot > cli->protocol) {
2005 break;
2007 bytes = (uint8_t *)talloc_append_blob(
2008 state, bytes, data_blob_const(&c, sizeof(c)));
2009 if (tevent_req_nomem(bytes, req)) {
2010 return tevent_req_post(req, ev);
2012 bytes = smb_bytes_push_str(bytes, false,
2013 prots[numprots].name,
2014 strlen(prots[numprots].name)+1,
2015 NULL);
2016 if (tevent_req_nomem(bytes, req)) {
2017 return tevent_req_post(req, ev);
2021 cnum = cli->cnum;
2023 cli->cnum = 0;
2024 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2025 talloc_get_size(bytes), bytes);
2026 cli->cnum = cnum;
2028 if (tevent_req_nomem(subreq, req)) {
2029 return tevent_req_post(req, ev);
2031 tevent_req_set_callback(subreq, cli_negprot_done, req);
2032 return req;
2035 static void cli_negprot_done(struct tevent_req *subreq)
2037 struct tevent_req *req = tevent_req_callback_data(
2038 subreq, struct tevent_req);
2039 struct cli_negprot_state *state = tevent_req_data(
2040 req, struct cli_negprot_state);
2041 struct cli_state *cli = state->cli;
2042 uint8_t wct;
2043 uint16_t *vwv;
2044 uint32_t num_bytes;
2045 uint8_t *bytes;
2046 NTSTATUS status;
2047 uint16_t protnum;
2048 uint8_t *inbuf;
2050 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
2051 &num_bytes, &bytes);
2052 TALLOC_FREE(subreq);
2053 if (!NT_STATUS_IS_OK(status)) {
2054 tevent_req_nterror(req, status);
2055 return;
2058 protnum = SVAL(vwv, 0);
2060 if ((protnum >= ARRAY_SIZE(prots))
2061 || (prots[protnum].prot > cli->protocol)) {
2062 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2063 return;
2066 cli->protocol = prots[protnum].prot;
2068 if ((cli->protocol < PROTOCOL_NT1) &&
2069 client_is_signing_mandatory(cli)) {
2070 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2071 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2072 return;
2075 if (cli->protocol >= PROTOCOL_NT1) {
2076 struct timespec ts;
2077 bool negotiated_smb_signing = false;
2079 /* NT protocol */
2080 cli->sec_mode = CVAL(vwv + 1, 0);
2081 cli->max_mux = SVAL(vwv + 1, 1);
2082 cli->max_xmit = IVAL(vwv + 3, 1);
2083 cli->sesskey = IVAL(vwv + 7, 1);
2084 cli->serverzone = SVALS(vwv + 15, 1);
2085 cli->serverzone *= 60;
2086 /* this time arrives in real GMT */
2087 ts = interpret_long_date(((char *)(vwv+11))+1);
2088 cli->servertime = ts.tv_sec;
2089 cli->secblob = data_blob(bytes, num_bytes);
2090 cli->capabilities = IVAL(vwv + 9, 1);
2091 if (cli->capabilities & CAP_RAW_MODE) {
2092 cli->readbraw_supported = True;
2093 cli->writebraw_supported = True;
2095 /* work out if they sent us a workgroup */
2096 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
2097 smb_buflen(cli->inbuf) > 8) {
2098 clistr_pull(cli->inbuf, cli->server_domain,
2099 bytes+8, sizeof(cli->server_domain),
2100 num_bytes-8,
2101 STR_UNICODE|STR_NOALIGN);
2105 * As signing is slow we only turn it on if either the client or
2106 * the server require it. JRA.
2109 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2110 /* Fail if server says signing is mandatory and we don't want to support it. */
2111 if (!client_is_signing_allowed(cli)) {
2112 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
2113 tevent_req_nterror(req,
2114 NT_STATUS_ACCESS_DENIED);
2115 return;
2117 negotiated_smb_signing = true;
2118 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
2119 /* Fail if client says signing is mandatory and the server doesn't support it. */
2120 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
2121 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
2122 tevent_req_nterror(req,
2123 NT_STATUS_ACCESS_DENIED);
2124 return;
2126 negotiated_smb_signing = true;
2127 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2128 negotiated_smb_signing = true;
2131 if (negotiated_smb_signing) {
2132 cli_set_signing_negotiated(cli);
2135 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
2136 SAFE_FREE(cli->outbuf);
2137 SAFE_FREE(cli->inbuf);
2138 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2139 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2140 if (!cli->outbuf || !cli->inbuf) {
2141 tevent_req_nterror(req,
2142 NT_STATUS_NO_MEMORY);
2143 return;
2145 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
2148 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2149 cli->use_spnego = False;
2150 cli->sec_mode = SVAL(vwv + 1, 0);
2151 cli->max_xmit = SVAL(vwv + 2, 0);
2152 cli->max_mux = SVAL(vwv + 3, 0);
2153 cli->sesskey = IVAL(vwv + 6, 0);
2154 cli->serverzone = SVALS(vwv + 10, 0);
2155 cli->serverzone *= 60;
2156 /* this time is converted to GMT by make_unix_date */
2157 cli->servertime = make_unix_date(
2158 (char *)(vwv + 8), cli->serverzone);
2159 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2160 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2161 cli->secblob = data_blob(bytes, num_bytes);
2162 } else {
2163 /* the old core protocol */
2164 cli->use_spnego = False;
2165 cli->sec_mode = 0;
2166 cli->serverzone = get_time_zone(time(NULL));
2169 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2171 /* a way to force ascii SMB */
2172 if (getenv("CLI_FORCE_ASCII"))
2173 cli->capabilities &= ~CAP_UNICODE;
2175 tevent_req_done(req);
2178 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2180 return tevent_req_simple_recv_ntstatus(req);
2183 NTSTATUS cli_negprot(struct cli_state *cli)
2185 TALLOC_CTX *frame = talloc_stackframe();
2186 struct event_context *ev;
2187 struct tevent_req *req;
2188 NTSTATUS status = NT_STATUS_OK;
2190 if (cli_has_async_calls(cli)) {
2192 * Can't use sync call while an async call is in flight
2194 status = NT_STATUS_INVALID_PARAMETER;
2195 goto fail;
2198 ev = event_context_init(frame);
2199 if (ev == NULL) {
2200 status = NT_STATUS_NO_MEMORY;
2201 goto fail;
2204 req = cli_negprot_send(frame, ev, cli);
2205 if (req == NULL) {
2206 status = NT_STATUS_NO_MEMORY;
2207 goto fail;
2210 if (!tevent_req_poll(req, ev)) {
2211 status = map_nt_error_from_unix(errno);
2212 goto fail;
2215 status = cli_negprot_recv(req);
2216 fail:
2217 TALLOC_FREE(frame);
2218 if (!NT_STATUS_IS_OK(status)) {
2219 cli_set_error(cli, status);
2221 return status;
2224 /****************************************************************************
2225 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
2226 ****************************************************************************/
2228 bool cli_session_request(struct cli_state *cli,
2229 struct nmb_name *calling, struct nmb_name *called)
2231 char *p;
2232 int len = 4;
2233 int namelen = 0;
2234 char *tmp;
2236 /* 445 doesn't have session request */
2237 if (cli->port == 445)
2238 return True;
2240 memcpy(&(cli->calling), calling, sizeof(*calling));
2241 memcpy(&(cli->called ), called , sizeof(*called ));
2243 /* put in the destination name */
2245 tmp = name_mangle(talloc_tos(), cli->called.name,
2246 cli->called.name_type);
2247 if (tmp == NULL) {
2248 return false;
2251 p = cli->outbuf+len;
2252 namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
2253 if (namelen > 0) {
2254 memcpy(p, tmp, namelen);
2255 len += namelen;
2257 TALLOC_FREE(tmp);
2259 /* and my name */
2261 tmp = name_mangle(talloc_tos(), cli->calling.name,
2262 cli->calling.name_type);
2263 if (tmp == NULL) {
2264 return false;
2267 p = cli->outbuf+len;
2268 namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
2269 if (namelen > 0) {
2270 memcpy(p, tmp, namelen);
2271 len += namelen;
2273 TALLOC_FREE(tmp);
2275 /* send a session request (RFC 1002) */
2276 /* setup the packet length
2277 * Remove four bytes from the length count, since the length
2278 * field in the NBT Session Service header counts the number
2279 * of bytes which follow. The cli_send_smb() function knows
2280 * about this and accounts for those four bytes.
2281 * CRH.
2283 len -= 4;
2284 _smb_setlen(cli->outbuf,len);
2285 SCVAL(cli->outbuf,0,0x81);
2287 cli_send_smb(cli);
2288 DEBUG(5,("Sent session request\n"));
2290 if (!cli_receive_smb(cli))
2291 return False;
2293 if (CVAL(cli->inbuf,0) == 0x84) {
2294 /* C. Hoch 9/14/95 Start */
2295 /* For information, here is the response structure.
2296 * We do the byte-twiddling to for portability.
2297 struct RetargetResponse{
2298 unsigned char type;
2299 unsigned char flags;
2300 int16 length;
2301 int32 ip_addr;
2302 int16 port;
2305 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
2306 struct in_addr dest_ip;
2307 NTSTATUS status;
2309 /* SESSION RETARGET */
2310 putip((char *)&dest_ip,cli->inbuf+4);
2311 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
2313 status = open_socket_out(&cli->dest_ss, port,
2314 LONG_CONNECT_TIMEOUT, &cli->fd);
2315 if (!NT_STATUS_IS_OK(status)) {
2316 return False;
2319 DEBUG(3,("Retargeted\n"));
2321 set_socket_options(cli->fd, lp_socket_options());
2323 /* Try again */
2325 static int depth;
2326 bool ret;
2327 if (depth > 4) {
2328 DEBUG(0,("Retarget recursion - failing\n"));
2329 return False;
2331 depth++;
2332 ret = cli_session_request(cli, calling, called);
2333 depth--;
2334 return ret;
2336 } /* C. Hoch 9/14/95 End */
2338 if (CVAL(cli->inbuf,0) != 0x82) {
2339 /* This is the wrong place to put the error... JRA. */
2340 cli->rap_error = CVAL(cli->inbuf,4);
2341 return False;
2343 return(True);
2346 struct fd_struct {
2347 int fd;
2350 static void smb_sock_connected(struct tevent_req *req)
2352 struct fd_struct *pfd = tevent_req_callback_data(
2353 req, struct fd_struct);
2354 int fd;
2355 NTSTATUS status;
2357 status = open_socket_out_defer_recv(req, &fd);
2358 if (NT_STATUS_IS_OK(status)) {
2359 pfd->fd = fd;
2363 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
2364 uint16_t *port, int timeout, int *pfd)
2366 struct event_context *ev;
2367 struct tevent_req *r139, *r445;
2368 struct fd_struct *fd139, *fd445;
2369 NTSTATUS status = NT_STATUS_NO_MEMORY;
2371 if (*port != 0) {
2372 return open_socket_out(pss, *port, timeout, pfd);
2375 ev = event_context_init(talloc_tos());
2376 if (ev == NULL) {
2377 return NT_STATUS_NO_MEMORY;
2380 fd139 = talloc(ev, struct fd_struct);
2381 if (fd139 == NULL) {
2382 goto done;
2384 fd139->fd = -1;
2386 fd445 = talloc(ev, struct fd_struct);
2387 if (fd445 == NULL) {
2388 goto done;
2390 fd445->fd = -1;
2392 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
2393 pss, 445, timeout);
2394 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
2395 pss, 139, timeout);
2396 if ((r445 == NULL) || (r139 == NULL)) {
2397 goto done;
2399 tevent_req_set_callback(r445, smb_sock_connected, fd445);
2400 tevent_req_set_callback(r139, smb_sock_connected, fd139);
2402 while ((fd445->fd == -1) && (fd139->fd == -1)
2403 && (tevent_req_is_in_progress(r139)
2404 || tevent_req_is_in_progress(r445))) {
2405 event_loop_once(ev);
2408 if ((fd139->fd != -1) && (fd445->fd != -1)) {
2409 close(fd139->fd);
2410 fd139->fd = -1;
2413 if (fd445->fd != -1) {
2414 *port = 445;
2415 *pfd = fd445->fd;
2416 status = NT_STATUS_OK;
2417 goto done;
2419 if (fd139->fd != -1) {
2420 *port = 139;
2421 *pfd = fd139->fd;
2422 status = NT_STATUS_OK;
2423 goto done;
2426 status = open_socket_out_defer_recv(r445, &fd445->fd);
2427 done:
2428 TALLOC_FREE(ev);
2429 return status;
2432 /****************************************************************************
2433 Open the client sockets.
2434 ****************************************************************************/
2436 NTSTATUS cli_connect(struct cli_state *cli,
2437 const char *host,
2438 struct sockaddr_storage *dest_ss)
2441 int name_type = 0x20;
2442 TALLOC_CTX *frame = talloc_stackframe();
2443 unsigned int num_addrs = 0;
2444 unsigned int i = 0;
2445 struct sockaddr_storage *ss_arr = NULL;
2446 char *p = NULL;
2448 /* reasonable default hostname */
2449 if (!host) {
2450 host = STAR_SMBSERVER;
2453 fstrcpy(cli->desthost, host);
2455 /* allow hostnames of the form NAME#xx and do a netbios lookup */
2456 if ((p = strchr(cli->desthost, '#'))) {
2457 name_type = strtol(p+1, NULL, 16);
2458 *p = 0;
2461 if (!dest_ss || is_zero_addr((struct sockaddr *)dest_ss)) {
2462 NTSTATUS status =resolve_name_list(frame,
2463 cli->desthost,
2464 name_type,
2465 &ss_arr,
2466 &num_addrs);
2467 if (!NT_STATUS_IS_OK(status)) {
2468 TALLOC_FREE(frame);
2469 return NT_STATUS_BAD_NETWORK_NAME;
2471 } else {
2472 num_addrs = 1;
2473 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
2474 if (!ss_arr) {
2475 TALLOC_FREE(frame);
2476 return NT_STATUS_NO_MEMORY;
2478 *ss_arr = *dest_ss;
2481 for (i = 0; i < num_addrs; i++) {
2482 cli->dest_ss = ss_arr[i];
2483 if (getenv("LIBSMB_PROG")) {
2484 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
2485 } else {
2486 uint16_t port = cli->port;
2487 NTSTATUS status;
2488 status = open_smb_socket(&cli->dest_ss, &port,
2489 cli->timeout, &cli->fd);
2490 if (NT_STATUS_IS_OK(status)) {
2491 cli->port = port;
2494 if (cli->fd == -1) {
2495 char addr[INET6_ADDRSTRLEN];
2496 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
2497 DEBUG(2,("Error connecting to %s (%s)\n",
2498 dest_ss?addr:host,strerror(errno)));
2499 } else {
2500 /* Exit from loop on first connection. */
2501 break;
2505 if (cli->fd == -1) {
2506 TALLOC_FREE(frame);
2507 return map_nt_error_from_unix(errno);
2510 if (dest_ss) {
2511 *dest_ss = cli->dest_ss;
2514 set_socket_options(cli->fd, lp_socket_options());
2516 TALLOC_FREE(frame);
2517 return NT_STATUS_OK;
2521 establishes a connection to after the negprot.
2522 @param output_cli A fully initialised cli structure, non-null only on success
2523 @param dest_host The netbios name of the remote host
2524 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2525 @param port (optional) The destination port (0 for default)
2526 @param retry bool. Did this connection fail with a retryable error ?
2529 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2530 const char *my_name,
2531 const char *dest_host,
2532 struct sockaddr_storage *dest_ss, int port,
2533 int signing_state, int flags,
2534 bool *retry)
2536 NTSTATUS nt_status;
2537 struct nmb_name calling;
2538 struct nmb_name called;
2539 struct cli_state *cli;
2540 struct sockaddr_storage ss;
2542 if (retry)
2543 *retry = False;
2545 if (!my_name)
2546 my_name = global_myname();
2548 if (!(cli = cli_initialise_ex(signing_state))) {
2549 return NT_STATUS_NO_MEMORY;
2552 make_nmb_name(&calling, my_name, 0x0);
2553 make_nmb_name(&called , dest_host, 0x20);
2555 cli_set_port(cli, port);
2556 cli_set_timeout(cli, 10000); /* 10 seconds. */
2558 if (dest_ss) {
2559 ss = *dest_ss;
2560 } else {
2561 zero_sockaddr(&ss);
2564 again:
2566 DEBUG(3,("Connecting to host=%s\n", dest_host));
2568 nt_status = cli_connect(cli, dest_host, &ss);
2569 if (!NT_STATUS_IS_OK(nt_status)) {
2570 char addr[INET6_ADDRSTRLEN];
2571 print_sockaddr(addr, sizeof(addr), &ss);
2572 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
2573 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
2574 cli_shutdown(cli);
2575 return nt_status;
2578 if (retry)
2579 *retry = True;
2581 if (!cli_session_request(cli, &calling, &called)) {
2582 char *p;
2583 DEBUG(1,("session request to %s failed (%s)\n",
2584 called.name, cli_errstr(cli)));
2585 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
2586 *p = 0;
2587 goto again;
2589 if (strcmp(called.name, STAR_SMBSERVER)) {
2590 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
2591 goto again;
2593 return NT_STATUS_BAD_NETWORK_NAME;
2596 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
2597 cli->use_spnego = False;
2598 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
2599 cli->use_kerberos = True;
2601 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
2602 cli->use_kerberos) {
2603 cli->fallback_after_kerberos = true;
2605 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
2606 cli->use_ccache = true;
2609 nt_status = cli_negprot(cli);
2610 if (!NT_STATUS_IS_OK(nt_status)) {
2611 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2612 cli_shutdown(cli);
2613 return nt_status;
2616 *output_cli = cli;
2617 return NT_STATUS_OK;
2622 establishes a connection right up to doing tconX, password specified.
2623 @param output_cli A fully initialised cli structure, non-null only on success
2624 @param dest_host The netbios name of the remote host
2625 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2626 @param port (optional) The destination port (0 for default)
2627 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2628 @param service_type The 'type' of serivice.
2629 @param user Username, unix string
2630 @param domain User's domain
2631 @param password User's password, unencrypted unix string.
2632 @param retry bool. Did this connection fail with a retryable error ?
2635 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2636 const char *my_name,
2637 const char *dest_host,
2638 struct sockaddr_storage *dest_ss, int port,
2639 const char *service, const char *service_type,
2640 const char *user, const char *domain,
2641 const char *password, int flags,
2642 int signing_state,
2643 bool *retry)
2645 NTSTATUS nt_status;
2646 struct cli_state *cli = NULL;
2647 int pw_len = password ? strlen(password)+1 : 0;
2649 *output_cli = NULL;
2651 if (password == NULL) {
2652 password = "";
2655 nt_status = cli_start_connection(&cli, my_name, dest_host,
2656 dest_ss, port, signing_state,
2657 flags, retry);
2659 if (!NT_STATUS_IS_OK(nt_status)) {
2660 return nt_status;
2663 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
2664 cli->use_level_II_oplocks =
2665 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
2667 nt_status = cli_session_setup(cli, user, password, pw_len, password,
2668 pw_len, domain);
2669 if (!NT_STATUS_IS_OK(nt_status)) {
2671 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2672 DEBUG(1,("failed session setup with %s\n",
2673 nt_errstr(nt_status)));
2674 cli_shutdown(cli);
2675 return nt_status;
2678 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2679 if (!NT_STATUS_IS_OK(nt_status)) {
2680 DEBUG(1,("anonymous failed session setup with %s\n",
2681 nt_errstr(nt_status)));
2682 cli_shutdown(cli);
2683 return nt_status;
2687 if (service) {
2688 nt_status = cli_tcon_andx(cli, service, service_type, password,
2689 pw_len);
2690 if (!NT_STATUS_IS_OK(nt_status)) {
2691 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2692 cli_shutdown(cli);
2693 if (NT_STATUS_IS_OK(nt_status)) {
2694 nt_status = NT_STATUS_UNSUCCESSFUL;
2696 return nt_status;
2700 nt_status = cli_init_creds(cli, user, domain, password);
2701 if (!NT_STATUS_IS_OK(nt_status)) {
2702 cli_shutdown(cli);
2703 return nt_status;
2706 *output_cli = cli;
2707 return NT_STATUS_OK;
2710 /****************************************************************************
2711 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2712 ****************************************************************************/
2714 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
2715 struct sockaddr_storage *pdest_ss)
2717 struct nmb_name calling, called;
2719 make_nmb_name(&calling, srchost, 0x0);
2722 * If the called name is an IP address
2723 * then use *SMBSERVER immediately.
2726 if(is_ipaddress(desthost)) {
2727 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
2728 } else {
2729 make_nmb_name(&called, desthost, 0x20);
2732 if (!cli_session_request(*ppcli, &calling, &called)) {
2733 NTSTATUS status;
2734 struct nmb_name smbservername;
2736 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
2739 * If the name wasn't *SMBSERVER then
2740 * try with *SMBSERVER if the first name fails.
2743 if (nmb_name_equal(&called, &smbservername)) {
2746 * The name used was *SMBSERVER, don't bother with another name.
2749 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2750 with error %s.\n", desthost, cli_errstr(*ppcli) ));
2751 return False;
2754 /* Try again... */
2755 cli_shutdown(*ppcli);
2757 *ppcli = cli_initialise();
2758 if (!*ppcli) {
2759 /* Out of memory... */
2760 return False;
2763 status = cli_connect(*ppcli, desthost, pdest_ss);
2764 if (!NT_STATUS_IS_OK(status) ||
2765 !cli_session_request(*ppcli, &calling, &smbservername)) {
2766 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2767 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
2768 return False;
2772 return True;
2775 /****************************************************************************
2776 Send an old style tcon.
2777 ****************************************************************************/
2778 NTSTATUS cli_raw_tcon(struct cli_state *cli,
2779 const char *service, const char *pass, const char *dev,
2780 uint16 *max_xmit, uint16 *tid)
2782 char *p;
2784 if (!lp_client_plaintext_auth() && (*pass)) {
2785 DEBUG(1, ("Server requested plaintext password but 'client "
2786 "plaintext auth' is disabled\n"));
2787 return NT_STATUS_ACCESS_DENIED;
2790 memset(cli->outbuf,'\0',smb_size);
2791 memset(cli->inbuf,'\0',smb_size);
2793 cli_set_message(cli->outbuf, 0, 0, True);
2794 SCVAL(cli->outbuf,smb_com,SMBtcon);
2795 cli_setup_packet(cli);
2797 p = smb_buf(cli->outbuf);
2798 *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
2799 *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
2800 *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
2802 cli_setup_bcc(cli, p);
2804 cli_send_smb(cli);
2805 if (!cli_receive_smb(cli)) {
2806 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2809 if (cli_is_error(cli)) {
2810 return cli_nt_error(cli);
2813 *max_xmit = SVAL(cli->inbuf, smb_vwv0);
2814 *tid = SVAL(cli->inbuf, smb_vwv1);
2816 return NT_STATUS_OK;
2819 /* Return a cli_state pointing at the IPC$ share for the given server */
2821 struct cli_state *get_ipc_connect(char *server,
2822 struct sockaddr_storage *server_ss,
2823 const struct user_auth_info *user_info)
2825 struct cli_state *cli;
2826 NTSTATUS nt_status;
2827 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2829 if (user_info->use_kerberos) {
2830 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2833 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
2834 user_info->username ? user_info->username : "",
2835 lp_workgroup(),
2836 user_info->password ? user_info->password : "",
2837 flags,
2838 Undefined, NULL);
2840 if (NT_STATUS_IS_OK(nt_status)) {
2841 return cli;
2842 } else if (is_ipaddress(server)) {
2843 /* windows 9* needs a correct NMB name for connections */
2844 fstring remote_name;
2846 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2847 cli = get_ipc_connect(remote_name, server_ss, user_info);
2848 if (cli)
2849 return cli;
2852 return NULL;
2856 * Given the IP address of a master browser on the network, return its
2857 * workgroup and connect to it.
2859 * This function is provided to allow additional processing beyond what
2860 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2861 * browsers and obtain each master browsers' list of domains (in case the
2862 * first master browser is recently on the network and has not yet
2863 * synchronized with other master browsers and therefore does not yet have the
2864 * entire network browse list)
2867 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2868 struct ip_service *mb_ip,
2869 const struct user_auth_info *user_info,
2870 char **pp_workgroup_out)
2872 char addr[INET6_ADDRSTRLEN];
2873 fstring name;
2874 struct cli_state *cli;
2875 struct sockaddr_storage server_ss;
2877 *pp_workgroup_out = NULL;
2879 print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2880 DEBUG(99, ("Looking up name of master browser %s\n",
2881 addr));
2884 * Do a name status query to find out the name of the master browser.
2885 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2886 * master browser will not respond to a wildcard query (or, at least,
2887 * an NT4 server acting as the domain master browser will not).
2889 * We might be able to use ONLY the query on MSBROWSE, but that's not
2890 * yet been tested with all Windows versions, so until it is, leave
2891 * the original wildcard query as the first choice and fall back to
2892 * MSBROWSE if the wildcard query fails.
2894 if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2895 !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2897 DEBUG(99, ("Could not retrieve name status for %s\n",
2898 addr));
2899 return NULL;
2902 if (!find_master_ip(name, &server_ss)) {
2903 DEBUG(99, ("Could not find master ip for %s\n", name));
2904 return NULL;
2907 *pp_workgroup_out = talloc_strdup(ctx, name);
2909 DEBUG(4, ("found master browser %s, %s\n", name, addr));
2911 print_sockaddr(addr, sizeof(addr), &server_ss);
2912 cli = get_ipc_connect(addr, &server_ss, user_info);
2914 return cli;
2918 * Return the IP address and workgroup of a master browser on the network, and
2919 * connect to it.
2922 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2923 const struct user_auth_info *user_info,
2924 char **pp_workgroup_out)
2926 struct ip_service *ip_list;
2927 struct cli_state *cli;
2928 int i, count;
2930 *pp_workgroup_out = NULL;
2932 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2934 /* Go looking for workgroups by broadcasting on the local network */
2936 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2937 &count))) {
2938 DEBUG(99, ("No master browsers responded\n"));
2939 return False;
2942 for (i = 0; i < count; i++) {
2943 char addr[INET6_ADDRSTRLEN];
2944 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2945 DEBUG(99, ("Found master browser %s\n", addr));
2947 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2948 user_info, pp_workgroup_out);
2949 if (cli)
2950 return(cli);
2953 return NULL;