1/*
2   Unix SMB/CIFS implementation.
3   client connect/disconnect routines
4   Copyright (C) Andrew Tridgell 1994-1998
5   Copyright (C) Andrew Bartlett 2001-2003
6
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.
11
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.
16
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.
20*/
21
22#define NO_SYSLOG
23
24#include "includes.h"
25
26
27static const struct {
28	int prot;
29	const char *name;
30} prots[] = {
31	{PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
32	{PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
33	{PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
34	{PROTOCOL_LANMAN1,"LANMAN1.0"},
35	{PROTOCOL_LANMAN2,"LM1.2X002"},
36	{PROTOCOL_LANMAN2,"DOS LANMAN2.1"},
37	{PROTOCOL_LANMAN2,"Samba"},
38	{PROTOCOL_NT1,"NT LANMAN 1.0"},
39	{PROTOCOL_NT1,"NT LM 0.12"},
40	{-1,NULL}
41};
42
43/**
44 * Set the user session key for a connection
45 * @param cli The cli structure to add it too
46 * @param session_key The session key used.  (A copy of this is taken for the cli struct)
47 *
48 */
49
50static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
51{
52	cli->user_session_key = data_blob(session_key.data, session_key.length);
53}
54
55/****************************************************************************
56 Do an old lanman2 style session setup.
57****************************************************************************/
58
59static BOOL cli_session_setup_lanman2(struct cli_state *cli, const char *user,
60				      const char *pass, size_t passlen, const char *workgroup)
61{
62	DATA_BLOB session_key = data_blob(NULL, 0);
63	DATA_BLOB lm_response = data_blob(NULL, 0);
64	fstring pword;
65	char *p;
66
67	if (passlen > sizeof(pword)-1)
68		return False;
69
70	/* LANMAN servers predate NT status codes and Unicode and ignore those
71	   smb flags so we must disable the corresponding default capabilities
72	   that would otherwise cause the Unicode and NT Status flags to be
73	   set (and even returned by the server) */
74
75	cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
76
77	/* if in share level security then don't send a password now */
78	if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
79		passlen = 0;
80
81	if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
82		/* Encrypted mode needed, and non encrypted password supplied. */
83		lm_response = data_blob(NULL, 24);
84		if (!SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data)) {
85			DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n"));
86			return False;
87		}
88	} else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
89		/* Encrypted mode needed, and encrypted password supplied. */
90		lm_response = data_blob(pass, passlen);
91	} else if (passlen > 0) {
92		/* Plaintext mode needed, assume plaintext supplied. */
93		passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
94		lm_response = data_blob(pass, passlen);
95	}
96
97	/* send a session setup command */
98	memset(cli->outbuf,'\0',smb_size);
99	set_message(cli->outbuf,10, 0, True);
100	SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
101	cli_setup_packet(cli);
102
103	SCVAL(cli->outbuf,smb_vwv0,0xFF);
104	SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
105	SSVAL(cli->outbuf,smb_vwv3,2);
106	SSVAL(cli->outbuf,smb_vwv4,1);
107	SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
108	SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
109
110	p = smb_buf(cli->outbuf);
111	memcpy(p,lm_response.data,lm_response.length);
112	p += lm_response.length;
113	p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
114	p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
115	p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
116	p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
117	cli_setup_bcc(cli, p);
118
119	cli_send_smb(cli);
120	if (!cli_receive_smb(cli))
121		return False;
122
123	show_msg(cli->inbuf);
124
125	if (cli_is_error(cli))
126		return False;
127
128	/* use the returned vuid from now on */
129	cli->vuid = SVAL(cli->inbuf,smb_uid);
130	fstrcpy(cli->user_name, user);
131
132	if (session_key.data) {
133		/* Have plaintext orginal */
134		cli_set_session_key(cli, session_key);
135	}
136
137	return True;
138}
139
140/****************************************************************************
141 Work out suitable capabilities to offer the server.
142****************************************************************************/
143
144static uint32 cli_session_setup_capabilities(struct cli_state *cli)
145{
146	uint32 capabilities = CAP_NT_SMBS;
147
148	if (!cli->force_dos_errors)
149		capabilities |= CAP_STATUS32;
150
151	if (cli->use_level_II_oplocks)
152		capabilities |= CAP_LEVEL_II_OPLOCKS;
153
154	capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
155	return capabilities;
156}
157
158/****************************************************************************
159 Do a NT1 guest session setup.
160****************************************************************************/
161
162static BOOL cli_session_setup_guest(struct cli_state *cli)
163{
164	char *p;
165	uint32 capabilities = cli_session_setup_capabilities(cli);
166
167	set_message(cli->outbuf,13,0,True);
168	SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
169	cli_setup_packet(cli);
170
171	SCVAL(cli->outbuf,smb_vwv0,0xFF);
172	SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
173	SSVAL(cli->outbuf,smb_vwv3,2);
174	SSVAL(cli->outbuf,smb_vwv4,cli->pid);
175	SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
176	SSVAL(cli->outbuf,smb_vwv7,0);
177	SSVAL(cli->outbuf,smb_vwv8,0);
178	SIVAL(cli->outbuf,smb_vwv11,capabilities);
179	p = smb_buf(cli->outbuf);
180	p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* username */
181	p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* workgroup */
182	p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
183	p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
184	cli_setup_bcc(cli, p);
185
186	cli_send_smb(cli);
187	if (!cli_receive_smb(cli))
188	      return False;
189
190	show_msg(cli->inbuf);
191
192	if (cli_is_error(cli))
193		return False;
194
195	cli->vuid = SVAL(cli->inbuf,smb_uid);
196
197	p = smb_buf(cli->inbuf);
198	p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
199	p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
200	p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
201
202	fstrcpy(cli->user_name, "");
203
204	return True;
205}
206
207/****************************************************************************
208 Do a NT1 plaintext session setup.
209****************************************************************************/
210
211static BOOL cli_session_setup_plaintext(struct cli_state *cli, const char *user,
212					const char *pass, const char *workgroup)
213{
214	uint32 capabilities = cli_session_setup_capabilities(cli);
215	char *p;
216	fstring lanman;
217
218	fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
219
220	set_message(cli->outbuf,13,0,True);
221	SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
222	cli_setup_packet(cli);
223
224	SCVAL(cli->outbuf,smb_vwv0,0xFF);
225	SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
226	SSVAL(cli->outbuf,smb_vwv3,2);
227	SSVAL(cli->outbuf,smb_vwv4,cli->pid);
228	SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
229	SSVAL(cli->outbuf,smb_vwv8,0);
230	SIVAL(cli->outbuf,smb_vwv11,capabilities);
231	p = smb_buf(cli->outbuf);
232
233	/* check wether to send the ASCII or UNICODE version of the password */
234
235	if ( (capabilities & CAP_UNICODE) == 0 ) {
236		p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
237		SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
238	}
239	else {
240		p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
241		SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf)));
242	}
243
244	p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
245	p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
246	p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
247	p += clistr_push(cli, p, lanman, -1, STR_TERMINATE);
248	cli_setup_bcc(cli, p);
249
250	cli_send_smb(cli);
251	if (!cli_receive_smb(cli))
252	      return False;
253
254	show_msg(cli->inbuf);
255
256	if (cli_is_error(cli))
257		return False;
258
259	cli->vuid = SVAL(cli->inbuf,smb_uid);
260	p = smb_buf(cli->inbuf);
261	p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
262	p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
263	p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
264	fstrcpy(cli->user_name, user);
265
266	return True;
267}
268
269/****************************************************************************
270   do a NT1 NTLM/LM encrypted session setup - for when extended security
271   is not negotiated.
272   @param cli client state to create do session setup on
273   @param user username
274   @param pass *either* cleartext password (passlen !=24) or LM response.
275   @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
276   @param workgroup The user's domain.
277****************************************************************************/
278
279static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
280				  const char *pass, size_t passlen,
281				  const char *ntpass, size_t ntpasslen,
282				  const char *workgroup)
283{
284	uint32 capabilities = cli_session_setup_capabilities(cli);
285	DATA_BLOB lm_response = data_blob(NULL, 0);
286	DATA_BLOB nt_response = data_blob(NULL, 0);
287	DATA_BLOB session_key = data_blob(NULL, 0);
288	BOOL ret = False;
289	char *p;
290
291	if (passlen == 0) {
292		/* do nothing - guest login */
293	} else if (passlen != 24) {
294		if (lp_client_ntlmv2_auth()) {
295			DATA_BLOB server_chal;
296			DATA_BLOB names_blob;
297			server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8));
298
299			/* note that the 'workgroup' here is a best guess - we don't know
300			   the server's domain at this point.  The 'server name' is also
301			   dodgy...
302			*/
303			names_blob = NTLMv2_generate_names_blob(cli->called.name, workgroup);
304
305			if (!SMBNTLMv2encrypt(user, workgroup, pass, &server_chal,
306					      &names_blob,
307					      &lm_response, &nt_response, &session_key)) {
308				data_blob_free(&names_blob);
309				data_blob_free(&server_chal);
310				return False;
311			}
312			data_blob_free(&names_blob);
313			data_blob_free(&server_chal);
314
315		} else {
316			uchar nt_hash[16];
317			E_md4hash(pass, nt_hash);
318
319#ifdef LANMAN_ONLY
320			nt_response = data_blob(NULL, 0);
321#else
322			nt_response = data_blob(NULL, 24);
323			SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
324#endif
325			/* non encrypted password supplied. Ignore ntpass. */
326			if (lp_client_lanman_auth()) {
327				lm_response = data_blob(NULL, 24);
328				if (!SMBencrypt(pass,cli->secblob.data, lm_response.data)) {
329					/* Oops, the LM response is invalid, just put
330					   the NT response there instead */
331					data_blob_free(&lm_response);
332					lm_response = data_blob(nt_response.data, nt_response.length);
333				}
334			} else {
335				/* LM disabled, place NT# in LM field instead */
336				lm_response = data_blob(nt_response.data, nt_response.length);
337			}
338
339			session_key = data_blob(NULL, 16);
340#ifdef LANMAN_ONLY
341			E_deshash(pass, session_key.data);
342			memset(&session_key.data[8], '\0', 8);
343#else
344			SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
345#endif
346		}
347#ifdef LANMAN_ONLY
348		cli_simple_set_signing(cli, session_key, lm_response);
349#else
350		cli_simple_set_signing(cli, session_key, nt_response);
351#endif
352	} else {
353		/* pre-encrypted password supplied.  Only used for
354		   security=server, can't do
355		   signing because we don't have original key */
356
357		lm_response = data_blob(pass, passlen);
358		nt_response = data_blob(ntpass, ntpasslen);
359	}
360
361	/* send a session setup command */
362	memset(cli->outbuf,'\0',smb_size);
363
364	set_message(cli->outbuf,13,0,True);
365	SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
366	cli_setup_packet(cli);
367
368	SCVAL(cli->outbuf,smb_vwv0,0xFF);
369	SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
370	SSVAL(cli->outbuf,smb_vwv3,2);
371	SSVAL(cli->outbuf,smb_vwv4,cli->pid);
372	SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
373	SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
374	SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
375	SIVAL(cli->outbuf,smb_vwv11,capabilities);
376	p = smb_buf(cli->outbuf);
377	if (lm_response.length) {
378		memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
379	}
380	if (nt_response.length) {
381		memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
382	}
383	p += clistr_push(cli, p, user, -1, STR_TERMINATE);
384
385	/* Upper case here might help some NTLMv2 implementations */
386	p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
387	p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
388	p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
389	cli_setup_bcc(cli, p);
390
391	if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
392		ret = False;
393		goto end;
394	}
395
396	/* show_msg(cli->inbuf); */
397
398	if (cli_is_error(cli)) {
399		ret = False;
400		goto end;
401	}
402
403	/* use the returned vuid from now on */
404	cli->vuid = SVAL(cli->inbuf,smb_uid);
405
406	p = smb_buf(cli->inbuf);
407	p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
408	p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
409	p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
410
411	fstrcpy(cli->user_name, user);
412
413	if (session_key.data) {
414		/* Have plaintext orginal */
415		cli_set_session_key(cli, session_key);
416	}
417
418	ret = True;
419end:
420	data_blob_free(&lm_response);
421	data_blob_free(&nt_response);
422	data_blob_free(&session_key);
423	return ret;
424}
425
426/****************************************************************************
427 Send a extended security session setup blob
428****************************************************************************/
429
430static BOOL cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob)
431{
432	uint32 capabilities = cli_session_setup_capabilities(cli);
433	char *p;
434
435	capabilities |= CAP_EXTENDED_SECURITY;
436
437	/* send a session setup command */
438	memset(cli->outbuf,'\0',smb_size);
439
440	set_message(cli->outbuf,12,0,True);
441	SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
442
443	cli_setup_packet(cli);
444
445	SCVAL(cli->outbuf,smb_vwv0,0xFF);
446	SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
447	SSVAL(cli->outbuf,smb_vwv3,2);
448	SSVAL(cli->outbuf,smb_vwv4,1);
449	SIVAL(cli->outbuf,smb_vwv5,0);
450	SSVAL(cli->outbuf,smb_vwv7,blob.length);
451	SIVAL(cli->outbuf,smb_vwv10,capabilities);
452	p = smb_buf(cli->outbuf);
453	memcpy(p, blob.data, blob.length);
454	p += blob.length;
455	p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
456	p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
457	cli_setup_bcc(cli, p);
458	return cli_send_smb(cli);
459}
460
461/****************************************************************************
462 Send a extended security session setup blob, returning a reply blob.
463****************************************************************************/
464
465static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli)
466{
467	DATA_BLOB blob2 = data_blob(NULL, 0);
468	char *p;
469	size_t len;
470
471	if (!cli_receive_smb(cli))
472		return blob2;
473
474	show_msg(cli->inbuf);
475
476	if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli),
477						  NT_STATUS_MORE_PROCESSING_REQUIRED)) {
478		return blob2;
479	}
480
481	/* use the returned vuid from now on */
482	cli->vuid = SVAL(cli->inbuf,smb_uid);
483
484	p = smb_buf(cli->inbuf);
485
486	blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3));
487
488	p += blob2.length;
489	p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
490
491	/* w2k with kerberos doesn't properly null terminate this field */
492	len = smb_buflen(cli->inbuf) - PTR_DIFF(p, smb_buf(cli->inbuf));
493	p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), len, 0);
494
495	return blob2;
496}
497
498#ifdef HAVE_KRB5
499
500/****************************************************************************
501 Send a extended security session setup blob, returning a reply blob.
502****************************************************************************/
503
504static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
505{
506	DATA_BLOB blob2 = data_blob(NULL, 0);
507	if (!cli_session_setup_blob_send(cli, blob)) {
508		return blob2;
509	}
510
511	return cli_session_setup_blob_receive(cli);
512}
513
514/****************************************************************************
515 Use in-memory credentials cache
516****************************************************************************/
517
518static void use_in_memory_ccache(void) {
519	setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
520}
521
522/****************************************************************************
523 Do a spnego/kerberos encrypted session setup.
524****************************************************************************/
525
526static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
527{
528	DATA_BLOB blob2, negTokenTarg;
529	DATA_BLOB session_key_krb5;
530	DATA_BLOB null_blob = data_blob(NULL, 0);
531	int rc;
532
533	DEBUG(2,("Doing kerberos session setup\n"));
534
535	/* generate the encapsulated kerberos5 ticket */
536	rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5);
537
538	if (rc) {
539		DEBUG(1, ("spnego_gen_negTokenTarg failed: %s\n", error_message(rc)));
540		return ADS_ERROR_KRB5(rc);
541	}
542
543#if 0
544	file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
545#endif
546
547	cli_simple_set_signing(cli, session_key_krb5, null_blob);
548
549	blob2 = cli_session_setup_blob(cli, negTokenTarg);
550
551	/* we don't need this blob for kerberos */
552	data_blob_free(&blob2);
553
554	cli_set_session_key(cli, session_key_krb5);
555
556	data_blob_free(&negTokenTarg);
557	data_blob_free(&session_key_krb5);
558
559	if (cli_is_error(cli)) {
560		if (NT_STATUS_IS_OK(cli_nt_error(cli))) {
561			return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
562		}
563	}
564	return ADS_ERROR_NT(cli_nt_error(cli));
565}
566#endif	/* HAVE_KRB5 */
567
568
569/****************************************************************************
570 Do a spnego/NTLMSSP encrypted session setup.
571****************************************************************************/
572
573static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
574					  const char *pass, const char *domain)
575{
576	struct ntlmssp_state *ntlmssp_state;
577	NTSTATUS nt_status;
578	int turn = 1;
579	DATA_BLOB msg1;
580	DATA_BLOB blob = data_blob(NULL, 0);
581	DATA_BLOB blob_in = data_blob(NULL, 0);
582	DATA_BLOB blob_out = data_blob(NULL, 0);
583
584	cli_temp_set_signing(cli);
585
586	if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
587		return nt_status;
588	}
589
590	if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
591		return nt_status;
592	}
593	if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
594		return nt_status;
595	}
596	if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
597		return nt_status;
598	}
599
600	do {
601		nt_status = ntlmssp_update(ntlmssp_state,
602						  blob_in, &blob_out);
603		data_blob_free(&blob_in);
604		if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
605			if (turn == 1) {
606				/* and wrap it in a SPNEGO wrapper */
607				msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
608			} else {
609				/* wrap it in SPNEGO */
610				msg1 = spnego_gen_auth(blob_out);
611			}
612
613			/* now send that blob on its way */
614			if (!cli_session_setup_blob_send(cli, msg1)) {
615				DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
616				nt_status = NT_STATUS_UNSUCCESSFUL;
617			} else {
618				data_blob_free(&msg1);
619
620				blob = cli_session_setup_blob_receive(cli);
621
622				nt_status = cli_nt_error(cli);
623				if (cli_is_error(cli) && NT_STATUS_IS_OK(nt_status)) {
624					if (cli->smb_rw_error == READ_BAD_SIG) {
625						nt_status = NT_STATUS_ACCESS_DENIED;
626					} else {
627						nt_status = NT_STATUS_UNSUCCESSFUL;
628					}
629				}
630			}
631		}
632
633		if (!blob.length) {
634			if (NT_STATUS_IS_OK(nt_status)) {
635				nt_status = NT_STATUS_UNSUCCESSFUL;
636			}
637		} else if ((turn == 1) &&
638			   NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
639			DATA_BLOB tmp_blob = data_blob(NULL, 0);
640			/* the server might give us back two challenges */
641			if (!spnego_parse_challenge(blob, &blob_in,
642						    &tmp_blob)) {
643				DEBUG(3,("Failed to parse challenges\n"));
644				nt_status = NT_STATUS_INVALID_PARAMETER;
645			}
646			data_blob_free(&tmp_blob);
647		} else {
648			if (!spnego_parse_auth_response(blob, nt_status,
649							&blob_in)) {
650				DEBUG(3,("Failed to parse auth response\n"));
651				if (NT_STATUS_IS_OK(nt_status)
652				    || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED))
653					nt_status = NT_STATUS_INVALID_PARAMETER;
654			}
655		}
656		data_blob_free(&blob);
657		data_blob_free(&blob_out);
658		turn++;
659	} while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
660
661	if (NT_STATUS_IS_OK(nt_status)) {
662
663		DATA_BLOB key = data_blob(ntlmssp_state->session_key.data,
664					  ntlmssp_state->session_key.length);
665		DATA_BLOB null_blob = data_blob(NULL, 0);
666		BOOL res;
667
668		fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
669		cli_set_session_key(cli, ntlmssp_state->session_key);
670
671		res = cli_simple_set_signing(cli, key, null_blob);
672
673		data_blob_free(&key);
674
675		if (res) {
676
677			/* 'resign' the last message, so we get the right sequence numbers
678			   for checking the first reply from the server */
679			cli_calculate_sign_mac(cli);
680
681			if (!cli_check_sign_mac(cli)) {
682				nt_status = NT_STATUS_ACCESS_DENIED;
683			}
684		}
685	}
686
687	/* we have a reference conter on ntlmssp_state, if we are signing
688	   then the state will be kept by the signing engine */
689
690	ntlmssp_end(&ntlmssp_state);
691
692	return nt_status;
693}
694
695/****************************************************************************
696 Do a spnego encrypted session setup.
697****************************************************************************/
698
699ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
700			      const char *pass, const char *domain)
701{
702	char *principal;
703	char *OIDs[ASN1_MAX_OIDS];
704	int i;
705	BOOL got_kerberos_mechanism = False;
706	DATA_BLOB blob;
707
708	DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
709
710	/* the server might not even do spnego */
711	if (cli->secblob.length <= 16) {
712		DEBUG(3,("server didn't supply a full spnego negprot\n"));
713		goto ntlmssp;
714	}
715
716#if 0
717	file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
718#endif
719
720	/* there is 16 bytes of GUID before the real spnego packet starts */
721	blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
722
723	/* the server sent us the first part of the SPNEGO exchange in the negprot
724	   reply */
725	if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
726		data_blob_free(&blob);
727		return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
728	}
729	data_blob_free(&blob);
730
731	/* make sure the server understands kerberos */
732	for (i=0;OIDs[i];i++) {
733		DEBUG(3,("got OID=%s\n", OIDs[i]));
734		if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
735		    strcmp(OIDs[i], OID_KERBEROS5) == 0) {
736			got_kerberos_mechanism = True;
737		}
738		free(OIDs[i]);
739	}
740	DEBUG(3,("got principal=%s\n", principal));
741
742	fstrcpy(cli->user_name, user);
743
744#ifdef HAVE_KRB5
745	/* If password is set we reauthenticate to kerberos server
746	 * and do not store results */
747
748	if (got_kerberos_mechanism && cli->use_kerberos) {
749		ADS_STATUS rc;
750
751		if (pass && *pass) {
752			int ret;
753
754			use_in_memory_ccache();
755			ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL, NULL);
756
757			if (ret){
758				SAFE_FREE(principal);
759				DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
760				if (cli->fallback_after_kerberos)
761					goto ntlmssp;
762				return ADS_ERROR_KRB5(ret);
763			}
764		}
765
766		rc = cli_session_setup_kerberos(cli, principal, domain);
767		if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
768			SAFE_FREE(principal);
769			return rc;
770		}
771	}
772#endif
773
774	SAFE_FREE(principal);
775
776ntlmssp:
777
778	return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, user, pass, domain));
779}
780
781/****************************************************************************
782 Send a session setup. The username and workgroup is in UNIX character
783 format and must be converted to DOS codepage format before sending. If the
784 password is in plaintext, the same should be done.
785****************************************************************************/
786
787BOOL cli_session_setup(struct cli_state *cli,
788		       const char *user,
789		       const char *pass, int passlen,
790		       const char *ntpass, int ntpasslen,
791		       const char *workgroup)
792{
793	char *p;
794	fstring user2;
795
796	/* allow for workgroups as part of the username */
797	fstrcpy(user2, user);
798	if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
799	    (p=strchr_m(user2,*lp_winbind_separator()))) {
800		*p = 0;
801		user = p+1;
802		workgroup = user2;
803	}
804
805	if (cli->protocol < PROTOCOL_LANMAN1)
806		return True;
807
808	/* now work out what sort of session setup we are going to
809           do. I have split this into separate functions to make the
810           flow a bit easier to understand (tridge) */
811
812	/* if its an older server then we have to use the older request format */
813
814	if (cli->protocol < PROTOCOL_NT1) {
815		if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
816			DEBUG(1, ("Server requested LM password but 'client lanman auth'"
817				  " is disabled\n"));
818			return False;
819		}
820
821		if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
822		    !lp_client_plaintext_auth() && (*pass)) {
823			DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
824				  " is disabled\n"));
825			return False;
826		}
827
828		return cli_session_setup_lanman2(cli, user, pass, passlen, workgroup);
829	}
830
831	/* if no user is supplied then we have to do an anonymous connection.
832	   passwords are ignored */
833
834	if (!user || !*user)
835		return cli_session_setup_guest(cli);
836
837	/* if the server is share level then send a plaintext null
838           password at this point. The password is sent in the tree
839           connect */
840
841	if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
842		return cli_session_setup_plaintext(cli, user, "", workgroup);
843
844	/* if the server doesn't support encryption then we have to use
845	   plaintext. The second password is ignored */
846
847	if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
848		if (!lp_client_plaintext_auth() && (*pass)) {
849			DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
850				  " is disabled\n"));
851			return False;
852		}
853		return cli_session_setup_plaintext(cli, user, pass, workgroup);
854	}
855
856	/* if the server supports extended security then use SPNEGO */
857
858	if (cli->capabilities & CAP_EXTENDED_SECURITY) {
859		ADS_STATUS status = cli_session_setup_spnego(cli, user, pass, workgroup);
860		if (!ADS_ERR_OK(status)) {
861			DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
862			return False;
863		}
864		return True;
865	}
866
867	/* otherwise do a NT1 style session setup */
868
869	return cli_session_setup_nt1(cli, user,
870				     pass, passlen, ntpass, ntpasslen,
871				     workgroup);
872}
873
874/****************************************************************************
875 Send a uloggoff.
876*****************************************************************************/
877
878BOOL cli_ulogoff(struct cli_state *cli)
879{
880	memset(cli->outbuf,'\0',smb_size);
881	set_message(cli->outbuf,2,0,True);
882	SCVAL(cli->outbuf,smb_com,SMBulogoffX);
883	cli_setup_packet(cli);
884	SSVAL(cli->outbuf,smb_vwv0,0xFF);
885	SSVAL(cli->outbuf,smb_vwv2,0);  /* no additional info */
886
887	cli_send_smb(cli);
888	if (!cli_receive_smb(cli))
889		return False;
890
891	if (cli_is_error(cli)) {
892		return False;
893	}
894
895        cli->cnum = -1;
896        return True;
897}
898
899/****************************************************************************
900 Send a tconX.
901****************************************************************************/
902BOOL cli_send_tconX(struct cli_state *cli,
903		    const char *share, const char *dev, const char *pass, int passlen)
904{
905	fstring fullshare, pword;
906	char *p;
907	memset(cli->outbuf,'\0',smb_size);
908	memset(cli->inbuf,'\0',smb_size);
909
910	fstrcpy(cli->share, share);
911
912	/* in user level security don't send a password now */
913	if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
914		passlen = 1;
915		pass = "";
916	}
917
918	if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && *pass && passlen != 24) {
919		if (!lp_client_lanman_auth()) {
920			DEBUG(1, ("Server requested LANMAN password (share-level security) but 'client use lanman auth'"
921				  " is disabled\n"));
922			return False;
923		}
924
925		/*
926		 * Non-encrypted passwords - convert to DOS codepage before encryption.
927		 */
928		passlen = 24;
929		SMBencrypt(pass,cli->secblob.data,(uchar *)pword);
930	} else {
931		if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL|NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)) == 0) {
932			if (!lp_client_plaintext_auth() && (*pass)) {
933				DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
934					  " is disabled\n"));
935				return False;
936			}
937
938			/*
939			 * Non-encrypted passwords - convert to DOS codepage before using.
940			 */
941			passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
942
943		} else {
944			memcpy(pword, pass, passlen);
945		}
946	}
947
948	slprintf(fullshare, sizeof(fullshare)-1,
949		 "\\\\%s\\%s", cli->desthost, share);
950
951	set_message(cli->outbuf,4, 0, True);
952	SCVAL(cli->outbuf,smb_com,SMBtconX);
953	cli_setup_packet(cli);
954
955	SSVAL(cli->outbuf,smb_vwv0,0xFF);
956	SSVAL(cli->outbuf,smb_vwv3,passlen);
957
958	p = smb_buf(cli->outbuf);
959	memcpy(p,pword,passlen);
960	p += passlen;
961	p += clistr_push(cli, p, fullshare, -1, STR_TERMINATE |STR_UPPER);
962	p += clistr_push(cli, p, dev, -1, STR_TERMINATE |STR_UPPER | STR_ASCII);
963
964	cli_setup_bcc(cli, p);
965
966	cli_send_smb(cli);
967	if (!cli_receive_smb(cli))
968		return False;
969
970	if (cli_is_error(cli))
971		return False;
972
973	clistr_pull(cli, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), -1, STR_TERMINATE|STR_ASCII);
974
975	if (cli->protocol >= PROTOCOL_NT1 &&
976	    smb_buflen(cli->inbuf) == 3) {
977		/* almost certainly win95 - enable bug fixes */
978		cli->win95 = True;
979	}
980
981	/* Make sure that we have the optional support 16-bit field.  WCT > 2 */
982	/* Avoids issues when connecting to Win9x boxes sharing files */
983
984	cli->dfsroot = False;
985	if ( (CVAL(cli->inbuf, smb_wct))>2 && cli->protocol >= PROTOCOL_LANMAN2 )
986		cli->dfsroot = (SVAL( cli->inbuf, smb_vwv2 ) & SMB_SHARE_IN_DFS) ? True : False;
987
988	cli->cnum = SVAL(cli->inbuf,smb_tid);
989	return True;
990}
991
992/****************************************************************************
993 Send a tree disconnect.
994****************************************************************************/
995
996BOOL cli_tdis(struct cli_state *cli)
997{
998	memset(cli->outbuf,'\0',smb_size);
999	set_message(cli->outbuf,0,0,True);
1000	SCVAL(cli->outbuf,smb_com,SMBtdis);
1001	SSVAL(cli->outbuf,smb_tid,cli->cnum);
1002	cli_setup_packet(cli);
1003
1004	cli_send_smb(cli);
1005	if (!cli_receive_smb(cli))
1006		return False;
1007
1008	if (cli_is_error(cli)) {
1009		return False;
1010	}
1011
1012	cli->cnum = -1;
1013	return True;
1014}
1015
1016/****************************************************************************
1017 Send a negprot command.
1018****************************************************************************/
1019
1020void cli_negprot_send(struct cli_state *cli)
1021{
1022	char *p;
1023	int numprots;
1024
1025	if (cli->protocol < PROTOCOL_NT1)
1026		cli->use_spnego = False;
1027
1028	memset(cli->outbuf,'\0',smb_size);
1029
1030	/* setup the protocol strings */
1031	set_message(cli->outbuf,0,0,True);
1032
1033	p = smb_buf(cli->outbuf);
1034	for (numprots=0;
1035	     prots[numprots].name && prots[numprots].prot<=cli->protocol;
1036	     numprots++) {
1037		*p++ = 2;
1038		p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1039	}
1040
1041	SCVAL(cli->outbuf,smb_com,SMBnegprot);
1042	cli_setup_bcc(cli, p);
1043	cli_setup_packet(cli);
1044
1045	SCVAL(smb_buf(cli->outbuf),0,2);
1046
1047	cli_send_smb(cli);
1048}
1049
1050/****************************************************************************
1051 Send a negprot command.
1052****************************************************************************/
1053
1054BOOL cli_negprot(struct cli_state *cli)
1055{
1056	char *p;
1057	int numprots;
1058	int plength;
1059
1060	if (cli->protocol < PROTOCOL_NT1)
1061		cli->use_spnego = False;
1062
1063	memset(cli->outbuf,'\0',smb_size);
1064
1065	/* setup the protocol strings */
1066	for (plength=0,numprots=0;
1067	     prots[numprots].name && prots[numprots].prot<=cli->protocol;
1068	     numprots++)
1069		plength += strlen(prots[numprots].name)+2;
1070
1071	set_message(cli->outbuf,0,plength,True);
1072
1073	p = smb_buf(cli->outbuf);
1074	for (numprots=0;
1075	     prots[numprots].name && prots[numprots].prot<=cli->protocol;
1076	     numprots++) {
1077		*p++ = 2;
1078		p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1079	}
1080
1081	SCVAL(cli->outbuf,smb_com,SMBnegprot);
1082	cli_setup_packet(cli);
1083
1084	SCVAL(smb_buf(cli->outbuf),0,2);
1085
1086	cli_send_smb(cli);
1087	if (!cli_receive_smb(cli))
1088		return False;
1089
1090	show_msg(cli->inbuf);
1091
1092	if (cli_is_error(cli) ||
1093	    ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
1094		return(False);
1095	}
1096
1097	cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
1098
1099	if ((cli->protocol < PROTOCOL_NT1) && cli->sign_info.mandatory_signing) {
1100		DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1101		return False;
1102	}
1103
1104	if (cli->protocol >= PROTOCOL_NT1) {
1105		/* NT protocol */
1106		cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
1107		cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
1108		cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
1109		cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
1110		cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1);
1111		cli->serverzone *= 60;
1112		/* this time arrives in real GMT */
1113		cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
1114		cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
1115		cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
1116		if (cli->capabilities & CAP_RAW_MODE) {
1117			cli->readbraw_supported = True;
1118			cli->writebraw_supported = True;
1119		}
1120		/* work out if they sent us a workgroup */
1121		if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1122		    smb_buflen(cli->inbuf) > 8) {
1123			clistr_pull(cli, cli->server_domain,
1124				    smb_buf(cli->inbuf)+8, sizeof(cli->server_domain),
1125				    smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN);
1126		}
1127
1128		/*
1129		 * As signing is slow we only turn it on if either the client or
1130		 * the server require it. JRA.
1131		 */
1132
1133		if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
1134			/* Fail if server says signing is mandatory and we don't want to support it. */
1135			if (!cli->sign_info.allow_smb_signing) {
1136				DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1137				return False;
1138			}
1139			cli->sign_info.negotiated_smb_signing = True;
1140			cli->sign_info.mandatory_signing = True;
1141		} else if (cli->sign_info.mandatory_signing && cli->sign_info.allow_smb_signing) {
1142			/* Fail if client says signing is mandatory and the server doesn't support it. */
1143			if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
1144				DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1145				return False;
1146			}
1147			cli->sign_info.negotiated_smb_signing = True;
1148			cli->sign_info.mandatory_signing = True;
1149		} else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
1150			cli->sign_info.negotiated_smb_signing = True;
1151		}
1152
1153		if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
1154			SAFE_FREE(cli->outbuf);
1155			SAFE_FREE(cli->inbuf);
1156			cli->outbuf = (char *)SMB_MALLOC(CLI_MAX_LARGE_READX_SIZE+SAFETY_MARGIN);
1157			cli->inbuf = (char *)SMB_MALLOC(CLI_MAX_LARGE_READX_SIZE+SAFETY_MARGIN);
1158			cli->bufsize = CLI_MAX_LARGE_READX_SIZE;
1159		}
1160
1161	} else if (cli->protocol >= PROTOCOL_LANMAN1) {
1162		cli->use_spnego = False;
1163		cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
1164		cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
1165		cli->max_mux = SVAL(cli->inbuf, smb_vwv3);
1166		cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
1167		cli->serverzone = SVALS(cli->inbuf,smb_vwv10);
1168		cli->serverzone *= 60;
1169		/* this time is converted to GMT by make_unix_date */
1170		cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
1171		cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
1172		cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
1173		cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
1174	} else {
1175		/* the old core protocol */
1176		cli->use_spnego = False;
1177		cli->sec_mode = 0;
1178		cli->serverzone = TimeDiff(time(NULL));
1179	}
1180
1181	cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1182
1183	/* a way to force ascii SMB */
1184	if (getenv("CLI_FORCE_ASCII"))
1185		cli->capabilities &= ~CAP_UNICODE;
1186
1187	return True;
1188}
1189
1190/****************************************************************************
1191 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1192****************************************************************************/
1193
1194BOOL cli_session_request(struct cli_state *cli,
1195			 struct nmb_name *calling, struct nmb_name *called)
1196{
1197	char *p;
1198	int len = 4;
1199	extern pstring user_socket_options;
1200
1201	memcpy(&(cli->calling), calling, sizeof(*calling));
1202	memcpy(&(cli->called ), called , sizeof(*called ));
1203
1204	/* put in the destination name */
1205	p = cli->outbuf+len;
1206	name_mangle(cli->called .name, p, cli->called .name_type);
1207	len += name_len(p);
1208
1209	/* and my name */
1210	p = cli->outbuf+len;
1211	name_mangle(cli->calling.name, p, cli->calling.name_type);
1212	len += name_len(p);
1213
1214	/* 445 doesn't have session request */
1215	if (cli->port == 445)
1216		return True;
1217
1218	/* send a session request (RFC 1002) */
1219	/* setup the packet length
1220         * Remove four bytes from the length count, since the length
1221         * field in the NBT Session Service header counts the number
1222         * of bytes which follow.  The cli_send_smb() function knows
1223         * about this and accounts for those four bytes.
1224         * CRH.
1225         */
1226        len -= 4;
1227	_smb_setlen(cli->outbuf,len);
1228	SCVAL(cli->outbuf,0,0x81);
1229
1230	cli_send_smb(cli);
1231	DEBUG(5,("Sent session request\n"));
1232
1233	if (!cli_receive_smb(cli))
1234		return False;
1235
1236	if (CVAL(cli->inbuf,0) == 0x84) {
1237		/* C. Hoch  9/14/95 Start */
1238		/* For information, here is the response structure.
1239		 * We do the byte-twiddling to for portability.
1240		struct RetargetResponse{
1241		unsigned char type;
1242		unsigned char flags;
1243		int16 length;
1244		int32 ip_addr;
1245		int16 port;
1246		};
1247		*/
1248		int port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1249		/* SESSION RETARGET */
1250		putip((char *)&cli->dest_ip,cli->inbuf+4);
1251
1252		cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, LONG_CONNECT_TIMEOUT);
1253		if (cli->fd == -1)
1254			return False;
1255
1256		DEBUG(3,("Retargeted\n"));
1257
1258		set_socket_options(cli->fd,user_socket_options);
1259
1260		/* Try again */
1261		{
1262			static int depth;
1263			BOOL ret;
1264			if (depth > 4) {
1265				DEBUG(0,("Retarget recursion - failing\n"));
1266				return False;
1267			}
1268			depth++;
1269			ret = cli_session_request(cli, calling, called);
1270			depth--;
1271			return ret;
1272		}
1273	} /* C. Hoch 9/14/95 End */
1274
1275	if (CVAL(cli->inbuf,0) != 0x82) {
1276                /* This is the wrong place to put the error... JRA. */
1277		cli->rap_error = CVAL(cli->inbuf,4);
1278		return False;
1279	}
1280	return(True);
1281}
1282
1283/****************************************************************************
1284 Open the client sockets.
1285****************************************************************************/
1286
1287BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
1288{
1289	extern pstring user_socket_options;
1290	int name_type = 0x20;
1291	char *p;
1292
1293	/* reasonable default hostname */
1294	if (!host) host = "*SMBSERVER";
1295
1296	fstrcpy(cli->desthost, host);
1297
1298	/* allow hostnames of the form NAME#xx and do a netbios lookup */
1299	if ((p = strchr(cli->desthost, '#'))) {
1300		name_type = strtol(p+1, NULL, 16);
1301		*p = 0;
1302	}
1303
1304	if (!ip || is_zero_ip(*ip)) {
1305                if (!resolve_name(cli->desthost, &cli->dest_ip, name_type)) {
1306                        return False;
1307                }
1308		if (ip) *ip = cli->dest_ip;
1309	} else {
1310		cli->dest_ip = *ip;
1311	}
1312
1313	if (getenv("LIBSMB_PROG")) {
1314		cli->fd = sock_exec(getenv("LIBSMB_PROG"));
1315	} else {
1316		/* try 445 first, then 139 */
1317		int port = cli->port?cli->port:445;
1318		cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
1319					  port, cli->timeout);
1320		if (cli->fd == -1 && cli->port == 0) {
1321			port = 139;
1322			cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
1323						  port, cli->timeout);
1324		}
1325		if (cli->fd != -1)
1326			cli->port = port;
1327	}
1328	if (cli->fd == -1) {
1329		DEBUG(1,("Error connecting to %s (%s)\n",
1330			 ip?inet_ntoa(*ip):host,strerror(errno)));
1331		return False;
1332	}
1333
1334	set_socket_options(cli->fd,user_socket_options);
1335
1336	return True;
1337}
1338
1339/****************************************************************************
1340 Initialise client credentials for authenticated pipe access.
1341****************************************************************************/
1342
1343void init_creds(struct ntuser_creds *creds, const char* username,
1344		       const char* domain, const char* password)
1345{
1346	ZERO_STRUCTP(creds);
1347
1348	pwd_set_cleartext(&creds->pwd, password);
1349
1350	fstrcpy(creds->user_name, username);
1351	fstrcpy(creds->domain, domain);
1352
1353	if (!*username) {
1354		creds->pwd.null_pwd = True;
1355	}
1356}
1357
1358/**
1359   establishes a connection to after the negprot.
1360   @param output_cli A fully initialised cli structure, non-null only on success
1361   @param dest_host The netbios name of the remote host
1362   @param dest_ip (optional) The the destination IP, NULL for name based lookup
1363   @param port (optional) The destination port (0 for default)
1364   @param retry BOOL. Did this connection fail with a retryable error ?
1365
1366*/
1367NTSTATUS cli_start_connection(struct cli_state **output_cli,
1368			      const char *my_name,
1369			      const char *dest_host,
1370			      struct in_addr *dest_ip, int port,
1371			      int signing_state, int flags,
1372			      BOOL *retry)
1373{
1374	NTSTATUS nt_status;
1375	struct nmb_name calling;
1376	struct nmb_name called;
1377	struct cli_state *cli;
1378	struct in_addr ip;
1379
1380	if (retry)
1381		*retry = False;
1382
1383	if (!my_name)
1384		my_name = global_myname();
1385
1386	if (!(cli = cli_initialise(NULL)))
1387		return NT_STATUS_NO_MEMORY;
1388
1389	make_nmb_name(&calling, my_name, 0x0);
1390	make_nmb_name(&called , dest_host, 0x20);
1391
1392	if (cli_set_port(cli, port) != port) {
1393		cli_shutdown(cli);
1394		return NT_STATUS_UNSUCCESSFUL;
1395	}
1396
1397	cli_set_timeout(cli, 10000); /* 10 seconds. */
1398
1399	if (dest_ip)
1400		ip = *dest_ip;
1401	else
1402		ZERO_STRUCT(ip);
1403
1404again:
1405
1406	DEBUG(3,("Connecting to host=%s\n", dest_host));
1407
1408	if (!cli_connect(cli, dest_host, &ip)) {
1409		DEBUG(1,("cli_full_connection: failed to connect to %s (%s)\n",
1410			 nmb_namestr(&called), inet_ntoa(ip)));
1411		cli_shutdown(cli);
1412		return NT_STATUS_UNSUCCESSFUL;
1413	}
1414
1415	if (retry)
1416		*retry = True;
1417
1418	if (!cli_session_request(cli, &calling, &called)) {
1419		char *p;
1420		DEBUG(1,("session request to %s failed (%s)\n",
1421			 called.name, cli_errstr(cli)));
1422		if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
1423			*p = 0;
1424			goto again;
1425		}
1426		if (strcmp(called.name, "*SMBSERVER")) {
1427			make_nmb_name(&called , "*SMBSERVER", 0x20);
1428			goto again;
1429		}
1430		return NT_STATUS_UNSUCCESSFUL;
1431	}
1432
1433	cli_setup_signing_state(cli, signing_state);
1434
1435	if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
1436		cli->use_spnego = False;
1437	else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
1438		cli->use_kerberos = True;
1439
1440	if (!cli_negprot(cli)) {
1441		DEBUG(1,("failed negprot\n"));
1442		nt_status = NT_STATUS_UNSUCCESSFUL;
1443		cli_shutdown(cli);
1444		return nt_status;
1445	}
1446
1447	*output_cli = cli;
1448	return NT_STATUS_OK;
1449}
1450
1451
1452/**
1453   establishes a connection right up to doing tconX, password specified.
1454   @param output_cli A fully initialised cli structure, non-null only on success
1455   @param dest_host The netbios name of the remote host
1456   @param dest_ip (optional) The the destination IP, NULL for name based lookup
1457   @param port (optional) The destination port (0 for default)
1458   @param service (optional) The share to make the connection to.  Should be 'unqualified' in any way.
1459   @param service_type The 'type' of serivice.
1460   @param user Username, unix string
1461   @param domain User's domain
1462   @param password User's password, unencrypted unix string.
1463   @param retry BOOL. Did this connection fail with a retryable error ?
1464*/
1465
1466NTSTATUS cli_full_connection(struct cli_state **output_cli,
1467			     const char *my_name,
1468			     const char *dest_host,
1469			     struct in_addr *dest_ip, int port,
1470			     const char *service, const char *service_type,
1471			     const char *user, const char *domain,
1472			     const char *password, int flags,
1473			     int signing_state,
1474			     BOOL *retry)
1475{
1476	struct ntuser_creds creds;
1477	NTSTATUS nt_status;
1478	struct cli_state *cli = NULL;
1479
1480	nt_status = cli_start_connection(&cli, my_name, dest_host,
1481					 dest_ip, port, signing_state, flags, retry);
1482
1483	if (!NT_STATUS_IS_OK(nt_status)) {
1484		return nt_status;
1485	}
1486
1487	if (!cli_session_setup(cli, user, password, strlen(password)+1,
1488			       password, strlen(password)+1,
1489			       domain)) {
1490		if ((flags & CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK)
1491		    && cli_session_setup(cli, "", "", 0, "", 0, domain)) {
1492		} else {
1493			nt_status = cli_nt_error(cli);
1494			DEBUG(1,("failed session setup with %s\n", nt_errstr(nt_status)));
1495			cli_shutdown(cli);
1496			if (NT_STATUS_IS_OK(nt_status))
1497				nt_status = NT_STATUS_UNSUCCESSFUL;
1498			return nt_status;
1499		}
1500	}
1501
1502	if (service) {
1503		if (!cli_send_tconX(cli, service, service_type,
1504				    password, strlen(password)+1)) {
1505			nt_status = cli_nt_error(cli);
1506			DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
1507			cli_shutdown(cli);
1508			if (NT_STATUS_IS_OK(nt_status)) {
1509				nt_status = NT_STATUS_UNSUCCESSFUL;
1510			}
1511			return nt_status;
1512		}
1513	}
1514
1515	init_creds(&creds, user, domain, password);
1516	cli_init_creds(cli, &creds);
1517
1518	*output_cli = cli;
1519	return NT_STATUS_OK;
1520}
1521
1522/****************************************************************************
1523 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
1524****************************************************************************/
1525
1526BOOL attempt_netbios_session_request(struct cli_state *cli, const char *srchost, const char *desthost,
1527                                     struct in_addr *pdest_ip)
1528{
1529	struct nmb_name calling, called;
1530
1531	make_nmb_name(&calling, srchost, 0x0);
1532
1533	/*
1534	 * If the called name is an IP address
1535	 * then use *SMBSERVER immediately.
1536	 */
1537
1538	if(is_ipaddress(desthost))
1539		make_nmb_name(&called, "*SMBSERVER", 0x20);
1540	else
1541		make_nmb_name(&called, desthost, 0x20);
1542
1543	if (!cli_session_request(cli, &calling, &called)) {
1544		struct nmb_name smbservername;
1545
1546		make_nmb_name(&smbservername , "*SMBSERVER", 0x20);
1547
1548		/*
1549		 * If the name wasn't *SMBSERVER then
1550		 * try with *SMBSERVER if the first name fails.
1551		 */
1552
1553		if (nmb_name_equal(&called, &smbservername)) {
1554
1555			/*
1556			 * The name used was *SMBSERVER, don't bother with another name.
1557			 */
1558
1559			DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
1560with error %s.\n", desthost, cli_errstr(cli) ));
1561			return False;
1562		}
1563
1564		/*
1565		 * We need to close the connection here but can't call cli_shutdown as
1566		 * will free an allocated cli struct. cli_close_connection was invented
1567		 * for this purpose. JRA. Based on work by "Kim R. Pedersen" <krp@filanet.dk>.
1568		 */
1569
1570		cli_close_connection(cli);
1571
1572		if (!cli_initialise(cli) ||
1573				!cli_connect(cli, desthost, pdest_ip) ||
1574				!cli_session_request(cli, &calling, &smbservername)) {
1575			DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
1576name *SMBSERVER with error %s\n", desthost, cli_errstr(cli) ));
1577			return False;
1578		}
1579	}
1580
1581	return True;
1582}
1583
1584
1585
1586
1587
1588/****************************************************************************
1589 Send an old style tcon.
1590****************************************************************************/
1591NTSTATUS cli_raw_tcon(struct cli_state *cli,
1592		      const char *service, const char *pass, const char *dev,
1593		      uint16 *max_xmit, uint16 *tid)
1594{
1595	char *p;
1596
1597	if (!lp_client_plaintext_auth() && (*pass)) {
1598		DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
1599			  " is disabled\n"));
1600		return NT_STATUS_ACCESS_DENIED;
1601	}
1602
1603	memset(cli->outbuf,'\0',smb_size);
1604	memset(cli->inbuf,'\0',smb_size);
1605
1606	set_message(cli->outbuf, 0, 0, True);
1607	SCVAL(cli->outbuf,smb_com,SMBtcon);
1608	cli_setup_packet(cli);
1609
1610	p = smb_buf(cli->outbuf);
1611	*p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
1612	*p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
1613	*p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
1614
1615	cli_setup_bcc(cli, p);
1616
1617	cli_send_smb(cli);
1618	if (!cli_receive_smb(cli)) {
1619		return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1620	}
1621
1622	if (cli_is_error(cli)) {
1623		return cli_nt_error(cli);
1624	}
1625
1626	*max_xmit = SVAL(cli->inbuf, smb_vwv0);
1627	*tid = SVAL(cli->inbuf, smb_vwv1);
1628
1629	return NT_STATUS_OK;
1630}
1631
1632/* Return a cli_state pointing at the IPC$ share for the given server */
1633
1634struct cli_state *get_ipc_connect(char *server, struct in_addr *server_ip,
1635                                         struct user_auth_info *user_info)
1636{
1637        struct cli_state *cli;
1638        pstring myname;
1639	NTSTATUS nt_status;
1640
1641        get_myname(myname);
1642
1643	nt_status = cli_full_connection(&cli, myname, server, server_ip, 0, "IPC$", "IPC",
1644					user_info->username, lp_workgroup(), user_info->password,
1645					CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, Undefined, NULL);
1646
1647	if (NT_STATUS_IS_OK(nt_status)) {
1648		return cli;
1649	} else if (is_ipaddress(server)) {
1650	    /* windows 9* needs a correct NMB name for connections */
1651	    fstring remote_name;
1652
1653	    if (name_status_find("*", 0, 0, *server_ip, remote_name)) {
1654		cli = get_ipc_connect(remote_name, server_ip, user_info);
1655		if (cli)
1656		    return cli;
1657	    }
1658	}
1659	return NULL;
1660}
1661
1662/*
1663 * Given the IP address of a master browser on the network, return its
1664 * workgroup and connect to it.
1665 *
1666 * This function is provided to allow additional processing beyond what
1667 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
1668 * browsers and obtain each master browsers' list of domains (in case the
1669 * first master browser is recently on the network and has not yet
1670 * synchronized with other master browsers and therefore does not yet have the
1671 * entire network browse list)
1672 */
1673
1674struct cli_state *get_ipc_connect_master_ip(struct ip_service * mb_ip, pstring workgroup, struct user_auth_info *user_info)
1675{
1676        static fstring name;
1677	struct cli_state *cli;
1678	struct in_addr server_ip;
1679
1680        DEBUG(99, ("Looking up name of master browser %s\n",
1681                   inet_ntoa(mb_ip->ip)));
1682
1683        /*
1684         * Do a name status query to find out the name of the master browser.
1685         * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
1686         * master browser will not respond to a wildcard query (or, at least,
1687         * an NT4 server acting as the domain master browser will not).
1688         *
1689         * We might be able to use ONLY the query on MSBROWSE, but that's not
1690         * yet been tested with all Windows versions, so until it is, leave
1691         * the original wildcard query as the first choice and fall back to
1692         * MSBROWSE if the wildcard query fails.
1693         */
1694        if (!name_status_find("*", 0, 0x1d, mb_ip->ip, name) &&
1695            !name_status_find(MSBROWSE, 1, 0x1d, mb_ip->ip, name)) {
1696
1697                DEBUG(99, ("Could not retrieve name status for %s\n",
1698                           inet_ntoa(mb_ip->ip)));
1699                return NULL;
1700        }
1701
1702        if (!find_master_ip(name, &server_ip)) {
1703                DEBUG(99, ("Could not find master ip for %s\n", name));
1704                return NULL;
1705        }
1706
1707                pstrcpy(workgroup, name);
1708
1709                DEBUG(4, ("found master browser %s, %s\n",
1710                  name, inet_ntoa(mb_ip->ip)));
1711
1712		cli = get_ipc_connect(inet_ntoa(server_ip), &server_ip, user_info);
1713
1714		return cli;
1715
1716}
1717
1718/*
1719 * Return the IP address and workgroup of a master browser on the network, and
1720 * connect to it.
1721 */
1722
1723struct cli_state *get_ipc_connect_master_ip_bcast(pstring workgroup, struct user_auth_info *user_info)
1724{
1725	struct ip_service *ip_list;
1726	struct cli_state *cli;
1727	int i, count;
1728
1729        DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
1730
1731        /* Go looking for workgroups by broadcasting on the local network */
1732
1733        if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) {
1734                DEBUG(99, ("No master browsers responded\n"));
1735                return False;
1736        }
1737
1738	for (i = 0; i < count; i++) {
1739            DEBUG(99, ("Found master browser %s\n", inet_ntoa(ip_list[i].ip)));
1740
1741            cli = get_ipc_connect_master_ip(&ip_list[i], workgroup, user_info);
1742            if (cli)
1743                    return(cli);
1744	}
1745
1746	return NULL;
1747}
1748