1/*
2   Unix SMB/CIFS implementation.
3   SMB client generic functions
4   Copyright (C) Andrew Tridgell 1994-1998
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2 of the License, or
9   (at your option) any later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21#define NO_SYSLOG
22
23#include "includes.h"
24
25/****************************************************************************
26 Change the timeout (in milliseconds).
27****************************************************************************/
28
29unsigned int cli_set_timeout(struct cli_state *cli, unsigned int timeout)
30{
31	unsigned int old_timeout = cli->timeout;
32	cli->timeout = timeout;
33	return old_timeout;
34}
35
36/****************************************************************************
37 Change the port number used to call on.
38****************************************************************************/
39
40int cli_set_port(struct cli_state *cli, int port)
41{
42	cli->port = port;
43	return port;
44}
45
46/****************************************************************************
47 Read an smb from a fd ignoring all keepalive packets. Note that the buffer
48 *MUST* be of size BUFFER_SIZE+SAFETY_MARGIN.
49 The timeout is in milliseconds
50
51 This is exactly the same as receive_smb except that it never returns
52 a session keepalive packet (just as receive_smb used to do).
53 receive_smb was changed to return keepalives as the oplock processing means this call
54 should never go into a blocking read.
55****************************************************************************/
56
57static BOOL client_receive_smb(int fd,char *buffer, unsigned int timeout)
58{
59	BOOL ret;
60
61	for(;;) {
62		ret = receive_smb_raw(fd, buffer, timeout);
63
64		if (!ret) {
65			DEBUG(10,("client_receive_smb failed\n"));
66			show_msg(buffer);
67			return ret;
68		}
69
70		/* Ignore session keepalive packets. */
71		if(CVAL(buffer,0) != SMBkeepalive)
72			break;
73	}
74	show_msg(buffer);
75	return ret;
76}
77
78/****************************************************************************
79 Recv an smb.
80****************************************************************************/
81
82BOOL cli_receive_smb(struct cli_state *cli)
83{
84	extern int smb_read_error;
85	BOOL ret;
86
87	/* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */
88	if (cli->fd == -1)
89		return False;
90
91 again:
92	ret = client_receive_smb(cli->fd,cli->inbuf,cli->timeout);
93
94	if (ret) {
95		/* it might be an oplock break request */
96		if (!(CVAL(cli->inbuf, smb_flg) & FLAG_REPLY) &&
97		    CVAL(cli->inbuf,smb_com) == SMBlockingX &&
98		    SVAL(cli->inbuf,smb_vwv6) == 0 &&
99		    SVAL(cli->inbuf,smb_vwv7) == 0) {
100			if (cli->oplock_handler) {
101				int fnum = SVAL(cli->inbuf,smb_vwv2);
102				unsigned char level = CVAL(cli->inbuf,smb_vwv3+1);
103				if (!cli->oplock_handler(cli, fnum, level)) return False;
104			}
105			/* try to prevent loops */
106			SCVAL(cli->inbuf,smb_com,0xFF);
107			goto again;
108		}
109	}
110
111	/* If the server is not responding, note that now */
112
113	if (!ret) {
114		cli->smb_rw_error = smb_read_error;
115		close(cli->fd);
116		cli->fd = -1;
117		return ret;
118	}
119
120	if (!cli_check_sign_mac(cli)) {
121		DEBUG(0, ("SMB Signature verification failed on incoming packet!\n"));
122		cli->smb_rw_error = READ_BAD_SIG;
123		close(cli->fd);
124		cli->fd = -1;
125		return False;
126	};
127	return True;
128}
129
130/****************************************************************************
131 Send an smb to a fd.
132****************************************************************************/
133
134BOOL cli_send_smb(struct cli_state *cli)
135{
136	size_t len;
137	size_t nwritten=0;
138	ssize_t ret;
139
140	/* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */
141	if (cli->fd == -1)
142		return False;
143
144	cli_calculate_sign_mac(cli);
145
146	len = smb_len(cli->outbuf) + 4;
147
148	while (nwritten < len) {
149		ret = write_socket(cli->fd,cli->outbuf+nwritten,len - nwritten);
150		if (ret <= 0) {
151			close(cli->fd);
152			cli->fd = -1;
153			cli->smb_rw_error = WRITE_ERROR;
154			DEBUG(0,("Error writing %d bytes to client. %d (%s)\n",
155				(int)len,(int)ret, strerror(errno) ));
156			return False;
157		}
158		nwritten += ret;
159	}
160	/* Increment the mid so we can tell between responses. */
161	cli->mid++;
162	if (!cli->mid)
163		cli->mid++;
164	return True;
165}
166
167/****************************************************************************
168 Setup basics in a outgoing packet.
169****************************************************************************/
170
171void cli_setup_packet(struct cli_state *cli)
172{
173	cli->rap_error = 0;
174	SSVAL(cli->outbuf,smb_pid,cli->pid);
175	SSVAL(cli->outbuf,smb_uid,cli->vuid);
176	SSVAL(cli->outbuf,smb_mid,cli->mid);
177	if (cli->protocol > PROTOCOL_CORE) {
178		uint16 flags2;
179		if (cli->case_sensitive) {
180			SCVAL(cli->outbuf,smb_flg,0x0);
181		} else {
182			/* Default setting, case insensitive. */
183			SCVAL(cli->outbuf,smb_flg,0x8);
184		}
185		flags2 = FLAGS2_LONG_PATH_COMPONENTS;
186		if (cli->capabilities & CAP_UNICODE)
187			flags2 |= FLAGS2_UNICODE_STRINGS;
188		if (cli->capabilities & CAP_DFS)
189			flags2 |= FLAGS2_DFS_PATHNAMES;
190		if (cli->capabilities & CAP_STATUS32)
191			flags2 |= FLAGS2_32_BIT_ERROR_CODES;
192		if (cli->use_spnego)
193			flags2 |= FLAGS2_EXTENDED_SECURITY;
194		SSVAL(cli->outbuf,smb_flg2, flags2);
195	}
196}
197
198/****************************************************************************
199 Setup the bcc length of the packet from a pointer to the end of the data.
200****************************************************************************/
201
202void cli_setup_bcc(struct cli_state *cli, void *p)
203{
204	set_message_bcc(cli->outbuf, PTR_DIFF(p, smb_buf(cli->outbuf)));
205}
206
207/****************************************************************************
208 Initialise credentials of a client structure.
209****************************************************************************/
210
211void cli_init_creds(struct cli_state *cli, const struct ntuser_creds *usr)
212{
213        /* copy_nt_creds(&cli->usr, usr); */
214	fstrcpy(cli->domain   , usr->domain);
215	fstrcpy(cli->user_name, usr->user_name);
216	memcpy(&cli->pwd, &usr->pwd, sizeof(usr->pwd));
217
218        DEBUG(10,("cli_init_creds: user %s domain %s\n",
219               cli->user_name, cli->domain));
220}
221
222/****************************************************************************
223 Set the signing state (used from the command line).
224****************************************************************************/
225
226void cli_setup_signing_state(struct cli_state *cli, int signing_state)
227{
228	if (signing_state == Undefined)
229		return;
230
231	if (signing_state == False) {
232		cli->sign_info.allow_smb_signing = False;
233		cli->sign_info.mandatory_signing = False;
234		return;
235	}
236
237	cli->sign_info.allow_smb_signing = True;
238
239	if (signing_state == Required)
240		cli->sign_info.mandatory_signing = True;
241}
242
243/****************************************************************************
244 Initialise a client structure.
245****************************************************************************/
246
247struct cli_state *cli_initialise(struct cli_state *cli)
248{
249        BOOL alloced_cli = False;
250	int i;
251
252	/* Check the effective uid - make sure we are not setuid */
253	if (is_setuid_root()) {
254		DEBUG(0,("libsmb based programs must *NOT* be setuid root.\n"));
255		return NULL;
256	}
257
258	if (!cli) {
259		cli = SMB_MALLOC_P(struct cli_state);
260		if (!cli)
261			return NULL;
262		ZERO_STRUCTP(cli);
263                alloced_cli = True;
264	}
265
266	if (cli->initialised)
267		cli_close_connection(cli);
268
269	ZERO_STRUCTP(cli);
270
271	cli->port = 0;
272	cli->fd = -1;
273	cli->cnum = -1;
274	cli->pid = (uint16)sys_getpid();
275	cli->mid = 1;
276	cli->vuid = UID_FIELD_INVALID;
277	cli->protocol = PROTOCOL_NT1;
278	cli->timeout = 20000; /* Timeout is in milliseconds. */
279	cli->bufsize = CLI_BUFFER_SIZE+4;
280	cli->max_xmit = cli->bufsize;
281	cli->outbuf = (char *)SMB_MALLOC(cli->bufsize+SAFETY_MARGIN);
282	cli->inbuf = (char *)SMB_MALLOC(cli->bufsize+SAFETY_MARGIN);
283	cli->oplock_handler = cli_oplock_ack;
284	cli->case_sensitive = False;
285	cli->smb_rw_error = 0;
286
287	cli->use_spnego = lp_client_use_spnego();
288
289	cli->capabilities = CAP_UNICODE | CAP_STATUS32 | CAP_DFS;
290
291	/* Set the CLI_FORCE_DOSERR environment variable to test
292	   client routines using DOS errors instead of STATUS32
293	   ones.  This intended only as a temporary hack. */
294	if (getenv("CLI_FORCE_DOSERR"))
295		cli->force_dos_errors = True;
296
297	if (lp_client_signing())
298		cli->sign_info.allow_smb_signing = True;
299
300	if (lp_client_signing() == Required)
301		cli->sign_info.mandatory_signing = True;
302
303	if (!cli->outbuf || !cli->inbuf)
304                goto error;
305
306	if ((cli->mem_ctx = talloc_init("cli based talloc")) == NULL)
307                goto error;
308
309	memset(cli->outbuf, 0, cli->bufsize);
310	memset(cli->inbuf, 0, cli->bufsize);
311
312
313#if defined(DEVELOPER)
314	/* just because we over-allocate, doesn't mean it's right to use it */
315	clobber_region(FUNCTION_MACRO, __LINE__, cli->outbuf+cli->bufsize, SAFETY_MARGIN);
316	clobber_region(FUNCTION_MACRO, __LINE__, cli->inbuf+cli->bufsize, SAFETY_MARGIN);
317#endif
318
319	/* initialise signing */
320	cli_null_set_signing(cli);
321
322	for (i=0; i<PI_MAX_PIPES; i++)
323		cli->nt_pipe_fnum[i] = 0;
324
325	cli->saved_netlogon_pipe_fnum = 0;
326
327	cli->initialised = 1;
328	cli->allocated = alloced_cli;
329
330	cli->pipe_idx = -1;
331
332	return cli;
333
334        /* Clean up after malloc() error */
335
336 error:
337
338        SAFE_FREE(cli->inbuf);
339        SAFE_FREE(cli->outbuf);
340
341        if (alloced_cli)
342                SAFE_FREE(cli);
343
344        return NULL;
345}
346
347/****************************************************************************
348close the session
349****************************************************************************/
350
351void cli_nt_session_close(struct cli_state *cli)
352{
353	int i;
354
355	if (cli->ntlmssp_pipe_state) {
356		ntlmssp_end(&cli->ntlmssp_pipe_state);
357	}
358
359	for (i=0; i<PI_MAX_PIPES; i++) {
360		if (cli->nt_pipe_fnum[i] != 0)
361			cli_close(cli, cli->nt_pipe_fnum[i]);
362		cli->nt_pipe_fnum[i] = 0;
363	}
364	cli->pipe_idx = -1;
365}
366
367/****************************************************************************
368close the NETLOGON session holding the session key for NETSEC
369****************************************************************************/
370
371void cli_nt_netlogon_netsec_session_close(struct cli_state *cli)
372{
373	if (cli->saved_netlogon_pipe_fnum != 0) {
374		cli_close(cli, cli->saved_netlogon_pipe_fnum);
375		cli->saved_netlogon_pipe_fnum = 0;
376	}
377}
378
379/****************************************************************************
380 Close a client connection and free the memory without destroying cli itself.
381****************************************************************************/
382
383void cli_close_connection(struct cli_state *cli)
384{
385	cli_nt_session_close(cli);
386	cli_nt_netlogon_netsec_session_close(cli);
387
388	/*
389	 * tell our peer to free his resources.  Wihtout this, when an
390	 * application attempts to do a graceful shutdown and calls
391	 * smbc_free_context() to clean up all connections, some connections
392	 * can remain active on the peer end, until some (long) timeout period
393	 * later.  This tree disconnect forces the peer to clean up, since the
394	 * connection will be going away.
395	 *
396	 * Also, do not do tree disconnect when cli->smb_rw_error is DO_NOT_DO_TDIS
397	 * the only user for this so far is smbmount which passes opened connection
398	 * down to kernel's smbfs module.
399	 */
400	if ( (cli->cnum != (uint16)-1) && (cli->smb_rw_error != DO_NOT_DO_TDIS ) )
401		cli_tdis(cli);
402
403	SAFE_FREE(cli->outbuf);
404	SAFE_FREE(cli->inbuf);
405
406	cli_free_signing_context(cli);
407	data_blob_free(&cli->secblob);
408	data_blob_free(&cli->user_session_key);
409
410	if (cli->ntlmssp_pipe_state)
411		ntlmssp_end(&cli->ntlmssp_pipe_state);
412
413	if (cli->mem_ctx) {
414		talloc_destroy(cli->mem_ctx);
415		cli->mem_ctx = NULL;
416	}
417
418	if (cli->fd != -1)
419		close(cli->fd);
420	cli->fd = -1;
421	cli->smb_rw_error = 0;
422
423}
424
425/****************************************************************************
426 Shutdown a client structure.
427****************************************************************************/
428
429void cli_shutdown(struct cli_state *cli)
430{
431	BOOL allocated = cli->allocated;
432	cli_close_connection(cli);
433	ZERO_STRUCTP(cli);
434	if (allocated)
435		free(cli);
436}
437
438/****************************************************************************
439 Set socket options on a open connection.
440****************************************************************************/
441
442void cli_sockopt(struct cli_state *cli, const char *options)
443{
444	set_socket_options(cli->fd, options);
445}
446
447/****************************************************************************
448 Set the PID to use for smb messages. Return the old pid.
449****************************************************************************/
450
451uint16 cli_setpid(struct cli_state *cli, uint16 pid)
452{
453	uint16 ret = cli->pid;
454	cli->pid = pid;
455	return ret;
456}
457
458/****************************************************************************
459 Set the case sensitivity flag on the packets. Returns old state.
460****************************************************************************/
461
462BOOL cli_set_case_sensitive(struct cli_state *cli, BOOL case_sensitive)
463{
464	BOOL ret = cli->case_sensitive;
465	cli->case_sensitive = case_sensitive;
466	return ret;
467}
468
469/****************************************************************************
470Send a keepalive packet to the server
471****************************************************************************/
472BOOL cli_send_keepalive(struct cli_state *cli)
473{
474        if (cli->fd == -1) {
475                DEBUG(3, ("cli_send_keepalive: fd == -1\n"));
476                return False;
477        }
478        if (!send_keepalive(cli->fd)) {
479                close(cli->fd);
480                cli->fd = -1;
481                DEBUG(0,("Error sending keepalive packet to client.\n"));
482                return False;
483        }
484        return True;
485}
486