WHATSNEW: Update release notes.
[Samba.git] / source3 / libsmb / cliconnect.c
blob1d1195d8e0cad7baa246801157f5a274a05d1220
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 "smb_krb5.h"
24 static const struct {
25 int prot;
26 const char name[24];
27 } prots[10] = {
28 {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
29 {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
30 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
31 {PROTOCOL_LANMAN1, "LANMAN1.0"},
32 {PROTOCOL_LANMAN2, "LM1.2X002"},
33 {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
34 {PROTOCOL_LANMAN2, "LANMAN2.1"},
35 {PROTOCOL_LANMAN2, "Samba"},
36 {PROTOCOL_NT1, "NT LANMAN 1.0"},
37 {PROTOCOL_NT1, "NT LM 0.12"},
40 #define STAR_SMBSERVER "*SMBSERVER"
42 /**
43 * Set the user session key for a connection
44 * @param cli The cli structure to add it too
45 * @param session_key The session key used. (A copy of this is taken for the cli struct)
49 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
51 cli->user_session_key = data_blob(session_key.data, session_key.length);
54 /****************************************************************************
55 Do an old lanman2 style session setup.
56 ****************************************************************************/
58 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
59 const char *user,
60 const char *pass, size_t passlen,
61 const char *workgroup)
63 DATA_BLOB session_key = data_blob_null;
64 DATA_BLOB lm_response = data_blob_null;
65 NTSTATUS status;
66 fstring pword;
67 char *p;
69 if (passlen > sizeof(pword)-1) {
70 return NT_STATUS_INVALID_PARAMETER;
73 /* LANMAN servers predate NT status codes and Unicode and ignore those
74 smb flags so we must disable the corresponding default capabilities
75 that would otherwise cause the Unicode and NT Status flags to be
76 set (and even returned by the server) */
78 cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
80 /* if in share level security then don't send a password now */
81 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
82 passlen = 0;
84 if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
85 /* Encrypted mode needed, and non encrypted password supplied. */
86 lm_response = data_blob(NULL, 24);
87 if (!SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data)) {
88 DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n"));
89 return NT_STATUS_ACCESS_DENIED;
91 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
92 /* Encrypted mode needed, and encrypted password supplied. */
93 lm_response = data_blob(pass, passlen);
94 } else if (passlen > 0) {
95 /* Plaintext mode needed, assume plaintext supplied. */
96 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
97 lm_response = data_blob(pass, passlen);
100 /* send a session setup command */
101 memset(cli->outbuf,'\0',smb_size);
102 cli_set_message(cli->outbuf,10, 0, True);
103 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
104 cli_setup_packet(cli);
106 SCVAL(cli->outbuf,smb_vwv0,0xFF);
107 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
108 SSVAL(cli->outbuf,smb_vwv3,2);
109 SSVAL(cli->outbuf,smb_vwv4,1);
110 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
111 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
113 p = smb_buf(cli->outbuf);
114 memcpy(p,lm_response.data,lm_response.length);
115 p += lm_response.length;
116 p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
117 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
118 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
119 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
120 cli_setup_bcc(cli, p);
122 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
123 return cli_nt_error(cli);
126 show_msg(cli->inbuf);
128 if (cli_is_error(cli)) {
129 return cli_nt_error(cli);
132 /* use the returned vuid from now on */
133 cli->vuid = SVAL(cli->inbuf,smb_uid);
134 status = cli_set_username(cli, user);
135 if (!NT_STATUS_IS_OK(status)) {
136 return status;
139 if (session_key.data) {
140 /* Have plaintext orginal */
141 cli_set_session_key(cli, session_key);
144 return NT_STATUS_OK;
147 /****************************************************************************
148 Work out suitable capabilities to offer the server.
149 ****************************************************************************/
151 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
153 uint32 capabilities = CAP_NT_SMBS;
155 if (!cli->force_dos_errors)
156 capabilities |= CAP_STATUS32;
158 if (cli->use_level_II_oplocks)
159 capabilities |= CAP_LEVEL_II_OPLOCKS;
161 capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
162 return capabilities;
165 /****************************************************************************
166 Do a NT1 guest session setup.
167 ****************************************************************************/
169 struct async_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
170 struct event_context *ev,
171 struct cli_state *cli)
173 struct async_req *result;
174 uint16_t vwv[13];
175 uint8_t *bytes;
177 SCVAL(vwv+0, 0, 0xFF);
178 SCVAL(vwv+0, 1, 0);
179 SSVAL(vwv+1, 0, 0);
180 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
181 SSVAL(vwv+3, 0, 2);
182 SSVAL(vwv+4, 0, cli->pid);
183 SIVAL(vwv+5, 0, cli->sesskey);
184 SSVAL(vwv+7, 0, 0);
185 SSVAL(vwv+8, 0, 0);
186 SSVAL(vwv+9, 0, 0);
187 SSVAL(vwv+10, 0, 0);
188 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
190 bytes = talloc_array(talloc_tos(), uint8_t, 0);
192 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
193 NULL);
194 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
195 NULL);
196 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
197 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
199 if (bytes == NULL) {
200 return NULL;
203 result = cli_request_send(mem_ctx, ev, cli, SMBsesssetupX, 0,
204 13, vwv, 0, talloc_get_size(bytes), bytes);
205 TALLOC_FREE(bytes);
206 return result;
209 NTSTATUS cli_session_setup_guest_recv(struct async_req *req)
211 struct cli_request *cli_req = talloc_get_type_abort(
212 req->private_data, struct cli_request);
213 struct cli_state *cli = cli_req->cli;
214 uint8_t wct;
215 uint16_t *vwv;
216 uint16_t num_bytes;
217 uint8_t *bytes;
218 uint8_t *p;
219 NTSTATUS status;
221 if (async_req_is_nterror(req, &status)) {
222 return status;
225 status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
226 if (!NT_STATUS_IS_OK(status)) {
227 return status;
230 p = bytes;
232 cli->vuid = SVAL(cli_req->inbuf, smb_uid);
234 p += clistr_pull(cli_req->inbuf, cli->server_os, (char *)p,
235 sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE);
236 p += clistr_pull(cli_req->inbuf, cli->server_type, (char *)p,
237 sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE);
238 p += clistr_pull(cli_req->inbuf, cli->server_domain, (char *)p,
239 sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE);
241 if (strstr(cli->server_type, "Samba")) {
242 cli->is_samba = True;
245 status = cli_set_username(cli, "");
246 if (!NT_STATUS_IS_OK(status)) {
247 return status;
250 return NT_STATUS_OK;
253 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
255 TALLOC_CTX *frame = talloc_stackframe();
256 struct event_context *ev;
257 struct async_req *req;
258 NTSTATUS status;
260 if (cli->fd_event != NULL) {
262 * Can't use sync call while an async call is in flight
264 status = NT_STATUS_INVALID_PARAMETER;
265 goto fail;
268 ev = event_context_init(frame);
269 if (ev == NULL) {
270 status = NT_STATUS_NO_MEMORY;
271 goto fail;
274 req = cli_session_setup_guest_send(frame, ev, cli);
275 if (req == NULL) {
276 status = NT_STATUS_NO_MEMORY;
277 goto fail;
280 while (req->state < ASYNC_REQ_DONE) {
281 event_loop_once(ev);
284 status = cli_session_setup_guest_recv(req);
285 fail:
286 TALLOC_FREE(frame);
287 return status;
290 /****************************************************************************
291 Do a NT1 plaintext session setup.
292 ****************************************************************************/
294 static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
295 const char *user, const char *pass,
296 const char *workgroup)
298 uint32 capabilities = cli_session_setup_capabilities(cli);
299 char *p;
300 NTSTATUS status;
301 fstring lanman;
303 fstr_sprintf( lanman, "Samba %s", samba_version_string());
305 memset(cli->outbuf, '\0', smb_size);
306 cli_set_message(cli->outbuf,13,0,True);
307 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
308 cli_setup_packet(cli);
310 SCVAL(cli->outbuf,smb_vwv0,0xFF);
311 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
312 SSVAL(cli->outbuf,smb_vwv3,2);
313 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
314 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
315 SSVAL(cli->outbuf,smb_vwv8,0);
316 SIVAL(cli->outbuf,smb_vwv11,capabilities);
317 p = smb_buf(cli->outbuf);
319 /* check wether to send the ASCII or UNICODE version of the password */
321 if ( (capabilities & CAP_UNICODE) == 0 ) {
322 p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
323 SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
325 else {
326 /* For ucs2 passwords clistr_push calls ucs2_align, which causes
327 * the space taken by the unicode password to be one byte too
328 * long (as we're on an odd byte boundary here). Reduce the
329 * count by 1 to cope with this. Fixes smbclient against NetApp
330 * servers which can't cope. Fix from
331 * bryan.kolodziej@allenlund.com in bug #3840.
333 p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
334 SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))-1);
337 p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
338 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
339 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
340 p += clistr_push(cli, p, lanman, -1, STR_TERMINATE);
341 cli_setup_bcc(cli, p);
343 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
344 return cli_nt_error(cli);
347 show_msg(cli->inbuf);
349 if (cli_is_error(cli)) {
350 return cli_nt_error(cli);
353 cli->vuid = SVAL(cli->inbuf,smb_uid);
354 p = smb_buf(cli->inbuf);
355 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
356 -1, STR_TERMINATE);
357 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
358 -1, STR_TERMINATE);
359 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
360 -1, STR_TERMINATE);
361 status = cli_set_username(cli, user);
362 if (!NT_STATUS_IS_OK(status)) {
363 return status;
365 if (strstr(cli->server_type, "Samba")) {
366 cli->is_samba = True;
369 return NT_STATUS_OK;
372 /****************************************************************************
373 do a NT1 NTLM/LM encrypted session setup - for when extended security
374 is not negotiated.
375 @param cli client state to create do session setup on
376 @param user username
377 @param pass *either* cleartext password (passlen !=24) or LM response.
378 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
379 @param workgroup The user's domain.
380 ****************************************************************************/
382 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
383 const char *pass, size_t passlen,
384 const char *ntpass, size_t ntpasslen,
385 const char *workgroup)
387 uint32 capabilities = cli_session_setup_capabilities(cli);
388 DATA_BLOB lm_response = data_blob_null;
389 DATA_BLOB nt_response = data_blob_null;
390 DATA_BLOB session_key = data_blob_null;
391 NTSTATUS result;
392 char *p;
393 bool ok;
395 if (passlen == 0) {
396 /* do nothing - guest login */
397 } else if (passlen != 24) {
398 if (lp_client_ntlmv2_auth()) {
399 DATA_BLOB server_chal;
400 DATA_BLOB names_blob;
401 server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8));
403 /* note that the 'workgroup' here is a best guess - we don't know
404 the server's domain at this point. The 'server name' is also
405 dodgy...
407 names_blob = NTLMv2_generate_names_blob(cli->called.name, workgroup);
409 if (!SMBNTLMv2encrypt(user, workgroup, pass, &server_chal,
410 &names_blob,
411 &lm_response, &nt_response, &session_key)) {
412 data_blob_free(&names_blob);
413 data_blob_free(&server_chal);
414 return NT_STATUS_ACCESS_DENIED;
416 data_blob_free(&names_blob);
417 data_blob_free(&server_chal);
419 } else {
420 uchar nt_hash[16];
421 E_md4hash(pass, nt_hash);
423 #ifdef LANMAN_ONLY
424 nt_response = data_blob_null;
425 #else
426 nt_response = data_blob(NULL, 24);
427 SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
428 #endif
429 /* non encrypted password supplied. Ignore ntpass. */
430 if (lp_client_lanman_auth()) {
431 lm_response = data_blob(NULL, 24);
432 if (!SMBencrypt(pass,cli->secblob.data, lm_response.data)) {
433 /* Oops, the LM response is invalid, just put
434 the NT response there instead */
435 data_blob_free(&lm_response);
436 lm_response = data_blob(nt_response.data, nt_response.length);
438 } else {
439 /* LM disabled, place NT# in LM field instead */
440 lm_response = data_blob(nt_response.data, nt_response.length);
443 session_key = data_blob(NULL, 16);
444 #ifdef LANMAN_ONLY
445 E_deshash(pass, session_key.data);
446 memset(&session_key.data[8], '\0', 8);
447 #else
448 SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
449 #endif
451 cli_temp_set_signing(cli);
452 } else {
453 /* pre-encrypted password supplied. Only used for
454 security=server, can't do
455 signing because we don't have original key */
457 lm_response = data_blob(pass, passlen);
458 nt_response = data_blob(ntpass, ntpasslen);
461 /* send a session setup command */
462 memset(cli->outbuf,'\0',smb_size);
464 cli_set_message(cli->outbuf,13,0,True);
465 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
466 cli_setup_packet(cli);
468 SCVAL(cli->outbuf,smb_vwv0,0xFF);
469 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
470 SSVAL(cli->outbuf,smb_vwv3,2);
471 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
472 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
473 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
474 SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
475 SIVAL(cli->outbuf,smb_vwv11,capabilities);
476 p = smb_buf(cli->outbuf);
477 if (lm_response.length) {
478 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
480 if (nt_response.length) {
481 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
483 p += clistr_push(cli, p, user, -1, STR_TERMINATE);
485 /* Upper case here might help some NTLMv2 implementations */
486 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
487 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
488 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
489 cli_setup_bcc(cli, p);
491 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
492 result = cli_nt_error(cli);
493 goto end;
496 /* show_msg(cli->inbuf); */
498 if (cli_is_error(cli)) {
499 result = cli_nt_error(cli);
500 goto end;
503 #ifdef LANMAN_ONLY
504 ok = cli_simple_set_signing(cli, session_key, lm_response);
505 #else
506 ok = cli_simple_set_signing(cli, session_key, nt_response);
507 #endif
508 if (ok) {
509 /* 'resign' the last message, so we get the right sequence numbers
510 for checking the first reply from the server */
511 cli_calculate_sign_mac(cli, cli->outbuf);
513 if (!cli_check_sign_mac(cli, cli->inbuf)) {
514 result = NT_STATUS_ACCESS_DENIED;
515 goto end;
519 /* use the returned vuid from now on */
520 cli->vuid = SVAL(cli->inbuf,smb_uid);
522 p = smb_buf(cli->inbuf);
523 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
524 -1, STR_TERMINATE);
525 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
526 -1, STR_TERMINATE);
527 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
528 -1, STR_TERMINATE);
530 if (strstr(cli->server_type, "Samba")) {
531 cli->is_samba = True;
534 result = cli_set_username(cli, user);
535 if (!NT_STATUS_IS_OK(result)) {
536 goto end;
539 if (session_key.data) {
540 /* Have plaintext orginal */
541 cli_set_session_key(cli, session_key);
544 result = NT_STATUS_OK;
545 end:
546 data_blob_free(&lm_response);
547 data_blob_free(&nt_response);
548 data_blob_free(&session_key);
549 return result;
552 /****************************************************************************
553 Send a extended security session setup blob
554 ****************************************************************************/
556 static bool cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob)
558 uint32 capabilities = cli_session_setup_capabilities(cli);
559 char *p;
561 capabilities |= CAP_EXTENDED_SECURITY;
563 /* send a session setup command */
564 memset(cli->outbuf,'\0',smb_size);
566 cli_set_message(cli->outbuf,12,0,True);
567 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
569 cli_setup_packet(cli);
571 SCVAL(cli->outbuf,smb_vwv0,0xFF);
572 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
573 SSVAL(cli->outbuf,smb_vwv3,2);
574 SSVAL(cli->outbuf,smb_vwv4,1);
575 SIVAL(cli->outbuf,smb_vwv5,0);
576 SSVAL(cli->outbuf,smb_vwv7,blob.length);
577 SIVAL(cli->outbuf,smb_vwv10,capabilities);
578 p = smb_buf(cli->outbuf);
579 memcpy(p, blob.data, blob.length);
580 p += blob.length;
581 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
582 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
583 cli_setup_bcc(cli, p);
584 return cli_send_smb(cli);
587 /****************************************************************************
588 Send a extended security session setup blob, returning a reply blob.
589 ****************************************************************************/
591 static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli)
593 DATA_BLOB blob2 = data_blob_null;
594 char *p;
595 size_t len;
597 if (!cli_receive_smb(cli))
598 return blob2;
600 show_msg(cli->inbuf);
602 if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli),
603 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
604 return blob2;
607 /* use the returned vuid from now on */
608 cli->vuid = SVAL(cli->inbuf,smb_uid);
610 p = smb_buf(cli->inbuf);
612 blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3));
614 p += blob2.length;
615 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
616 -1, STR_TERMINATE);
618 /* w2k with kerberos doesn't properly null terminate this field */
619 len = smb_bufrem(cli->inbuf, p);
620 if (p + len < cli->inbuf + cli->bufsize+SAFETY_MARGIN - 2) {
621 char *end_of_buf = p + len;
623 SSVAL(p, len, 0);
624 /* Now it's null terminated. */
625 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
626 -1, STR_TERMINATE);
628 * See if there's another string. If so it's the
629 * server domain (part of the 'standard' Samba
630 * server signature).
632 if (p < end_of_buf) {
633 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
634 -1, STR_TERMINATE);
636 } else {
638 * No room to null terminate so we can't see if there
639 * is another string (server_domain) afterwards.
641 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
642 len, 0);
644 return blob2;
647 #ifdef HAVE_KRB5
648 /****************************************************************************
649 Send a extended security session setup blob, returning a reply blob.
650 ****************************************************************************/
652 /* The following is calculated from :
653 * (smb_size-4) = 35
654 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
655 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
656 * end of packet.
659 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
661 static bool cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
663 int32 remaining = blob.length;
664 int32 cur = 0;
665 DATA_BLOB send_blob = data_blob_null;
666 int32 max_blob_size = 0;
667 DATA_BLOB receive_blob = data_blob_null;
669 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
670 DEBUG(0,("cli_session_setup_blob: cli->max_xmit too small "
671 "(was %u, need minimum %u)\n",
672 (unsigned int)cli->max_xmit,
673 BASE_SESSSETUP_BLOB_PACKET_SIZE));
674 cli_set_nt_error(cli, NT_STATUS_INVALID_PARAMETER);
675 return False;
678 max_blob_size = cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE;
680 while ( remaining > 0) {
681 if (remaining >= max_blob_size) {
682 send_blob.length = max_blob_size;
683 remaining -= max_blob_size;
684 } else {
685 send_blob.length = remaining;
686 remaining = 0;
689 send_blob.data = &blob.data[cur];
690 cur += send_blob.length;
692 DEBUG(10, ("cli_session_setup_blob: Remaining (%u) sending (%u) current (%u)\n",
693 (unsigned int)remaining,
694 (unsigned int)send_blob.length,
695 (unsigned int)cur ));
697 if (!cli_session_setup_blob_send(cli, send_blob)) {
698 DEBUG(0, ("cli_session_setup_blob: send failed\n"));
699 return False;
702 receive_blob = cli_session_setup_blob_receive(cli);
703 data_blob_free(&receive_blob);
705 if (cli_is_error(cli) &&
706 !NT_STATUS_EQUAL( cli_get_nt_error(cli),
707 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
708 DEBUG(0, ("cli_session_setup_blob: receive failed "
709 "(%s)\n", nt_errstr(cli_get_nt_error(cli))));
710 cli->vuid = 0;
711 return False;
715 return True;
718 /****************************************************************************
719 Use in-memory credentials cache
720 ****************************************************************************/
722 static void use_in_memory_ccache(void) {
723 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
726 /****************************************************************************
727 Do a spnego/kerberos encrypted session setup.
728 ****************************************************************************/
730 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
732 DATA_BLOB negTokenTarg;
733 DATA_BLOB session_key_krb5;
734 NTSTATUS nt_status;
735 int rc;
737 cli_temp_set_signing(cli);
739 DEBUG(2,("Doing kerberos session setup\n"));
741 /* generate the encapsulated kerberos5 ticket */
742 rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5, 0, NULL);
744 if (rc) {
745 DEBUG(1, ("cli_session_setup_kerberos: spnego_gen_negTokenTarg failed: %s\n",
746 error_message(rc)));
747 return ADS_ERROR_KRB5(rc);
750 #if 0
751 file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
752 #endif
754 if (!cli_session_setup_blob(cli, negTokenTarg)) {
755 nt_status = cli_nt_error(cli);
756 goto nt_error;
759 if (cli_is_error(cli)) {
760 nt_status = cli_nt_error(cli);
761 if (NT_STATUS_IS_OK(nt_status)) {
762 nt_status = NT_STATUS_UNSUCCESSFUL;
764 goto nt_error;
767 cli_set_session_key(cli, session_key_krb5);
769 if (cli_simple_set_signing(
770 cli, session_key_krb5, data_blob_null)) {
772 /* 'resign' the last message, so we get the right sequence numbers
773 for checking the first reply from the server */
774 cli_calculate_sign_mac(cli, cli->outbuf);
776 if (!cli_check_sign_mac(cli, cli->inbuf)) {
777 nt_status = NT_STATUS_ACCESS_DENIED;
778 goto nt_error;
782 data_blob_free(&negTokenTarg);
783 data_blob_free(&session_key_krb5);
785 return ADS_ERROR_NT(NT_STATUS_OK);
787 nt_error:
788 data_blob_free(&negTokenTarg);
789 data_blob_free(&session_key_krb5);
790 cli->vuid = 0;
791 return ADS_ERROR_NT(nt_status);
793 #endif /* HAVE_KRB5 */
796 /****************************************************************************
797 Do a spnego/NTLMSSP encrypted session setup.
798 ****************************************************************************/
800 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
801 const char *pass, const char *domain)
803 struct ntlmssp_state *ntlmssp_state;
804 NTSTATUS nt_status;
805 int turn = 1;
806 DATA_BLOB msg1;
807 DATA_BLOB blob = data_blob_null;
808 DATA_BLOB blob_in = data_blob_null;
809 DATA_BLOB blob_out = data_blob_null;
811 cli_temp_set_signing(cli);
813 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
814 return nt_status;
816 ntlmssp_want_feature(ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
818 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
819 return nt_status;
821 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
822 return nt_status;
824 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
825 return nt_status;
828 do {
829 nt_status = ntlmssp_update(ntlmssp_state,
830 blob_in, &blob_out);
831 data_blob_free(&blob_in);
832 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(nt_status)) {
833 if (turn == 1) {
834 /* and wrap it in a SPNEGO wrapper */
835 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
836 } else {
837 /* wrap it in SPNEGO */
838 msg1 = spnego_gen_auth(blob_out);
841 /* now send that blob on its way */
842 if (!cli_session_setup_blob_send(cli, msg1)) {
843 DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
844 nt_status = NT_STATUS_UNSUCCESSFUL;
845 } else {
846 blob = cli_session_setup_blob_receive(cli);
848 nt_status = cli_nt_error(cli);
849 if (cli_is_error(cli) && NT_STATUS_IS_OK(nt_status)) {
850 if (cli->smb_rw_error == SMB_READ_BAD_SIG) {
851 nt_status = NT_STATUS_ACCESS_DENIED;
852 } else {
853 nt_status = NT_STATUS_UNSUCCESSFUL;
857 data_blob_free(&msg1);
860 if (!blob.length) {
861 if (NT_STATUS_IS_OK(nt_status)) {
862 nt_status = NT_STATUS_UNSUCCESSFUL;
864 } else if ((turn == 1) &&
865 NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
866 DATA_BLOB tmp_blob = data_blob_null;
867 /* the server might give us back two challenges */
868 if (!spnego_parse_challenge(blob, &blob_in,
869 &tmp_blob)) {
870 DEBUG(3,("Failed to parse challenges\n"));
871 nt_status = NT_STATUS_INVALID_PARAMETER;
873 data_blob_free(&tmp_blob);
874 } else {
875 if (!spnego_parse_auth_response(blob, nt_status, OID_NTLMSSP,
876 &blob_in)) {
877 DEBUG(3,("Failed to parse auth response\n"));
878 if (NT_STATUS_IS_OK(nt_status)
879 || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED))
880 nt_status = NT_STATUS_INVALID_PARAMETER;
883 data_blob_free(&blob);
884 data_blob_free(&blob_out);
885 turn++;
886 } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
888 data_blob_free(&blob_in);
890 if (NT_STATUS_IS_OK(nt_status)) {
892 if (cli->server_domain[0] == '\0') {
893 fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
895 cli_set_session_key(cli, ntlmssp_state->session_key);
897 if (cli_simple_set_signing(
898 cli, ntlmssp_state->session_key, data_blob_null)) {
900 /* 'resign' the last message, so we get the right sequence numbers
901 for checking the first reply from the server */
902 cli_calculate_sign_mac(cli, cli->outbuf);
904 if (!cli_check_sign_mac(cli, cli->inbuf)) {
905 nt_status = NT_STATUS_ACCESS_DENIED;
910 /* we have a reference conter on ntlmssp_state, if we are signing
911 then the state will be kept by the signing engine */
913 ntlmssp_end(&ntlmssp_state);
915 if (!NT_STATUS_IS_OK(nt_status)) {
916 cli->vuid = 0;
918 return nt_status;
921 /****************************************************************************
922 Do a spnego encrypted session setup.
924 user_domain: The shortname of the domain the user/machine is a member of.
925 dest_realm: The realm we're connecting to, if NULL we use our default realm.
926 ****************************************************************************/
928 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
929 const char *pass, const char *user_domain,
930 const char * dest_realm)
932 char *principal = NULL;
933 char *OIDs[ASN1_MAX_OIDS];
934 int i;
935 DATA_BLOB blob;
936 const char *p = NULL;
937 char *account = NULL;
938 NTSTATUS status;
940 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
942 /* the server might not even do spnego */
943 if (cli->secblob.length <= 16) {
944 DEBUG(3,("server didn't supply a full spnego negprot\n"));
945 goto ntlmssp;
948 #if 0
949 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
950 #endif
952 /* there is 16 bytes of GUID before the real spnego packet starts */
953 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
955 /* The server sent us the first part of the SPNEGO exchange in the
956 * negprot reply. It is WRONG to depend on the principal sent in the
957 * negprot reply, but right now we do it. If we don't receive one,
958 * we try to best guess, then fall back to NTLM. */
959 if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
960 data_blob_free(&blob);
961 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
963 data_blob_free(&blob);
965 /* make sure the server understands kerberos */
966 for (i=0;OIDs[i];i++) {
967 DEBUG(3,("got OID=%s\n", OIDs[i]));
968 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
969 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
970 cli->got_kerberos_mechanism = True;
972 talloc_free(OIDs[i]);
975 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
977 status = cli_set_username(cli, user);
978 if (!NT_STATUS_IS_OK(status)) {
979 return ADS_ERROR_NT(status);
982 #ifdef HAVE_KRB5
983 /* If password is set we reauthenticate to kerberos server
984 * and do not store results */
986 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
987 ADS_STATUS rc;
989 if (pass && *pass) {
990 int ret;
992 use_in_memory_ccache();
993 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
995 if (ret){
996 TALLOC_FREE(principal);
997 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
998 if (cli->fallback_after_kerberos)
999 goto ntlmssp;
1000 return ADS_ERROR_KRB5(ret);
1004 /* If we get a bad principal, try to guess it if
1005 we have a valid host NetBIOS name.
1007 if (strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1008 TALLOC_FREE(principal);
1011 if (principal == NULL &&
1012 !is_ipaddress(cli->desthost) &&
1013 !strequal(STAR_SMBSERVER,
1014 cli->desthost)) {
1015 char *realm = NULL;
1016 char *machine = NULL;
1017 char *host = NULL;
1018 DEBUG(3,("cli_session_setup_spnego: got a "
1019 "bad server principal, trying to guess ...\n"));
1021 host = strchr_m(cli->desthost, '.');
1022 if (host) {
1023 machine = SMB_STRNDUP(cli->desthost,
1024 host - cli->desthost);
1025 } else {
1026 machine = SMB_STRDUP(cli->desthost);
1028 if (machine == NULL) {
1029 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1032 if (dest_realm) {
1033 realm = SMB_STRDUP(dest_realm);
1034 strupper_m(realm);
1035 } else {
1036 realm = kerberos_get_default_realm_from_ccache();
1038 if (realm && *realm) {
1039 principal = talloc_asprintf(NULL, "%s$@%s",
1040 machine, realm);
1041 if (!principal) {
1042 SAFE_FREE(machine);
1043 SAFE_FREE(realm);
1044 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1046 DEBUG(3,("cli_session_setup_spnego: guessed "
1047 "server principal=%s\n",
1048 principal ? principal : "<null>"));
1050 SAFE_FREE(machine);
1051 SAFE_FREE(realm);
1054 if (principal) {
1055 rc = cli_session_setup_kerberos(cli, principal,
1056 dest_realm);
1057 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1058 TALLOC_FREE(principal);
1059 return rc;
1063 #endif
1065 TALLOC_FREE(principal);
1067 ntlmssp:
1069 account = talloc_strdup(talloc_tos(), user);
1070 if (!account) {
1071 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1074 /* when falling back to ntlmssp while authenticating with a machine
1075 * account strip off the realm - gd */
1077 if ((p = strchr_m(user, '@')) != NULL) {
1078 account[PTR_DIFF(p,user)] = '\0';
1081 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1084 /****************************************************************************
1085 Send a session setup. The username and workgroup is in UNIX character
1086 format and must be converted to DOS codepage format before sending. If the
1087 password is in plaintext, the same should be done.
1088 ****************************************************************************/
1090 NTSTATUS cli_session_setup(struct cli_state *cli,
1091 const char *user,
1092 const char *pass, int passlen,
1093 const char *ntpass, int ntpasslen,
1094 const char *workgroup)
1096 char *p;
1097 fstring user2;
1099 if (user) {
1100 fstrcpy(user2, user);
1101 } else {
1102 user2[0] ='\0';
1105 if (!workgroup) {
1106 workgroup = "";
1109 /* allow for workgroups as part of the username */
1110 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1111 (p=strchr_m(user2,*lp_winbind_separator()))) {
1112 *p = 0;
1113 user = p+1;
1114 workgroup = user2;
1117 if (cli->protocol < PROTOCOL_LANMAN1) {
1118 return NT_STATUS_OK;
1121 /* now work out what sort of session setup we are going to
1122 do. I have split this into separate functions to make the
1123 flow a bit easier to understand (tridge) */
1125 /* if its an older server then we have to use the older request format */
1127 if (cli->protocol < PROTOCOL_NT1) {
1128 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1129 DEBUG(1, ("Server requested LM password but 'client lanman auth'"
1130 " is disabled\n"));
1131 return NT_STATUS_ACCESS_DENIED;
1134 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1135 !lp_client_plaintext_auth() && (*pass)) {
1136 DEBUG(1, ("Server requested plaintext password but "
1137 "'client plaintext auth' is disabled\n"));
1138 return NT_STATUS_ACCESS_DENIED;
1141 return cli_session_setup_lanman2(cli, user, pass, passlen,
1142 workgroup);
1145 /* if no user is supplied then we have to do an anonymous connection.
1146 passwords are ignored */
1148 if (!user || !*user)
1149 return cli_session_setup_guest(cli);
1151 /* if the server is share level then send a plaintext null
1152 password at this point. The password is sent in the tree
1153 connect */
1155 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
1156 return cli_session_setup_plaintext(cli, user, "", workgroup);
1158 /* if the server doesn't support encryption then we have to use
1159 plaintext. The second password is ignored */
1161 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1162 if (!lp_client_plaintext_auth() && (*pass)) {
1163 DEBUG(1, ("Server requested plaintext password but "
1164 "'client plaintext auth' is disabled\n"));
1165 return NT_STATUS_ACCESS_DENIED;
1167 return cli_session_setup_plaintext(cli, user, pass, workgroup);
1170 /* if the server supports extended security then use SPNEGO */
1172 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
1173 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
1174 workgroup, NULL);
1175 if (!ADS_ERR_OK(status)) {
1176 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1177 return ads_ntstatus(status);
1179 } else {
1180 NTSTATUS status;
1182 /* otherwise do a NT1 style session setup */
1183 status = cli_session_setup_nt1(cli, user, pass, passlen,
1184 ntpass, ntpasslen, workgroup);
1185 if (!NT_STATUS_IS_OK(status)) {
1186 DEBUG(3,("cli_session_setup: NT1 session setup "
1187 "failed: %s\n", nt_errstr(status)));
1188 return status;
1192 if (strstr(cli->server_type, "Samba")) {
1193 cli->is_samba = True;
1196 return NT_STATUS_OK;
1199 /****************************************************************************
1200 Send a uloggoff.
1201 *****************************************************************************/
1203 bool cli_ulogoff(struct cli_state *cli)
1205 memset(cli->outbuf,'\0',smb_size);
1206 cli_set_message(cli->outbuf,2,0,True);
1207 SCVAL(cli->outbuf,smb_com,SMBulogoffX);
1208 cli_setup_packet(cli);
1209 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1210 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1212 cli_send_smb(cli);
1213 if (!cli_receive_smb(cli))
1214 return False;
1216 if (cli_is_error(cli)) {
1217 return False;
1220 cli->vuid = -1;
1221 return True;
1224 /****************************************************************************
1225 Send a tconX.
1226 ****************************************************************************/
1228 struct async_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
1229 struct event_context *ev,
1230 struct cli_state *cli,
1231 const char *share, const char *dev,
1232 const char *pass, int passlen)
1234 fstring pword;
1235 char *tmp = NULL;
1236 struct async_req *result;
1237 uint16_t vwv[4];
1238 uint8_t *bytes;
1240 fstrcpy(cli->share, share);
1242 /* in user level security don't send a password now */
1243 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1244 passlen = 1;
1245 pass = "";
1246 } else if (pass == NULL) {
1247 DEBUG(1, ("Server not using user level security and no "
1248 "password supplied.\n"));
1249 goto access_denied;
1252 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1253 *pass && passlen != 24) {
1254 if (!lp_client_lanman_auth()) {
1255 DEBUG(1, ("Server requested LANMAN password "
1256 "(share-level security) but "
1257 "'client lanman auth' is disabled\n"));
1258 goto access_denied;
1262 * Non-encrypted passwords - convert to DOS codepage before
1263 * encryption.
1265 passlen = 24;
1266 SMBencrypt(pass, cli->secblob.data, (uchar *)pword);
1267 } else {
1268 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1269 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1270 == 0) {
1271 if (!lp_client_plaintext_auth() && (*pass)) {
1272 DEBUG(1, ("Server requested plaintext "
1273 "password but 'client plaintext "
1274 "auth' is disabled\n"));
1275 goto access_denied;
1279 * Non-encrypted passwords - convert to DOS codepage
1280 * before using.
1282 passlen = clistr_push(cli, pword, pass, sizeof(pword),
1283 STR_TERMINATE);
1284 if (passlen == -1) {
1285 DEBUG(1, ("clistr_push(pword) failed\n"));
1286 goto access_denied;
1288 } else {
1289 if (passlen) {
1290 memcpy(pword, pass, passlen);
1295 SCVAL(vwv+0, 0, 0xFF);
1296 SCVAL(vwv+0, 1, 0);
1297 SSVAL(vwv+1, 0, 0);
1298 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
1299 SSVAL(vwv+3, 0, passlen);
1301 if (passlen) {
1302 bytes = (uint8_t *)talloc_memdup(talloc_tos(), pword, passlen);
1303 } else {
1304 bytes = talloc_array(talloc_tos(), uint8_t, 0);
1308 * Add the sharename
1310 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1311 cli->desthost, share);
1312 if (tmp == NULL) {
1313 TALLOC_FREE(bytes);
1314 return NULL;
1316 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
1317 NULL);
1318 TALLOC_FREE(tmp);
1321 * Add the devicetype
1323 tmp = talloc_strdup_upper(talloc_tos(), dev);
1324 if (tmp == NULL) {
1325 TALLOC_FREE(bytes);
1326 return NULL;
1328 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
1329 TALLOC_FREE(tmp);
1331 if (bytes == NULL) {
1332 return NULL;
1335 result = cli_request_send(mem_ctx, ev, cli, SMBtconX, 0,
1336 4, vwv, 0, talloc_get_size(bytes), bytes);
1337 TALLOC_FREE(bytes);
1338 return result;
1340 access_denied:
1342 struct cli_request *state;
1343 if (!async_req_setup(mem_ctx, &result, &state,
1344 struct cli_request)) {
1345 goto fail;
1347 if (async_post_ntstatus(result, ev, NT_STATUS_ACCESS_DENIED)) {
1348 return result;
1351 fail:
1352 TALLOC_FREE(result);
1353 return NULL;
1356 NTSTATUS cli_tcon_andx_recv(struct async_req *req)
1358 struct cli_request *cli_req = talloc_get_type_abort(
1359 req->private_data, struct cli_request);
1360 struct cli_state *cli = cli_req->cli;
1361 uint8_t wct;
1362 uint16_t *vwv;
1363 uint16_t num_bytes;
1364 uint8_t *bytes;
1365 NTSTATUS status;
1367 if (async_req_is_nterror(req, &status)) {
1368 return status;
1371 status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
1372 if (!NT_STATUS_IS_OK(status)) {
1373 return status;
1376 clistr_pull(cli_req->inbuf, cli->dev, bytes, sizeof(fstring),
1377 num_bytes, STR_TERMINATE|STR_ASCII);
1379 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
1380 /* almost certainly win95 - enable bug fixes */
1381 cli->win95 = True;
1385 * Make sure that we have the optional support 16-bit field. WCT > 2.
1386 * Avoids issues when connecting to Win9x boxes sharing files
1389 cli->dfsroot = false;
1391 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
1392 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
1395 cli->cnum = SVAL(cli_req->inbuf,smb_tid);
1396 return NT_STATUS_OK;
1399 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
1400 const char *dev, const char *pass, int passlen)
1402 TALLOC_CTX *frame = talloc_stackframe();
1403 struct event_context *ev;
1404 struct async_req *req;
1405 NTSTATUS status;
1407 if (cli->fd_event != NULL) {
1409 * Can't use sync call while an async call is in flight
1411 status = NT_STATUS_INVALID_PARAMETER;
1412 goto fail;
1415 ev = event_context_init(frame);
1416 if (ev == NULL) {
1417 status = NT_STATUS_NO_MEMORY;
1418 goto fail;
1421 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
1422 if (req == NULL) {
1423 status = NT_STATUS_NO_MEMORY;
1424 goto fail;
1427 while (req->state < ASYNC_REQ_DONE) {
1428 event_loop_once(ev);
1431 status = cli_tcon_andx_recv(req);
1432 fail:
1433 TALLOC_FREE(frame);
1434 return status;
1437 /****************************************************************************
1438 Send a tree disconnect.
1439 ****************************************************************************/
1441 bool cli_tdis(struct cli_state *cli)
1443 memset(cli->outbuf,'\0',smb_size);
1444 cli_set_message(cli->outbuf,0,0,True);
1445 SCVAL(cli->outbuf,smb_com,SMBtdis);
1446 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1447 cli_setup_packet(cli);
1449 cli_send_smb(cli);
1450 if (!cli_receive_smb(cli))
1451 return False;
1453 if (cli_is_error(cli)) {
1454 return False;
1457 cli->cnum = -1;
1458 return True;
1461 /****************************************************************************
1462 Send a negprot command.
1463 ****************************************************************************/
1465 void cli_negprot_sendsync(struct cli_state *cli)
1467 char *p;
1468 int numprots;
1470 if (cli->protocol < PROTOCOL_NT1)
1471 cli->use_spnego = False;
1473 memset(cli->outbuf,'\0',smb_size);
1475 /* setup the protocol strings */
1476 cli_set_message(cli->outbuf,0,0,True);
1478 p = smb_buf(cli->outbuf);
1479 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1480 if (prots[numprots].prot > cli->protocol) {
1481 break;
1483 *p++ = 2;
1484 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1487 SCVAL(cli->outbuf,smb_com,SMBnegprot);
1488 cli_setup_bcc(cli, p);
1489 cli_setup_packet(cli);
1491 SCVAL(smb_buf(cli->outbuf),0,2);
1493 cli_send_smb(cli);
1496 /****************************************************************************
1497 Send a negprot command.
1498 ****************************************************************************/
1500 struct async_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
1501 struct event_context *ev,
1502 struct cli_state *cli)
1504 struct async_req *result;
1505 uint8_t *bytes = NULL;
1506 int numprots;
1508 if (cli->protocol < PROTOCOL_NT1)
1509 cli->use_spnego = False;
1511 /* setup the protocol strings */
1512 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1513 uint8_t c = 2;
1514 if (prots[numprots].prot > cli->protocol) {
1515 break;
1517 bytes = (uint8_t *)talloc_append_blob(
1518 talloc_tos(), bytes, data_blob_const(&c, sizeof(c)));
1519 if (bytes == NULL) {
1520 return NULL;
1522 bytes = smb_bytes_push_str(bytes, false,
1523 prots[numprots].name,
1524 strlen(prots[numprots].name)+1,
1525 NULL);
1526 if (bytes == NULL) {
1527 return NULL;
1531 result = cli_request_send(mem_ctx, ev, cli, SMBnegprot, 0, 0, NULL, 0,
1532 talloc_get_size(bytes), bytes);
1533 TALLOC_FREE(bytes);
1534 return result;
1537 NTSTATUS cli_negprot_recv(struct async_req *req)
1539 struct cli_request *cli_req = talloc_get_type_abort(
1540 req->private_data, struct cli_request);
1541 struct cli_state *cli = cli_req->cli;
1542 uint8_t wct;
1543 uint16_t *vwv;
1544 uint16_t num_bytes;
1545 uint8_t *bytes;
1546 NTSTATUS status;
1547 uint16_t protnum;
1549 if (async_req_is_nterror(req, &status)) {
1550 return status;
1553 status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
1554 if (!NT_STATUS_IS_OK(status)) {
1555 return status;
1558 protnum = SVAL(vwv, 0);
1560 if ((protnum >= ARRAY_SIZE(prots))
1561 || (prots[protnum].prot > cli_req->cli->protocol)) {
1562 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1565 cli->protocol = prots[protnum].prot;
1567 if ((cli->protocol < PROTOCOL_NT1) && cli->sign_info.mandatory_signing) {
1568 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1569 return NT_STATUS_ACCESS_DENIED;
1572 if (cli->protocol >= PROTOCOL_NT1) {
1573 struct timespec ts;
1574 /* NT protocol */
1575 cli->sec_mode = CVAL(vwv + 1, 0);
1576 cli->max_mux = SVAL(vwv + 1, 1);
1577 cli->max_xmit = IVAL(vwv + 3, 1);
1578 cli->sesskey = IVAL(vwv + 7, 1);
1579 cli->serverzone = SVALS(vwv + 15, 1);
1580 cli->serverzone *= 60;
1581 /* this time arrives in real GMT */
1582 ts = interpret_long_date(((char *)(vwv+11))+1);
1583 cli->servertime = ts.tv_sec;
1584 cli->secblob = data_blob(bytes, num_bytes);
1585 cli->capabilities = IVAL(vwv + 9, 1);
1586 if (cli->capabilities & CAP_RAW_MODE) {
1587 cli->readbraw_supported = True;
1588 cli->writebraw_supported = True;
1590 /* work out if they sent us a workgroup */
1591 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1592 smb_buflen(cli->inbuf) > 8) {
1593 clistr_pull(cli->inbuf, cli->server_domain,
1594 bytes+8, sizeof(cli->server_domain),
1595 num_bytes-8,
1596 STR_UNICODE|STR_NOALIGN);
1600 * As signing is slow we only turn it on if either the client or
1601 * the server require it. JRA.
1604 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
1605 /* Fail if server says signing is mandatory and we don't want to support it. */
1606 if (!cli->sign_info.allow_smb_signing) {
1607 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1608 return NT_STATUS_ACCESS_DENIED;
1610 cli->sign_info.negotiated_smb_signing = True;
1611 cli->sign_info.mandatory_signing = True;
1612 } else if (cli->sign_info.mandatory_signing && cli->sign_info.allow_smb_signing) {
1613 /* Fail if client says signing is mandatory and the server doesn't support it. */
1614 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
1615 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1616 return NT_STATUS_ACCESS_DENIED;
1618 cli->sign_info.negotiated_smb_signing = True;
1619 cli->sign_info.mandatory_signing = True;
1620 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
1621 cli->sign_info.negotiated_smb_signing = True;
1624 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
1625 SAFE_FREE(cli->outbuf);
1626 SAFE_FREE(cli->inbuf);
1627 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1628 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1629 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
1632 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1633 cli->use_spnego = False;
1634 cli->sec_mode = SVAL(vwv + 1, 0);
1635 cli->max_xmit = SVAL(vwv + 2, 0);
1636 cli->max_mux = SVAL(vwv + 3, 0);
1637 cli->sesskey = IVAL(vwv + 6, 0);
1638 cli->serverzone = SVALS(vwv + 10, 0);
1639 cli->serverzone *= 60;
1640 /* this time is converted to GMT by make_unix_date */
1641 cli->servertime = cli_make_unix_date(
1642 cli, (char *)(vwv + 8));
1643 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
1644 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
1645 cli->secblob = data_blob(bytes, num_bytes);
1646 } else {
1647 /* the old core protocol */
1648 cli->use_spnego = False;
1649 cli->sec_mode = 0;
1650 cli->serverzone = get_time_zone(time(NULL));
1653 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1655 /* a way to force ascii SMB */
1656 if (getenv("CLI_FORCE_ASCII"))
1657 cli->capabilities &= ~CAP_UNICODE;
1659 return NT_STATUS_OK;
1662 NTSTATUS cli_negprot(struct cli_state *cli)
1664 TALLOC_CTX *frame = talloc_stackframe();
1665 struct event_context *ev;
1666 struct async_req *req;
1667 NTSTATUS status = NT_STATUS_NO_MEMORY;
1669 if (cli->fd_event != NULL) {
1671 * Can't use sync call while an async call is in flight
1673 cli_set_error(cli, NT_STATUS_INVALID_PARAMETER);
1674 goto fail;
1677 ev = event_context_init(frame);
1678 if (ev == NULL) {
1679 goto fail;
1682 req = cli_negprot_send(frame, ev, cli);
1683 if (req == NULL) {
1684 goto fail;
1687 while (req->state < ASYNC_REQ_DONE) {
1688 event_loop_once(ev);
1691 status = cli_negprot_recv(req);
1692 fail:
1693 TALLOC_FREE(frame);
1694 return status;
1697 /****************************************************************************
1698 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1699 ****************************************************************************/
1701 bool cli_session_request(struct cli_state *cli,
1702 struct nmb_name *calling, struct nmb_name *called)
1704 char *p;
1705 int len = 4;
1706 char *tmp;
1708 /* 445 doesn't have session request */
1709 if (cli->port == 445)
1710 return True;
1712 memcpy(&(cli->calling), calling, sizeof(*calling));
1713 memcpy(&(cli->called ), called , sizeof(*called ));
1715 /* put in the destination name */
1717 tmp = name_mangle(talloc_tos(), cli->called.name,
1718 cli->called.name_type);
1719 if (tmp == NULL) {
1720 return false;
1723 p = cli->outbuf+len;
1724 memcpy(p, tmp, name_len(tmp));
1725 len += name_len(tmp);
1726 TALLOC_FREE(tmp);
1728 /* and my name */
1730 tmp = name_mangle(talloc_tos(), cli->calling.name,
1731 cli->calling.name_type);
1732 if (tmp == NULL) {
1733 return false;
1736 p = cli->outbuf+len;
1737 memcpy(p, tmp, name_len(tmp));
1738 len += name_len(tmp);
1739 TALLOC_FREE(tmp);
1741 /* send a session request (RFC 1002) */
1742 /* setup the packet length
1743 * Remove four bytes from the length count, since the length
1744 * field in the NBT Session Service header counts the number
1745 * of bytes which follow. The cli_send_smb() function knows
1746 * about this and accounts for those four bytes.
1747 * CRH.
1749 len -= 4;
1750 _smb_setlen(cli->outbuf,len);
1751 SCVAL(cli->outbuf,0,0x81);
1753 cli_send_smb(cli);
1754 DEBUG(5,("Sent session request\n"));
1756 if (!cli_receive_smb(cli))
1757 return False;
1759 if (CVAL(cli->inbuf,0) == 0x84) {
1760 /* C. Hoch 9/14/95 Start */
1761 /* For information, here is the response structure.
1762 * We do the byte-twiddling to for portability.
1763 struct RetargetResponse{
1764 unsigned char type;
1765 unsigned char flags;
1766 int16 length;
1767 int32 ip_addr;
1768 int16 port;
1771 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1772 struct in_addr dest_ip;
1773 NTSTATUS status;
1775 /* SESSION RETARGET */
1776 putip((char *)&dest_ip,cli->inbuf+4);
1777 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
1779 status = open_socket_out(&cli->dest_ss, port,
1780 LONG_CONNECT_TIMEOUT, &cli->fd);
1781 if (!NT_STATUS_IS_OK(status)) {
1782 return False;
1785 DEBUG(3,("Retargeted\n"));
1787 set_socket_options(cli->fd, lp_socket_options());
1789 /* Try again */
1791 static int depth;
1792 bool ret;
1793 if (depth > 4) {
1794 DEBUG(0,("Retarget recursion - failing\n"));
1795 return False;
1797 depth++;
1798 ret = cli_session_request(cli, calling, called);
1799 depth--;
1800 return ret;
1802 } /* C. Hoch 9/14/95 End */
1804 if (CVAL(cli->inbuf,0) != 0x82) {
1805 /* This is the wrong place to put the error... JRA. */
1806 cli->rap_error = CVAL(cli->inbuf,4);
1807 return False;
1809 return(True);
1812 struct fd_struct {
1813 int fd;
1816 static void smb_sock_connected(struct tevent_req *req)
1818 struct fd_struct *pfd = tevent_req_callback_data(
1819 req, struct fd_struct);
1820 int fd;
1821 NTSTATUS status;
1823 status = open_socket_out_defer_recv(req, &fd);
1824 if (NT_STATUS_IS_OK(status)) {
1825 pfd->fd = fd;
1829 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
1830 uint16_t *port, int timeout, int *pfd)
1832 struct event_context *ev;
1833 struct tevent_req *r139, *r445;
1834 struct fd_struct *fd139, *fd445;
1835 NTSTATUS status = NT_STATUS_NO_MEMORY;
1837 if (*port != 0) {
1838 return open_socket_out(pss, *port, timeout, pfd);
1841 ev = event_context_init(talloc_tos());
1842 if (ev == NULL) {
1843 return NT_STATUS_NO_MEMORY;
1846 fd139 = talloc(ev, struct fd_struct);
1847 if (fd139 == NULL) {
1848 goto done;
1850 fd139->fd = -1;
1852 fd445 = talloc(ev, struct fd_struct);
1853 if (fd445 == NULL) {
1854 goto done;
1856 fd445->fd = -1;
1858 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
1859 pss, 445, timeout);
1860 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
1861 pss, 139, timeout);
1862 if ((r445 == NULL) || (r139 == NULL)) {
1863 goto done;
1865 tevent_req_set_callback(r445, smb_sock_connected, fd445);
1866 tevent_req_set_callback(r139, smb_sock_connected, fd139);
1868 while ((fd445->fd == -1) && (fd139->fd == -1)
1869 && (tevent_req_is_in_progress(r139)
1870 || tevent_req_is_in_progress(r445))) {
1871 event_loop_once(ev);
1874 if ((fd139->fd != -1) && (fd445->fd != -1)) {
1875 close(fd139->fd);
1876 fd139->fd = -1;
1879 if (fd445->fd != -1) {
1880 *port = 445;
1881 *pfd = fd445->fd;
1882 status = NT_STATUS_OK;
1883 goto done;
1885 if (fd139->fd != -1) {
1886 *port = 139;
1887 *pfd = fd139->fd;
1888 status = NT_STATUS_OK;
1889 goto done;
1892 status = open_socket_out_defer_recv(r445, &fd445->fd);
1893 done:
1894 TALLOC_FREE(ev);
1895 return status;
1898 /****************************************************************************
1899 Open the client sockets.
1900 ****************************************************************************/
1902 NTSTATUS cli_connect(struct cli_state *cli,
1903 const char *host,
1904 struct sockaddr_storage *dest_ss)
1907 int name_type = 0x20;
1908 TALLOC_CTX *frame = talloc_stackframe();
1909 unsigned int num_addrs = 0;
1910 unsigned int i = 0;
1911 struct sockaddr_storage *ss_arr = NULL;
1912 char *p = NULL;
1914 /* reasonable default hostname */
1915 if (!host) {
1916 host = STAR_SMBSERVER;
1919 fstrcpy(cli->desthost, host);
1921 /* allow hostnames of the form NAME#xx and do a netbios lookup */
1922 if ((p = strchr(cli->desthost, '#'))) {
1923 name_type = strtol(p+1, NULL, 16);
1924 *p = 0;
1927 if (!dest_ss || is_zero_addr((struct sockaddr *)dest_ss)) {
1928 NTSTATUS status =resolve_name_list(frame,
1929 cli->desthost,
1930 name_type,
1931 &ss_arr,
1932 &num_addrs);
1933 if (!NT_STATUS_IS_OK(status)) {
1934 TALLOC_FREE(frame);
1935 return NT_STATUS_BAD_NETWORK_NAME;
1937 } else {
1938 num_addrs = 1;
1939 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
1940 if (!ss_arr) {
1941 TALLOC_FREE(frame);
1942 return NT_STATUS_NO_MEMORY;
1944 *ss_arr = *dest_ss;
1947 for (i = 0; i < num_addrs; i++) {
1948 cli->dest_ss = ss_arr[i];
1949 if (getenv("LIBSMB_PROG")) {
1950 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
1951 } else {
1952 uint16_t port = cli->port;
1953 NTSTATUS status;
1954 status = open_smb_socket(&cli->dest_ss, &port,
1955 cli->timeout, &cli->fd);
1956 if (NT_STATUS_IS_OK(status)) {
1957 cli->port = port;
1960 if (cli->fd == -1) {
1961 char addr[INET6_ADDRSTRLEN];
1962 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
1963 DEBUG(2,("Error connecting to %s (%s)\n",
1964 dest_ss?addr:host,strerror(errno)));
1965 } else {
1966 /* Exit from loop on first connection. */
1967 break;
1971 if (cli->fd == -1) {
1972 TALLOC_FREE(frame);
1973 return map_nt_error_from_unix(errno);
1976 if (dest_ss) {
1977 *dest_ss = cli->dest_ss;
1980 set_socket_options(cli->fd, lp_socket_options());
1982 TALLOC_FREE(frame);
1983 return NT_STATUS_OK;
1987 establishes a connection to after the negprot.
1988 @param output_cli A fully initialised cli structure, non-null only on success
1989 @param dest_host The netbios name of the remote host
1990 @param dest_ss (optional) The the destination IP, NULL for name based lookup
1991 @param port (optional) The destination port (0 for default)
1992 @param retry bool. Did this connection fail with a retryable error ?
1995 NTSTATUS cli_start_connection(struct cli_state **output_cli,
1996 const char *my_name,
1997 const char *dest_host,
1998 struct sockaddr_storage *dest_ss, int port,
1999 int signing_state, int flags,
2000 bool *retry)
2002 NTSTATUS nt_status;
2003 struct nmb_name calling;
2004 struct nmb_name called;
2005 struct cli_state *cli;
2006 struct sockaddr_storage ss;
2008 if (retry)
2009 *retry = False;
2011 if (!my_name)
2012 my_name = global_myname();
2014 if (!(cli = cli_initialise_ex(signing_state))) {
2015 return NT_STATUS_NO_MEMORY;
2018 make_nmb_name(&calling, my_name, 0x0);
2019 make_nmb_name(&called , dest_host, 0x20);
2021 cli_set_port(cli, port);
2022 cli_set_timeout(cli, 10000); /* 10 seconds. */
2024 if (dest_ss) {
2025 ss = *dest_ss;
2026 } else {
2027 zero_sockaddr(&ss);
2030 again:
2032 DEBUG(3,("Connecting to host=%s\n", dest_host));
2034 nt_status = cli_connect(cli, dest_host, &ss);
2035 if (!NT_STATUS_IS_OK(nt_status)) {
2036 char addr[INET6_ADDRSTRLEN];
2037 print_sockaddr(addr, sizeof(addr), &ss);
2038 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
2039 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
2040 cli_shutdown(cli);
2041 return nt_status;
2044 if (retry)
2045 *retry = True;
2047 if (!cli_session_request(cli, &calling, &called)) {
2048 char *p;
2049 DEBUG(1,("session request to %s failed (%s)\n",
2050 called.name, cli_errstr(cli)));
2051 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
2052 *p = 0;
2053 goto again;
2055 if (strcmp(called.name, STAR_SMBSERVER)) {
2056 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
2057 goto again;
2059 return NT_STATUS_BAD_NETWORK_NAME;
2062 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
2063 cli->use_spnego = False;
2064 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
2065 cli->use_kerberos = True;
2067 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
2068 cli->use_kerberos) {
2069 cli->fallback_after_kerberos = true;
2072 nt_status = cli_negprot(cli);
2073 if (!NT_STATUS_IS_OK(nt_status)) {
2074 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2075 cli_shutdown(cli);
2076 return nt_status;
2079 *output_cli = cli;
2080 return NT_STATUS_OK;
2085 establishes a connection right up to doing tconX, password specified.
2086 @param output_cli A fully initialised cli structure, non-null only on success
2087 @param dest_host The netbios name of the remote host
2088 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2089 @param port (optional) The destination port (0 for default)
2090 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2091 @param service_type The 'type' of serivice.
2092 @param user Username, unix string
2093 @param domain User's domain
2094 @param password User's password, unencrypted unix string.
2095 @param retry bool. Did this connection fail with a retryable error ?
2098 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2099 const char *my_name,
2100 const char *dest_host,
2101 struct sockaddr_storage *dest_ss, int port,
2102 const char *service, const char *service_type,
2103 const char *user, const char *domain,
2104 const char *password, int flags,
2105 int signing_state,
2106 bool *retry)
2108 NTSTATUS nt_status;
2109 struct cli_state *cli = NULL;
2110 int pw_len = password ? strlen(password)+1 : 0;
2112 *output_cli = NULL;
2114 if (password == NULL) {
2115 password = "";
2118 nt_status = cli_start_connection(&cli, my_name, dest_host,
2119 dest_ss, port, signing_state,
2120 flags, retry);
2122 if (!NT_STATUS_IS_OK(nt_status)) {
2123 return nt_status;
2126 nt_status = cli_session_setup(cli, user, password, pw_len, password,
2127 pw_len, domain);
2128 if (!NT_STATUS_IS_OK(nt_status)) {
2130 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2131 DEBUG(1,("failed session setup with %s\n",
2132 nt_errstr(nt_status)));
2133 cli_shutdown(cli);
2134 return nt_status;
2137 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2138 if (!NT_STATUS_IS_OK(nt_status)) {
2139 DEBUG(1,("anonymous failed session setup with %s\n",
2140 nt_errstr(nt_status)));
2141 cli_shutdown(cli);
2142 return nt_status;
2146 if (service) {
2147 nt_status = cli_tcon_andx(cli, service, service_type, password,
2148 pw_len);
2149 if (!NT_STATUS_IS_OK(nt_status)) {
2150 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2151 cli_shutdown(cli);
2152 if (NT_STATUS_IS_OK(nt_status)) {
2153 nt_status = NT_STATUS_UNSUCCESSFUL;
2155 return nt_status;
2159 nt_status = cli_init_creds(cli, user, domain, password);
2160 if (!NT_STATUS_IS_OK(nt_status)) {
2161 cli_shutdown(cli);
2162 return nt_status;
2165 *output_cli = cli;
2166 return NT_STATUS_OK;
2169 /****************************************************************************
2170 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2171 ****************************************************************************/
2173 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
2174 struct sockaddr_storage *pdest_ss)
2176 struct nmb_name calling, called;
2178 make_nmb_name(&calling, srchost, 0x0);
2181 * If the called name is an IP address
2182 * then use *SMBSERVER immediately.
2185 if(is_ipaddress(desthost)) {
2186 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
2187 } else {
2188 make_nmb_name(&called, desthost, 0x20);
2191 if (!cli_session_request(*ppcli, &calling, &called)) {
2192 NTSTATUS status;
2193 struct nmb_name smbservername;
2195 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
2198 * If the name wasn't *SMBSERVER then
2199 * try with *SMBSERVER if the first name fails.
2202 if (nmb_name_equal(&called, &smbservername)) {
2205 * The name used was *SMBSERVER, don't bother with another name.
2208 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2209 with error %s.\n", desthost, cli_errstr(*ppcli) ));
2210 return False;
2213 /* Try again... */
2214 cli_shutdown(*ppcli);
2216 *ppcli = cli_initialise();
2217 if (!*ppcli) {
2218 /* Out of memory... */
2219 return False;
2222 status = cli_connect(*ppcli, desthost, pdest_ss);
2223 if (!NT_STATUS_IS_OK(status) ||
2224 !cli_session_request(*ppcli, &calling, &smbservername)) {
2225 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2226 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
2227 return False;
2231 return True;
2234 /****************************************************************************
2235 Send an old style tcon.
2236 ****************************************************************************/
2237 NTSTATUS cli_raw_tcon(struct cli_state *cli,
2238 const char *service, const char *pass, const char *dev,
2239 uint16 *max_xmit, uint16 *tid)
2241 char *p;
2243 if (!lp_client_plaintext_auth() && (*pass)) {
2244 DEBUG(1, ("Server requested plaintext password but 'client "
2245 "plaintext auth' is disabled\n"));
2246 return NT_STATUS_ACCESS_DENIED;
2249 memset(cli->outbuf,'\0',smb_size);
2250 memset(cli->inbuf,'\0',smb_size);
2252 cli_set_message(cli->outbuf, 0, 0, True);
2253 SCVAL(cli->outbuf,smb_com,SMBtcon);
2254 cli_setup_packet(cli);
2256 p = smb_buf(cli->outbuf);
2257 *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
2258 *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
2259 *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
2261 cli_setup_bcc(cli, p);
2263 cli_send_smb(cli);
2264 if (!cli_receive_smb(cli)) {
2265 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2268 if (cli_is_error(cli)) {
2269 return cli_nt_error(cli);
2272 *max_xmit = SVAL(cli->inbuf, smb_vwv0);
2273 *tid = SVAL(cli->inbuf, smb_vwv1);
2275 return NT_STATUS_OK;
2278 /* Return a cli_state pointing at the IPC$ share for the given server */
2280 struct cli_state *get_ipc_connect(char *server,
2281 struct sockaddr_storage *server_ss,
2282 const struct user_auth_info *user_info)
2284 struct cli_state *cli;
2285 NTSTATUS nt_status;
2286 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2288 if (user_info->use_kerberos) {
2289 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2292 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
2293 user_info->username ? user_info->username : "",
2294 lp_workgroup(),
2295 user_info->password ? user_info->password : "",
2296 flags,
2297 Undefined, NULL);
2299 if (NT_STATUS_IS_OK(nt_status)) {
2300 return cli;
2301 } else if (is_ipaddress(server)) {
2302 /* windows 9* needs a correct NMB name for connections */
2303 fstring remote_name;
2305 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2306 cli = get_ipc_connect(remote_name, server_ss, user_info);
2307 if (cli)
2308 return cli;
2311 return NULL;
2315 * Given the IP address of a master browser on the network, return its
2316 * workgroup and connect to it.
2318 * This function is provided to allow additional processing beyond what
2319 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2320 * browsers and obtain each master browsers' list of domains (in case the
2321 * first master browser is recently on the network and has not yet
2322 * synchronized with other master browsers and therefore does not yet have the
2323 * entire network browse list)
2326 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2327 struct ip_service *mb_ip,
2328 const struct user_auth_info *user_info,
2329 char **pp_workgroup_out)
2331 char addr[INET6_ADDRSTRLEN];
2332 fstring name;
2333 struct cli_state *cli;
2334 struct sockaddr_storage server_ss;
2336 *pp_workgroup_out = NULL;
2338 print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2339 DEBUG(99, ("Looking up name of master browser %s\n",
2340 addr));
2343 * Do a name status query to find out the name of the master browser.
2344 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2345 * master browser will not respond to a wildcard query (or, at least,
2346 * an NT4 server acting as the domain master browser will not).
2348 * We might be able to use ONLY the query on MSBROWSE, but that's not
2349 * yet been tested with all Windows versions, so until it is, leave
2350 * the original wildcard query as the first choice and fall back to
2351 * MSBROWSE if the wildcard query fails.
2353 if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2354 !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2356 DEBUG(99, ("Could not retrieve name status for %s\n",
2357 addr));
2358 return NULL;
2361 if (!find_master_ip(name, &server_ss)) {
2362 DEBUG(99, ("Could not find master ip for %s\n", name));
2363 return NULL;
2366 *pp_workgroup_out = talloc_strdup(ctx, name);
2368 DEBUG(4, ("found master browser %s, %s\n", name, addr));
2370 print_sockaddr(addr, sizeof(addr), &server_ss);
2371 cli = get_ipc_connect(addr, &server_ss, user_info);
2373 return cli;
2377 * Return the IP address and workgroup of a master browser on the network, and
2378 * connect to it.
2381 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2382 const struct user_auth_info *user_info,
2383 char **pp_workgroup_out)
2385 struct ip_service *ip_list;
2386 struct cli_state *cli;
2387 int i, count;
2389 *pp_workgroup_out = NULL;
2391 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2393 /* Go looking for workgroups by broadcasting on the local network */
2395 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2396 &count))) {
2397 DEBUG(99, ("No master browsers responded\n"));
2398 return False;
2401 for (i = 0; i < count; i++) {
2402 char addr[INET6_ADDRSTRLEN];
2403 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2404 DEBUG(99, ("Found master browser %s\n", addr));
2406 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2407 user_info, pp_workgroup_out);
2408 if (cli)
2409 return(cli);
2412 return NULL;