Samba3-HOWTO: Fix usage of 'net idmap restore'.
[Samba.git] / source / libsmb / cliconnect.c
blobb2425e32ec73d677aaa29a828bb7496900f0355f
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 2 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, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "includes.h"
24 extern pstring user_socket_options;
26 static const struct {
27 int prot;
28 const char *name;
29 } prots[] = {
30 {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
31 {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
32 {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
33 {PROTOCOL_LANMAN1,"LANMAN1.0"},
34 {PROTOCOL_LANMAN2,"LM1.2X002"},
35 {PROTOCOL_LANMAN2,"DOS LANMAN2.1"},
36 {PROTOCOL_LANMAN2,"LANMAN2.1"},
37 {PROTOCOL_LANMAN2,"Samba"},
38 {PROTOCOL_NT1,"NT LANMAN 1.0"},
39 {PROTOCOL_NT1,"NT LM 0.12"},
40 {-1,NULL}
43 static const char *star_smbserver_name = "*SMBSERVER";
45 /**
46 * Set the user session key for a connection
47 * @param cli The cli structure to add it too
48 * @param session_key The session key used. (A copy of this is taken for the cli struct)
52 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
54 cli->user_session_key = data_blob(session_key.data, session_key.length);
57 /****************************************************************************
58 Do an old lanman2 style session setup.
59 ****************************************************************************/
61 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
62 const char *user,
63 const char *pass, size_t passlen,
64 const char *workgroup)
66 DATA_BLOB session_key = data_blob(NULL, 0);
67 DATA_BLOB lm_response = data_blob(NULL, 0);
68 fstring pword;
69 char *p;
71 if (passlen > sizeof(pword)-1) {
72 return NT_STATUS_INVALID_PARAMETER;
75 /* LANMAN servers predate NT status codes and Unicode and ignore those
76 smb flags so we must disable the corresponding default capabilities
77 that would otherwise cause the Unicode and NT Status flags to be
78 set (and even returned by the server) */
80 cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
82 /* if in share level security then don't send a password now */
83 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
84 passlen = 0;
86 if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
87 /* Encrypted mode needed, and non encrypted password supplied. */
88 lm_response = data_blob(NULL, 24);
89 if (!SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data)) {
90 DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n"));
91 return NT_STATUS_ACCESS_DENIED;
93 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
94 /* Encrypted mode needed, and encrypted password supplied. */
95 lm_response = data_blob(pass, passlen);
96 } else if (passlen > 0) {
97 /* Plaintext mode needed, assume plaintext supplied. */
98 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
99 lm_response = data_blob(pass, passlen);
102 /* send a session setup command */
103 memset(cli->outbuf,'\0',smb_size);
104 set_message(cli->outbuf,10, 0, True);
105 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
106 cli_setup_packet(cli);
108 SCVAL(cli->outbuf,smb_vwv0,0xFF);
109 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
110 SSVAL(cli->outbuf,smb_vwv3,2);
111 SSVAL(cli->outbuf,smb_vwv4,1);
112 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
113 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
115 p = smb_buf(cli->outbuf);
116 memcpy(p,lm_response.data,lm_response.length);
117 p += lm_response.length;
118 p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
119 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
120 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
121 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
122 cli_setup_bcc(cli, p);
124 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
125 return cli_nt_error(cli);
128 show_msg(cli->inbuf);
130 if (cli_is_error(cli)) {
131 return cli_nt_error(cli);
134 /* use the returned vuid from now on */
135 cli->vuid = SVAL(cli->inbuf,smb_uid);
136 fstrcpy(cli->user_name, user);
138 if (session_key.data) {
139 /* Have plaintext orginal */
140 cli_set_session_key(cli, session_key);
143 return NT_STATUS_OK;
146 /****************************************************************************
147 Work out suitable capabilities to offer the server.
148 ****************************************************************************/
150 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
152 uint32 capabilities = CAP_NT_SMBS;
154 if (!cli->force_dos_errors)
155 capabilities |= CAP_STATUS32;
157 if (cli->use_level_II_oplocks)
158 capabilities |= CAP_LEVEL_II_OPLOCKS;
160 capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
161 return capabilities;
164 /****************************************************************************
165 Do a NT1 guest session setup.
166 ****************************************************************************/
168 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
170 char *p;
171 uint32 capabilities = cli_session_setup_capabilities(cli);
173 memset(cli->outbuf, '\0', smb_size);
174 set_message(cli->outbuf,13,0,True);
175 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
176 cli_setup_packet(cli);
178 SCVAL(cli->outbuf,smb_vwv0,0xFF);
179 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
180 SSVAL(cli->outbuf,smb_vwv3,2);
181 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
182 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
183 SSVAL(cli->outbuf,smb_vwv7,0);
184 SSVAL(cli->outbuf,smb_vwv8,0);
185 SIVAL(cli->outbuf,smb_vwv11,capabilities);
186 p = smb_buf(cli->outbuf);
187 p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* username */
188 p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* workgroup */
189 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
190 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
191 cli_setup_bcc(cli, p);
193 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
194 return cli_nt_error(cli);
197 show_msg(cli->inbuf);
199 if (cli_is_error(cli)) {
200 return cli_nt_error(cli);
203 cli->vuid = SVAL(cli->inbuf,smb_uid);
205 p = smb_buf(cli->inbuf);
206 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
207 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
208 p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
210 if (strstr(cli->server_type, "Samba")) {
211 cli->is_samba = True;
214 fstrcpy(cli->user_name, "");
216 return NT_STATUS_OK;
219 /****************************************************************************
220 Do a NT1 plaintext session setup.
221 ****************************************************************************/
223 static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
224 const char *user, const char *pass,
225 const char *workgroup)
227 uint32 capabilities = cli_session_setup_capabilities(cli);
228 char *p;
229 fstring lanman;
231 fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
233 memset(cli->outbuf, '\0', smb_size);
234 set_message(cli->outbuf,13,0,True);
235 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
236 cli_setup_packet(cli);
238 SCVAL(cli->outbuf,smb_vwv0,0xFF);
239 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
240 SSVAL(cli->outbuf,smb_vwv3,2);
241 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
242 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
243 SSVAL(cli->outbuf,smb_vwv8,0);
244 SIVAL(cli->outbuf,smb_vwv11,capabilities);
245 p = smb_buf(cli->outbuf);
247 /* check wether to send the ASCII or UNICODE version of the password */
249 if ( (capabilities & CAP_UNICODE) == 0 ) {
250 p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
251 SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
252 } else {
253 /* For ucs2 passwords clistr_push calls ucs2_align, which causes
254 * the space taken by the unicode password to be one byte too
255 * long (as we're on an odd byte boundary here). Reduce the
256 * count by 1 to cope with this. Fixes smbclient against NetApp
257 * servers which can't cope. Fix from
258 * bryan.kolodziej@allenlund.com in bug #3840.
260 p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
261 SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))-1);
264 p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
265 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
266 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
267 p += clistr_push(cli, p, lanman, -1, STR_TERMINATE);
268 cli_setup_bcc(cli, p);
270 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
271 return cli_nt_error(cli);
274 show_msg(cli->inbuf);
276 if (cli_is_error(cli)) {
277 return cli_nt_error(cli);
280 cli->vuid = SVAL(cli->inbuf,smb_uid);
281 p = smb_buf(cli->inbuf);
282 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
283 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
284 p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
285 fstrcpy(cli->user_name, user);
287 if (strstr(cli->server_type, "Samba")) {
288 cli->is_samba = True;
291 return NT_STATUS_OK;
294 /****************************************************************************
295 do a NT1 NTLM/LM encrypted session setup - for when extended security
296 is not negotiated.
297 @param cli client state to create do session setup on
298 @param user username
299 @param pass *either* cleartext password (passlen !=24) or LM response.
300 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
301 @param workgroup The user's domain.
302 ****************************************************************************/
304 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
305 const char *pass, size_t passlen,
306 const char *ntpass, size_t ntpasslen,
307 const char *workgroup)
309 uint32 capabilities = cli_session_setup_capabilities(cli);
310 DATA_BLOB lm_response = data_blob(NULL, 0);
311 DATA_BLOB nt_response = data_blob(NULL, 0);
312 DATA_BLOB session_key = data_blob(NULL, 0);
313 NTSTATUS result;
314 char *p;
316 if (passlen == 0) {
317 /* do nothing - guest login */
318 } else if (passlen != 24) {
319 if (lp_client_ntlmv2_auth()) {
320 DATA_BLOB server_chal;
321 DATA_BLOB names_blob;
322 server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8));
324 /* note that the 'workgroup' here is a best guess - we don't know
325 the server's domain at this point. The 'server name' is also
326 dodgy...
328 names_blob = NTLMv2_generate_names_blob(cli->called.name, workgroup);
330 if (!SMBNTLMv2encrypt(user, workgroup, pass, &server_chal,
331 &names_blob,
332 &lm_response, &nt_response, &session_key)) {
333 data_blob_free(&names_blob);
334 data_blob_free(&server_chal);
335 return NT_STATUS_ACCESS_DENIED;
337 data_blob_free(&names_blob);
338 data_blob_free(&server_chal);
340 } else {
341 uchar nt_hash[16];
342 E_md4hash(pass, nt_hash);
344 #ifdef LANMAN_ONLY
345 nt_response = data_blob(NULL, 0);
346 #else
347 nt_response = data_blob(NULL, 24);
348 SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
349 #endif
350 /* non encrypted password supplied. Ignore ntpass. */
351 if (lp_client_lanman_auth()) {
352 lm_response = data_blob(NULL, 24);
353 if (!SMBencrypt(pass,cli->secblob.data, lm_response.data)) {
354 /* Oops, the LM response is invalid, just put
355 the NT response there instead */
356 data_blob_free(&lm_response);
357 lm_response = data_blob(nt_response.data, nt_response.length);
359 } else {
360 /* LM disabled, place NT# in LM field instead */
361 lm_response = data_blob(nt_response.data, nt_response.length);
364 session_key = data_blob(NULL, 16);
365 #ifdef LANMAN_ONLY
366 E_deshash(pass, session_key.data);
367 memset(&session_key.data[8], '\0', 8);
368 #else
369 SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
370 #endif
372 #ifdef LANMAN_ONLY
373 cli_simple_set_signing(cli, session_key, lm_response);
374 #else
375 cli_simple_set_signing(cli, session_key, nt_response);
376 #endif
377 } else {
378 /* pre-encrypted password supplied. Only used for
379 security=server, can't do
380 signing because we don't have original key */
382 lm_response = data_blob(pass, passlen);
383 nt_response = data_blob(ntpass, ntpasslen);
386 /* send a session setup command */
387 memset(cli->outbuf,'\0',smb_size);
389 set_message(cli->outbuf,13,0,True);
390 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
391 cli_setup_packet(cli);
393 SCVAL(cli->outbuf,smb_vwv0,0xFF);
394 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
395 SSVAL(cli->outbuf,smb_vwv3,2);
396 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
397 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
398 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
399 SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
400 SIVAL(cli->outbuf,smb_vwv11,capabilities);
401 p = smb_buf(cli->outbuf);
402 if (lm_response.length) {
403 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
405 if (nt_response.length) {
406 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
408 p += clistr_push(cli, p, user, -1, STR_TERMINATE);
410 /* Upper case here might help some NTLMv2 implementations */
411 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
412 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
413 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
414 cli_setup_bcc(cli, p);
416 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
417 result = cli_nt_error(cli);
418 goto end;
421 /* show_msg(cli->inbuf); */
423 if (cli_is_error(cli)) {
424 result = cli_nt_error(cli);
425 goto end;
428 /* use the returned vuid from now on */
429 cli->vuid = SVAL(cli->inbuf,smb_uid);
431 p = smb_buf(cli->inbuf);
432 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
433 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
434 p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
436 if (strstr(cli->server_type, "Samba")) {
437 cli->is_samba = True;
440 fstrcpy(cli->user_name, user);
442 if (session_key.data) {
443 /* Have plaintext orginal */
444 cli_set_session_key(cli, session_key);
447 result = NT_STATUS_OK;
448 end:
449 data_blob_free(&lm_response);
450 data_blob_free(&nt_response);
451 data_blob_free(&session_key);
452 return result;
455 /****************************************************************************
456 Send a extended security session setup blob
457 ****************************************************************************/
459 static BOOL cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob)
461 uint32 capabilities = cli_session_setup_capabilities(cli);
462 char *p;
464 capabilities |= CAP_EXTENDED_SECURITY;
466 /* send a session setup command */
467 memset(cli->outbuf,'\0',smb_size);
469 set_message(cli->outbuf,12,0,True);
470 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
472 cli_setup_packet(cli);
474 SCVAL(cli->outbuf,smb_vwv0,0xFF);
475 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
476 SSVAL(cli->outbuf,smb_vwv3,2);
477 SSVAL(cli->outbuf,smb_vwv4,1);
478 SIVAL(cli->outbuf,smb_vwv5,0);
479 SSVAL(cli->outbuf,smb_vwv7,blob.length);
480 SIVAL(cli->outbuf,smb_vwv10,capabilities);
481 p = smb_buf(cli->outbuf);
482 memcpy(p, blob.data, blob.length);
483 p += blob.length;
484 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
485 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
486 cli_setup_bcc(cli, p);
487 return cli_send_smb(cli);
490 /****************************************************************************
491 Send a extended security session setup blob, returning a reply blob.
492 ****************************************************************************/
494 static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli)
496 DATA_BLOB blob2 = data_blob(NULL, 0);
497 char *p;
498 size_t len;
500 if (!cli_receive_smb(cli))
501 return blob2;
503 show_msg(cli->inbuf);
505 if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli),
506 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
507 return blob2;
510 /* use the returned vuid from now on */
511 cli->vuid = SVAL(cli->inbuf,smb_uid);
513 p = smb_buf(cli->inbuf);
515 blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3));
517 p += blob2.length;
518 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
520 /* w2k with kerberos doesn't properly null terminate this field */
521 len = smb_buflen(cli->inbuf) - PTR_DIFF(p, smb_buf(cli->inbuf));
522 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), len, 0);
524 return blob2;
527 #ifdef HAVE_KRB5
528 /****************************************************************************
529 Send a extended security session setup blob, returning a reply blob.
530 ****************************************************************************/
532 /* The following is calculated from :
533 * (smb_size-4) = 35
534 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
535 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
536 * end of packet.
539 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
541 static BOOL cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob, DATA_BLOB session_key_krb5)
543 int32 remaining = blob.length;
544 int32 cur = 0;
545 DATA_BLOB send_blob = data_blob(NULL, 0);
546 int32 max_blob_size = 0;
547 DATA_BLOB receive_blob = data_blob(NULL, 0);
549 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
550 DEBUG(0,("cli_session_setup_blob: cli->max_xmit too small "
551 "(was %u, need minimum %u)\n",
552 (unsigned int)cli->max_xmit,
553 BASE_SESSSETUP_BLOB_PACKET_SIZE));
554 cli_set_nt_error(cli, NT_STATUS_INVALID_PARAMETER);
555 return False;
558 max_blob_size = cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE;
560 while ( remaining > 0) {
561 if (remaining >= max_blob_size) {
562 send_blob.length = max_blob_size;
563 remaining -= max_blob_size;
564 } else {
565 DATA_BLOB null_blob = data_blob(NULL, 0);
567 send_blob.length = remaining;
568 remaining = 0;
570 /* This is the last packet in the sequence - turn signing on. */
571 cli_simple_set_signing(cli, session_key_krb5, null_blob);
574 send_blob.data = &blob.data[cur];
575 cur += send_blob.length;
577 DEBUG(10, ("cli_session_setup_blob: Remaining (%u) sending (%u) current (%u)\n",
578 (unsigned int)remaining,
579 (unsigned int)send_blob.length,
580 (unsigned int)cur ));
582 if (!cli_session_setup_blob_send(cli, send_blob)) {
583 DEBUG(0, ("cli_session_setup_blob: send failed\n"));
584 return False;
587 receive_blob = cli_session_setup_blob_receive(cli);
588 data_blob_free(&receive_blob);
590 if (cli_is_error(cli) &&
591 !NT_STATUS_EQUAL( cli_get_nt_error(cli),
592 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
593 DEBUG(0, ("cli_session_setup_blob: recieve failed (%s)\n",
594 nt_errstr(cli_get_nt_error(cli)) ));
595 cli->vuid = 0;
596 return False;
600 return True;
603 /****************************************************************************
604 Use in-memory credentials cache
605 ****************************************************************************/
607 static void use_in_memory_ccache(void) {
608 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
611 /****************************************************************************
612 Do a spnego/kerberos encrypted session setup.
613 ****************************************************************************/
615 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
617 DATA_BLOB negTokenTarg;
618 DATA_BLOB session_key_krb5;
619 int rc;
621 DEBUG(2,("Doing kerberos session setup\n"));
623 /* generate the encapsulated kerberos5 ticket */
624 rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5, 0, NULL);
626 if (rc) {
627 DEBUG(1, ("cli_session_setup_kerberos: spnego_gen_negTokenTarg failed: %s\n",
628 error_message(rc)));
629 return ADS_ERROR_KRB5(rc);
632 #if 0
633 file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
634 #endif
636 if (!cli_session_setup_blob(cli, negTokenTarg, session_key_krb5)) {
637 data_blob_free(&negTokenTarg);
638 data_blob_free(&session_key_krb5);
639 return ADS_ERROR_NT(cli_nt_error(cli));
642 cli_set_session_key(cli, session_key_krb5);
644 data_blob_free(&negTokenTarg);
645 data_blob_free(&session_key_krb5);
647 if (cli_is_error(cli)) {
648 if (NT_STATUS_IS_OK(cli_nt_error(cli))) {
649 return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
652 return ADS_ERROR_NT(cli_nt_error(cli));
654 #endif /* HAVE_KRB5 */
657 /****************************************************************************
658 Do a spnego/NTLMSSP encrypted session setup.
659 ****************************************************************************/
661 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
662 const char *pass, const char *domain)
664 struct ntlmssp_state *ntlmssp_state;
665 NTSTATUS nt_status;
666 int turn = 1;
667 DATA_BLOB msg1;
668 DATA_BLOB blob = data_blob(NULL, 0);
669 DATA_BLOB blob_in = data_blob(NULL, 0);
670 DATA_BLOB blob_out = data_blob(NULL, 0);
672 cli_temp_set_signing(cli);
674 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
675 return nt_status;
677 ntlmssp_want_feature(ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
679 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
680 return nt_status;
682 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
683 return nt_status;
685 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
686 return nt_status;
689 do {
690 nt_status = ntlmssp_update(ntlmssp_state,
691 blob_in, &blob_out);
692 data_blob_free(&blob_in);
693 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(nt_status)) {
694 if (turn == 1) {
695 /* and wrap it in a SPNEGO wrapper */
696 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
697 } else {
698 /* wrap it in SPNEGO */
699 msg1 = spnego_gen_auth(blob_out);
702 /* now send that blob on its way */
703 if (!cli_session_setup_blob_send(cli, msg1)) {
704 DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
705 nt_status = NT_STATUS_UNSUCCESSFUL;
706 } else {
707 blob = cli_session_setup_blob_receive(cli);
709 nt_status = cli_nt_error(cli);
710 if (cli_is_error(cli) && NT_STATUS_IS_OK(nt_status)) {
711 if (cli->smb_rw_error == READ_BAD_SIG) {
712 nt_status = NT_STATUS_ACCESS_DENIED;
713 } else {
714 nt_status = NT_STATUS_UNSUCCESSFUL;
718 data_blob_free(&msg1);
721 if (!blob.length) {
722 if (NT_STATUS_IS_OK(nt_status)) {
723 nt_status = NT_STATUS_UNSUCCESSFUL;
725 } else if ((turn == 1) &&
726 NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
727 DATA_BLOB tmp_blob = data_blob(NULL, 0);
728 /* the server might give us back two challenges */
729 if (!spnego_parse_challenge(blob, &blob_in,
730 &tmp_blob)) {
731 DEBUG(3,("Failed to parse challenges\n"));
732 nt_status = NT_STATUS_INVALID_PARAMETER;
734 data_blob_free(&tmp_blob);
735 } else {
736 if (!spnego_parse_auth_response(blob, nt_status,
737 &blob_in)) {
738 DEBUG(3,("Failed to parse auth response\n"));
739 if (NT_STATUS_IS_OK(nt_status)
740 || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED))
741 nt_status = NT_STATUS_INVALID_PARAMETER;
744 data_blob_free(&blob);
745 data_blob_free(&blob_out);
746 turn++;
747 } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
749 data_blob_free(&blob_in);
751 if (NT_STATUS_IS_OK(nt_status)) {
753 DATA_BLOB key = data_blob(ntlmssp_state->session_key.data,
754 ntlmssp_state->session_key.length);
755 DATA_BLOB null_blob = data_blob(NULL, 0);
756 BOOL res;
758 fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
759 cli_set_session_key(cli, ntlmssp_state->session_key);
761 res = cli_simple_set_signing(cli, key, null_blob);
763 data_blob_free(&key);
765 if (res) {
767 /* 'resign' the last message, so we get the right sequence numbers
768 for checking the first reply from the server */
769 cli_calculate_sign_mac(cli);
771 if (!cli_check_sign_mac(cli)) {
772 nt_status = NT_STATUS_ACCESS_DENIED;
777 /* we have a reference conter on ntlmssp_state, if we are signing
778 then the state will be kept by the signing engine */
780 ntlmssp_end(&ntlmssp_state);
782 if (!NT_STATUS_IS_OK(nt_status)) {
783 cli->vuid = 0;
785 return nt_status;
788 /****************************************************************************
789 Do a spnego encrypted session setup.
791 user_domain: The shortname of the domain the user/machine is a member of.
792 dest_realm: The realm we're connecting to, if NULL we use our default realm.
793 ****************************************************************************/
795 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
796 const char *pass, const char *user_domain,
797 const char * dest_realm)
799 char *principal = NULL;
800 char *OIDs[ASN1_MAX_OIDS];
801 int i;
802 BOOL got_kerberos_mechanism = False;
803 DATA_BLOB blob;
805 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
807 /* the server might not even do spnego */
808 if (cli->secblob.length <= 16) {
809 DEBUG(3,("server didn't supply a full spnego negprot\n"));
810 goto ntlmssp;
813 #if 0
814 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
815 #endif
817 /* there is 16 bytes of GUID before the real spnego packet starts */
818 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
820 /* The server sent us the first part of the SPNEGO exchange in the
821 * negprot reply. It is WRONG to depend on the principal sent in the
822 * negprot reply, but right now we do it. If we don't receive one,
823 * we try to best guess, then fall back to NTLM. */
824 if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
825 data_blob_free(&blob);
826 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
828 data_blob_free(&blob);
830 /* make sure the server understands kerberos */
831 for (i=0;OIDs[i];i++) {
832 DEBUG(3,("got OID=%s\n", OIDs[i]));
833 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
834 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
835 got_kerberos_mechanism = True;
837 free(OIDs[i]);
840 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
842 fstrcpy(cli->user_name, user);
844 #ifdef HAVE_KRB5
845 /* If password is set we reauthenticate to kerberos server
846 * and do not store results */
848 if (got_kerberos_mechanism && cli->use_kerberos) {
849 ADS_STATUS rc;
851 if (pass && *pass) {
852 int ret;
854 use_in_memory_ccache();
855 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
857 if (ret){
858 SAFE_FREE(principal);
859 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
860 if (cli->fallback_after_kerberos)
861 goto ntlmssp;
862 return ADS_ERROR_KRB5(ret);
866 /* If we get a bad principal, try to guess it if
867 we have a valid host NetBIOS name.
869 if (strequal(principal, ADS_IGNORE_PRINCIPAL)) {
870 SAFE_FREE(principal);
872 if (principal == NULL &&
873 !is_ipaddress(cli->desthost) &&
874 !strequal(star_smbserver_name,
875 cli->desthost)) {
876 char *realm = NULL;
877 char *machine = NULL;
878 char *host = NULL;
879 DEBUG(3,("cli_session_setup_spnego: got a "
880 "bad server principal, trying to guess ...\n"));
882 host = strchr_m(cli->desthost, '.');
883 if (host) {
884 machine = SMB_STRNDUP(cli->desthost,
885 host - cli->desthost);
886 } else {
887 machine = SMB_STRDUP(cli->desthost);
889 if (machine == NULL) {
890 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
893 if (dest_realm) {
894 realm = SMB_STRDUP(dest_realm);
895 strupper_m(realm);
896 } else {
897 realm = kerberos_get_default_realm_from_ccache();
899 if (realm && *realm) {
900 if (asprintf(&principal, "%s$@%s",
901 machine, realm) < 0) {
902 SAFE_FREE(machine);
903 SAFE_FREE(realm);
904 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
906 DEBUG(3,("cli_session_setup_spnego: guessed "
907 "server principal=%s\n",
908 principal ? principal : "<null>"));
910 SAFE_FREE(machine);
911 SAFE_FREE(realm);
914 if (principal) {
915 rc = cli_session_setup_kerberos(cli, principal,
916 dest_realm);
917 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
918 SAFE_FREE(principal);
919 return rc;
923 #endif
925 SAFE_FREE(principal);
927 ntlmssp:
929 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, user, pass,
930 user_domain));
933 /****************************************************************************
934 Send a session setup. The username and workgroup is in UNIX character
935 format and must be converted to DOS codepage format before sending. If the
936 password is in plaintext, the same should be done.
937 ****************************************************************************/
939 NTSTATUS cli_session_setup(struct cli_state *cli,
940 const char *user,
941 const char *pass, int passlen,
942 const char *ntpass, int ntpasslen,
943 const char *workgroup)
945 char *p;
946 fstring user2;
948 /* allow for workgroups as part of the username */
949 fstrcpy(user2, user);
950 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
951 (p=strchr_m(user2,*lp_winbind_separator()))) {
952 *p = 0;
953 user = p+1;
954 workgroup = user2;
957 if (cli->protocol < PROTOCOL_LANMAN1) {
958 return NT_STATUS_OK;
961 /* now work out what sort of session setup we are going to
962 do. I have split this into separate functions to make the
963 flow a bit easier to understand (tridge) */
965 /* if its an older server then we have to use the older request format */
967 if (cli->protocol < PROTOCOL_NT1) {
968 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
969 DEBUG(1, ("Server requested LM password but 'client lanman auth'"
970 " is disabled\n"));
971 return NT_STATUS_ACCESS_DENIED;
974 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
975 !lp_client_plaintext_auth() && (*pass)) {
976 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
977 " is disabled\n"));
978 return NT_STATUS_ACCESS_DENIED;
981 return cli_session_setup_lanman2(cli, user, pass, passlen,
982 workgroup);
985 /* if no user is supplied then we have to do an anonymous connection.
986 passwords are ignored */
988 if (!user || !*user)
989 return cli_session_setup_guest(cli);
991 /* if the server is share level then send a plaintext null
992 password at this point. The password is sent in the tree
993 connect */
995 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
996 return cli_session_setup_plaintext(cli, user, "", workgroup);
998 /* if the server doesn't support encryption then we have to use
999 plaintext. The second password is ignored */
1001 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1002 if (!lp_client_plaintext_auth() && (*pass)) {
1003 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
1004 " is disabled\n"));
1005 return NT_STATUS_ACCESS_DENIED;
1007 return cli_session_setup_plaintext(cli, user, pass, workgroup);
1010 /* if the server supports extended security then use SPNEGO */
1012 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
1013 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
1014 workgroup, NULL);
1015 if (!ADS_ERR_OK(status)) {
1016 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1017 return ads_ntstatus(status);
1019 } else {
1020 NTSTATUS status;
1022 /* otherwise do a NT1 style session setup */
1023 status = cli_session_setup_nt1(cli, user, pass, passlen,
1024 ntpass, ntpasslen, workgroup);
1025 if (!NT_STATUS_IS_OK(status)) {
1026 DEBUG(3,("cli_session_setup: NT1 session setup "
1027 "failed: %s\n", nt_errstr(status)));
1028 return status;
1032 if (strstr(cli->server_type, "Samba")) {
1033 cli->is_samba = True;
1036 return NT_STATUS_OK;
1039 /****************************************************************************
1040 Send a uloggoff.
1041 *****************************************************************************/
1043 BOOL cli_ulogoff(struct cli_state *cli)
1045 memset(cli->outbuf,'\0',smb_size);
1046 set_message(cli->outbuf,2,0,True);
1047 SCVAL(cli->outbuf,smb_com,SMBulogoffX);
1048 cli_setup_packet(cli);
1049 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1050 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1052 cli_send_smb(cli);
1053 if (!cli_receive_smb(cli))
1054 return False;
1056 if (cli_is_error(cli)) {
1057 return False;
1060 cli->cnum = -1;
1061 return True;
1064 /****************************************************************************
1065 Send a tconX.
1066 ****************************************************************************/
1068 BOOL cli_send_tconX(struct cli_state *cli,
1069 const char *share, const char *dev, const char *pass, int passlen)
1071 fstring fullshare, pword;
1072 char *p;
1073 memset(cli->outbuf,'\0',smb_size);
1074 memset(cli->inbuf,'\0',smb_size);
1076 fstrcpy(cli->share, share);
1078 /* in user level security don't send a password now */
1079 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1080 passlen = 1;
1081 pass = "";
1082 } else if (!pass) {
1083 DEBUG(1, ("Server not using user level security and no password supplied.\n"));
1084 return False;
1087 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1088 *pass && passlen != 24) {
1089 if (!lp_client_lanman_auth()) {
1090 DEBUG(1, ("Server requested LANMAN password (share-level security) but 'client use lanman auth'"
1091 " is disabled\n"));
1092 return False;
1096 * Non-encrypted passwords - convert to DOS codepage before encryption.
1098 passlen = 24;
1099 SMBencrypt(pass,cli->secblob.data,(uchar *)pword);
1100 } else {
1101 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL|NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)) == 0) {
1102 if (!lp_client_plaintext_auth() && (*pass)) {
1103 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
1104 " is disabled\n"));
1105 return False;
1109 * Non-encrypted passwords - convert to DOS codepage before using.
1111 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
1113 } else {
1114 if (passlen) {
1115 memcpy(pword, pass, passlen);
1120 slprintf(fullshare, sizeof(fullshare)-1,
1121 "\\\\%s\\%s", cli->desthost, share);
1123 set_message(cli->outbuf,4, 0, True);
1124 SCVAL(cli->outbuf,smb_com,SMBtconX);
1125 cli_setup_packet(cli);
1127 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1128 SSVAL(cli->outbuf,smb_vwv2,TCONX_FLAG_EXTENDED_RESPONSE);
1129 SSVAL(cli->outbuf,smb_vwv3,passlen);
1131 p = smb_buf(cli->outbuf);
1132 if (passlen) {
1133 memcpy(p,pword,passlen);
1135 p += passlen;
1136 p += clistr_push(cli, p, fullshare, -1, STR_TERMINATE |STR_UPPER);
1137 p += clistr_push(cli, p, dev, -1, STR_TERMINATE |STR_UPPER | STR_ASCII);
1139 cli_setup_bcc(cli, p);
1141 cli_send_smb(cli);
1142 if (!cli_receive_smb(cli))
1143 return False;
1145 if (cli_is_error(cli))
1146 return False;
1148 clistr_pull(cli, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), -1, STR_TERMINATE|STR_ASCII);
1150 if (cli->protocol >= PROTOCOL_NT1 &&
1151 smb_buflen(cli->inbuf) == 3) {
1152 /* almost certainly win95 - enable bug fixes */
1153 cli->win95 = True;
1156 /* Make sure that we have the optional support 16-bit field. WCT > 2 */
1157 /* Avoids issues when connecting to Win9x boxes sharing files */
1159 cli->dfsroot = False;
1160 if ( (CVAL(cli->inbuf, smb_wct))>2 && cli->protocol >= PROTOCOL_LANMAN2 )
1161 cli->dfsroot = (SVAL( cli->inbuf, smb_vwv2 ) & SMB_SHARE_IN_DFS) ? True : False;
1163 cli->cnum = SVAL(cli->inbuf,smb_tid);
1164 return True;
1167 /****************************************************************************
1168 Send a tree disconnect.
1169 ****************************************************************************/
1171 BOOL cli_tdis(struct cli_state *cli)
1173 memset(cli->outbuf,'\0',smb_size);
1174 set_message(cli->outbuf,0,0,True);
1175 SCVAL(cli->outbuf,smb_com,SMBtdis);
1176 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1177 cli_setup_packet(cli);
1179 cli_send_smb(cli);
1180 if (!cli_receive_smb(cli))
1181 return False;
1183 if (cli_is_error(cli)) {
1184 return False;
1187 cli->cnum = -1;
1188 return True;
1191 /****************************************************************************
1192 Send a negprot command.
1193 ****************************************************************************/
1195 void cli_negprot_send(struct cli_state *cli)
1197 char *p;
1198 int numprots;
1200 if (cli->protocol < PROTOCOL_NT1)
1201 cli->use_spnego = False;
1203 memset(cli->outbuf,'\0',smb_size);
1205 /* setup the protocol strings */
1206 set_message(cli->outbuf,0,0,True);
1208 p = smb_buf(cli->outbuf);
1209 for (numprots=0;
1210 prots[numprots].name && prots[numprots].prot<=cli->protocol;
1211 numprots++) {
1212 *p++ = 2;
1213 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1216 SCVAL(cli->outbuf,smb_com,SMBnegprot);
1217 cli_setup_bcc(cli, p);
1218 cli_setup_packet(cli);
1220 SCVAL(smb_buf(cli->outbuf),0,2);
1222 cli_send_smb(cli);
1225 /****************************************************************************
1226 Send a negprot command.
1227 ****************************************************************************/
1229 BOOL cli_negprot(struct cli_state *cli)
1231 char *p;
1232 int numprots;
1233 int plength;
1235 if (cli->protocol < PROTOCOL_NT1)
1236 cli->use_spnego = False;
1238 memset(cli->outbuf,'\0',smb_size);
1240 /* setup the protocol strings */
1241 for (plength=0,numprots=0;
1242 prots[numprots].name && prots[numprots].prot<=cli->protocol;
1243 numprots++)
1244 plength += strlen(prots[numprots].name)+2;
1246 set_message(cli->outbuf,0,plength,True);
1248 p = smb_buf(cli->outbuf);
1249 for (numprots=0;
1250 prots[numprots].name && prots[numprots].prot<=cli->protocol;
1251 numprots++) {
1252 *p++ = 2;
1253 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1256 SCVAL(cli->outbuf,smb_com,SMBnegprot);
1257 cli_setup_packet(cli);
1259 SCVAL(smb_buf(cli->outbuf),0,2);
1261 cli_send_smb(cli);
1262 if (!cli_receive_smb(cli))
1263 return False;
1265 show_msg(cli->inbuf);
1267 if (cli_is_error(cli) ||
1268 ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
1269 return(False);
1272 cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
1274 if ((cli->protocol < PROTOCOL_NT1) && cli->sign_info.mandatory_signing) {
1275 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1276 return False;
1279 if (cli->protocol >= PROTOCOL_NT1) {
1280 struct timespec ts;
1281 /* NT protocol */
1282 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
1283 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
1284 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
1285 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
1286 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1);
1287 cli->serverzone *= 60;
1288 /* this time arrives in real GMT */
1289 ts = interpret_long_date(cli->inbuf+smb_vwv11+1);
1290 cli->servertime = ts.tv_sec;
1291 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
1292 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
1293 if (cli->capabilities & CAP_RAW_MODE) {
1294 cli->readbraw_supported = True;
1295 cli->writebraw_supported = True;
1297 /* work out if they sent us a workgroup */
1298 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1299 smb_buflen(cli->inbuf) > 8) {
1300 clistr_pull(cli, cli->server_domain,
1301 smb_buf(cli->inbuf)+8, sizeof(cli->server_domain),
1302 smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN);
1306 * As signing is slow we only turn it on if either the client or
1307 * the server require it. JRA.
1310 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
1311 /* Fail if server says signing is mandatory and we don't want to support it. */
1312 if (!cli->sign_info.allow_smb_signing) {
1313 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1314 return False;
1316 cli->sign_info.negotiated_smb_signing = True;
1317 cli->sign_info.mandatory_signing = True;
1318 } else if (cli->sign_info.mandatory_signing && cli->sign_info.allow_smb_signing) {
1319 /* Fail if client says signing is mandatory and the server doesn't support it. */
1320 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
1321 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1322 return False;
1324 cli->sign_info.negotiated_smb_signing = True;
1325 cli->sign_info.mandatory_signing = True;
1326 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
1327 cli->sign_info.negotiated_smb_signing = True;
1330 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
1331 SAFE_FREE(cli->outbuf);
1332 SAFE_FREE(cli->inbuf);
1333 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1334 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1335 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
1338 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1339 cli->use_spnego = False;
1340 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
1341 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
1342 cli->max_mux = SVAL(cli->inbuf, smb_vwv3);
1343 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
1344 cli->serverzone = SVALS(cli->inbuf,smb_vwv10);
1345 cli->serverzone *= 60;
1346 /* this time is converted to GMT by make_unix_date */
1347 cli->servertime = cli_make_unix_date(cli,cli->inbuf+smb_vwv8);
1348 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
1349 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
1350 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
1351 } else {
1352 /* the old core protocol */
1353 cli->use_spnego = False;
1354 cli->sec_mode = 0;
1355 cli->serverzone = get_time_zone(time(NULL));
1358 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1360 /* a way to force ascii SMB */
1361 if (getenv("CLI_FORCE_ASCII"))
1362 cli->capabilities &= ~CAP_UNICODE;
1364 return True;
1367 /****************************************************************************
1368 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1369 ****************************************************************************/
1371 BOOL cli_session_request(struct cli_state *cli,
1372 struct nmb_name *calling, struct nmb_name *called)
1374 char *p;
1375 int len = 4;
1377 memcpy(&(cli->calling), calling, sizeof(*calling));
1378 memcpy(&(cli->called ), called , sizeof(*called ));
1380 /* put in the destination name */
1381 p = cli->outbuf+len;
1382 name_mangle(cli->called .name, p, cli->called .name_type);
1383 len += name_len(p);
1385 /* and my name */
1386 p = cli->outbuf+len;
1387 name_mangle(cli->calling.name, p, cli->calling.name_type);
1388 len += name_len(p);
1390 /* 445 doesn't have session request */
1391 if (cli->port == 445)
1392 return True;
1394 /* send a session request (RFC 1002) */
1395 /* setup the packet length
1396 * Remove four bytes from the length count, since the length
1397 * field in the NBT Session Service header counts the number
1398 * of bytes which follow. The cli_send_smb() function knows
1399 * about this and accounts for those four bytes.
1400 * CRH.
1402 len -= 4;
1403 _smb_setlen(cli->outbuf,len);
1404 SCVAL(cli->outbuf,0,0x81);
1406 cli_send_smb(cli);
1407 DEBUG(5,("Sent session request\n"));
1409 if (!cli_receive_smb(cli))
1410 return False;
1412 if (CVAL(cli->inbuf,0) == 0x84) {
1413 /* C. Hoch 9/14/95 Start */
1414 /* For information, here is the response structure.
1415 * We do the byte-twiddling to for portability.
1416 struct RetargetResponse{
1417 unsigned char type;
1418 unsigned char flags;
1419 int16 length;
1420 int32 ip_addr;
1421 int16 port;
1424 int port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1425 /* SESSION RETARGET */
1426 putip((char *)&cli->dest_ip,cli->inbuf+4);
1428 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, LONG_CONNECT_TIMEOUT);
1429 if (cli->fd == -1)
1430 return False;
1432 DEBUG(3,("Retargeted\n"));
1434 set_socket_options(cli->fd,user_socket_options);
1436 /* Try again */
1438 static int depth;
1439 BOOL ret;
1440 if (depth > 4) {
1441 DEBUG(0,("Retarget recursion - failing\n"));
1442 return False;
1444 depth++;
1445 ret = cli_session_request(cli, calling, called);
1446 depth--;
1447 return ret;
1449 } /* C. Hoch 9/14/95 End */
1451 if (CVAL(cli->inbuf,0) != 0x82) {
1452 /* This is the wrong place to put the error... JRA. */
1453 cli->rap_error = CVAL(cli->inbuf,4);
1454 return False;
1456 return(True);
1459 /****************************************************************************
1460 Open the client sockets.
1461 ****************************************************************************/
1463 NTSTATUS cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
1465 int name_type = 0x20;
1466 char *p;
1468 /* reasonable default hostname */
1469 if (!host) host = star_smbserver_name;
1471 fstrcpy(cli->desthost, host);
1473 /* allow hostnames of the form NAME#xx and do a netbios lookup */
1474 if ((p = strchr(cli->desthost, '#'))) {
1475 name_type = strtol(p+1, NULL, 16);
1476 *p = 0;
1479 if (!ip || is_zero_ip(*ip)) {
1480 if (!resolve_name(cli->desthost, &cli->dest_ip, name_type)) {
1481 return NT_STATUS_BAD_NETWORK_NAME;
1483 if (ip) *ip = cli->dest_ip;
1484 } else {
1485 cli->dest_ip = *ip;
1488 if (getenv("LIBSMB_PROG")) {
1489 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
1490 } else {
1491 /* try 445 first, then 139 */
1492 int port = cli->port?cli->port:445;
1493 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
1494 port, cli->timeout);
1495 if (cli->fd == -1 && cli->port == 0) {
1496 port = 139;
1497 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
1498 port, cli->timeout);
1500 if (cli->fd != -1)
1501 cli->port = port;
1503 if (cli->fd == -1) {
1504 DEBUG(1,("Error connecting to %s (%s)\n",
1505 ip?inet_ntoa(*ip):host,strerror(errno)));
1506 return map_nt_error_from_unix(errno);
1509 set_socket_options(cli->fd,user_socket_options);
1511 return NT_STATUS_OK;
1515 establishes a connection to after the negprot.
1516 @param output_cli A fully initialised cli structure, non-null only on success
1517 @param dest_host The netbios name of the remote host
1518 @param dest_ip (optional) The the destination IP, NULL for name based lookup
1519 @param port (optional) The destination port (0 for default)
1520 @param retry BOOL. Did this connection fail with a retryable error ?
1523 NTSTATUS cli_start_connection(struct cli_state **output_cli,
1524 const char *my_name,
1525 const char *dest_host,
1526 struct in_addr *dest_ip, int port,
1527 int signing_state, int flags,
1528 BOOL *retry)
1530 NTSTATUS nt_status;
1531 struct nmb_name calling;
1532 struct nmb_name called;
1533 struct cli_state *cli;
1534 struct in_addr ip;
1536 if (retry)
1537 *retry = False;
1539 if (!my_name)
1540 my_name = global_myname();
1542 if (!(cli = cli_initialise())) {
1543 return NT_STATUS_NO_MEMORY;
1546 make_nmb_name(&calling, my_name, 0x0);
1547 make_nmb_name(&called , dest_host, 0x20);
1549 if (cli_set_port(cli, port) != port) {
1550 cli_shutdown(cli);
1551 return NT_STATUS_UNSUCCESSFUL;
1554 cli_set_timeout(cli, 10000); /* 10 seconds. */
1556 if (dest_ip)
1557 ip = *dest_ip;
1558 else
1559 ZERO_STRUCT(ip);
1561 again:
1563 DEBUG(3,("Connecting to host=%s\n", dest_host));
1565 nt_status = cli_connect(cli, dest_host, &ip);
1566 if (!NT_STATUS_IS_OK(nt_status)) {
1567 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
1568 nmb_namestr(&called), inet_ntoa(ip), nt_errstr(nt_status) ));
1569 cli_shutdown(cli);
1570 return nt_status;
1573 if (retry)
1574 *retry = True;
1576 if (!cli_session_request(cli, &calling, &called)) {
1577 char *p;
1578 DEBUG(1,("session request to %s failed (%s)\n",
1579 called.name, cli_errstr(cli)));
1580 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
1581 *p = 0;
1582 goto again;
1584 if (strcmp(called.name, star_smbserver_name)) {
1585 make_nmb_name(&called , star_smbserver_name, 0x20);
1586 goto again;
1588 return NT_STATUS_BAD_NETWORK_NAME;
1591 cli_setup_signing_state(cli, signing_state);
1593 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
1594 cli->use_spnego = False;
1595 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
1596 cli->use_kerberos = True;
1598 if (!cli_negprot(cli)) {
1599 DEBUG(1,("failed negprot\n"));
1600 nt_status = cli_nt_error(cli);
1601 if (NT_STATUS_IS_OK(nt_status)) {
1602 nt_status = NT_STATUS_UNSUCCESSFUL;
1604 cli_shutdown(cli);
1605 return nt_status;
1608 *output_cli = cli;
1609 return NT_STATUS_OK;
1614 establishes a connection right up to doing tconX, password specified.
1615 @param output_cli A fully initialised cli structure, non-null only on success
1616 @param dest_host The netbios name of the remote host
1617 @param dest_ip (optional) The the destination IP, NULL for name based lookup
1618 @param port (optional) The destination port (0 for default)
1619 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
1620 @param service_type The 'type' of serivice.
1621 @param user Username, unix string
1622 @param domain User's domain
1623 @param password User's password, unencrypted unix string.
1624 @param retry BOOL. Did this connection fail with a retryable error ?
1627 NTSTATUS cli_full_connection(struct cli_state **output_cli,
1628 const char *my_name,
1629 const char *dest_host,
1630 struct in_addr *dest_ip, int port,
1631 const char *service, const char *service_type,
1632 const char *user, const char *domain,
1633 const char *password, int flags,
1634 int signing_state,
1635 BOOL *retry)
1637 NTSTATUS nt_status;
1638 struct cli_state *cli = NULL;
1639 int pw_len = password ? strlen(password)+1 : 0;
1641 *output_cli = NULL;
1643 if (password == NULL) {
1644 password = "";
1647 nt_status = cli_start_connection(&cli, my_name, dest_host,
1648 dest_ip, port, signing_state, flags, retry);
1650 if (!NT_STATUS_IS_OK(nt_status)) {
1651 return nt_status;
1654 nt_status = cli_session_setup(cli, user, password, pw_len, password,
1655 pw_len, domain);
1656 if (!NT_STATUS_IS_OK(nt_status)) {
1658 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
1659 DEBUG(1,("failed session setup with %s\n",
1660 nt_errstr(nt_status)));
1661 cli_shutdown(cli);
1662 return nt_status;
1665 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
1666 if (!NT_STATUS_IS_OK(nt_status)) {
1667 DEBUG(1,("anonymous failed session setup with %s\n",
1668 nt_errstr(nt_status)));
1669 cli_shutdown(cli);
1670 return nt_status;
1674 if (service) {
1675 if (!cli_send_tconX(cli, service, service_type, password, pw_len)) {
1676 nt_status = cli_nt_error(cli);
1677 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
1678 cli_shutdown(cli);
1679 if (NT_STATUS_IS_OK(nt_status)) {
1680 nt_status = NT_STATUS_UNSUCCESSFUL;
1682 return nt_status;
1686 cli_init_creds(cli, user, domain, password);
1688 *output_cli = cli;
1689 return NT_STATUS_OK;
1692 /****************************************************************************
1693 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
1694 ****************************************************************************/
1696 BOOL attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
1697 struct in_addr *pdest_ip)
1699 struct nmb_name calling, called;
1701 make_nmb_name(&calling, srchost, 0x0);
1704 * If the called name is an IP address
1705 * then use *SMBSERVER immediately.
1708 if(is_ipaddress(desthost)) {
1709 make_nmb_name(&called, star_smbserver_name, 0x20);
1710 } else {
1711 make_nmb_name(&called, desthost, 0x20);
1714 if (!cli_session_request(*ppcli, &calling, &called)) {
1715 NTSTATUS status;
1716 struct nmb_name smbservername;
1718 make_nmb_name(&smbservername, star_smbserver_name, 0x20);
1721 * If the name wasn't *SMBSERVER then
1722 * try with *SMBSERVER if the first name fails.
1725 if (nmb_name_equal(&called, &smbservername)) {
1728 * The name used was *SMBSERVER, don't bother with another name.
1731 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
1732 with error %s.\n", desthost, cli_errstr(*ppcli) ));
1733 return False;
1736 /* Try again... */
1737 cli_shutdown(*ppcli);
1739 *ppcli = cli_initialise();
1740 if (!*ppcli) {
1741 /* Out of memory... */
1742 return False;
1745 status = cli_connect(*ppcli, desthost, pdest_ip);
1746 if (!NT_STATUS_IS_OK(status) ||
1747 !cli_session_request(*ppcli, &calling, &smbservername)) {
1748 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
1749 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
1750 return False;
1754 return True;
1761 /****************************************************************************
1762 Send an old style tcon.
1763 ****************************************************************************/
1764 NTSTATUS cli_raw_tcon(struct cli_state *cli,
1765 const char *service, const char *pass, const char *dev,
1766 uint16 *max_xmit, uint16 *tid)
1768 char *p;
1770 if (!lp_client_plaintext_auth() && (*pass)) {
1771 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
1772 " is disabled\n"));
1773 return NT_STATUS_ACCESS_DENIED;
1776 memset(cli->outbuf,'\0',smb_size);
1777 memset(cli->inbuf,'\0',smb_size);
1779 set_message(cli->outbuf, 0, 0, True);
1780 SCVAL(cli->outbuf,smb_com,SMBtcon);
1781 cli_setup_packet(cli);
1783 p = smb_buf(cli->outbuf);
1784 *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
1785 *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
1786 *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
1788 cli_setup_bcc(cli, p);
1790 cli_send_smb(cli);
1791 if (!cli_receive_smb(cli)) {
1792 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1795 if (cli_is_error(cli)) {
1796 return cli_nt_error(cli);
1799 *max_xmit = SVAL(cli->inbuf, smb_vwv0);
1800 *tid = SVAL(cli->inbuf, smb_vwv1);
1802 return NT_STATUS_OK;
1805 /* Return a cli_state pointing at the IPC$ share for the given server */
1807 struct cli_state *get_ipc_connect(char *server, struct in_addr *server_ip,
1808 struct user_auth_info *user_info)
1810 struct cli_state *cli;
1811 pstring myname;
1812 NTSTATUS nt_status;
1814 get_myname(myname);
1816 nt_status = cli_full_connection(&cli, myname, server, server_ip, 0, "IPC$", "IPC",
1817 user_info->username, lp_workgroup(), user_info->password,
1818 CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK, Undefined, NULL);
1820 if (NT_STATUS_IS_OK(nt_status)) {
1821 return cli;
1822 } else if (is_ipaddress(server)) {
1823 /* windows 9* needs a correct NMB name for connections */
1824 fstring remote_name;
1826 if (name_status_find("*", 0, 0, *server_ip, remote_name)) {
1827 cli = get_ipc_connect(remote_name, server_ip, user_info);
1828 if (cli)
1829 return cli;
1832 return NULL;
1836 * Given the IP address of a master browser on the network, return its
1837 * workgroup and connect to it.
1839 * This function is provided to allow additional processing beyond what
1840 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
1841 * browsers and obtain each master browsers' list of domains (in case the
1842 * first master browser is recently on the network and has not yet
1843 * synchronized with other master browsers and therefore does not yet have the
1844 * entire network browse list)
1847 struct cli_state *get_ipc_connect_master_ip(struct ip_service * mb_ip, pstring workgroup, struct user_auth_info *user_info)
1849 static fstring name;
1850 struct cli_state *cli;
1851 struct in_addr server_ip;
1853 DEBUG(99, ("Looking up name of master browser %s\n",
1854 inet_ntoa(mb_ip->ip)));
1857 * Do a name status query to find out the name of the master browser.
1858 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
1859 * master browser will not respond to a wildcard query (or, at least,
1860 * an NT4 server acting as the domain master browser will not).
1862 * We might be able to use ONLY the query on MSBROWSE, but that's not
1863 * yet been tested with all Windows versions, so until it is, leave
1864 * the original wildcard query as the first choice and fall back to
1865 * MSBROWSE if the wildcard query fails.
1867 if (!name_status_find("*", 0, 0x1d, mb_ip->ip, name) &&
1868 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip->ip, name)) {
1870 DEBUG(99, ("Could not retrieve name status for %s\n",
1871 inet_ntoa(mb_ip->ip)));
1872 return NULL;
1875 if (!find_master_ip(name, &server_ip)) {
1876 DEBUG(99, ("Could not find master ip for %s\n", name));
1877 return NULL;
1880 pstrcpy(workgroup, name);
1882 DEBUG(4, ("found master browser %s, %s\n",
1883 name, inet_ntoa(mb_ip->ip)));
1885 cli = get_ipc_connect(inet_ntoa(server_ip), &server_ip, user_info);
1887 return cli;
1892 * Return the IP address and workgroup of a master browser on the network, and
1893 * connect to it.
1896 struct cli_state *get_ipc_connect_master_ip_bcast(pstring workgroup, struct user_auth_info *user_info)
1898 struct ip_service *ip_list;
1899 struct cli_state *cli;
1900 int i, count;
1902 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
1904 /* Go looking for workgroups by broadcasting on the local network */
1906 if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) {
1907 DEBUG(99, ("No master browsers responded\n"));
1908 return False;
1911 for (i = 0; i < count; i++) {
1912 DEBUG(99, ("Found master browser %s\n", inet_ntoa(ip_list[i].ip)));
1914 cli = get_ipc_connect_master_ip(&ip_list[i], workgroup, user_info);
1915 if (cli)
1916 return(cli);
1919 return NULL;