r24223: Convert reply_echo to the new API
[kai/samba.git] / source3 / libsmb / clientgen.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB client generic functions
4    Copyright (C) Andrew Tridgell 1994-1998
5    Copyright (C) Jeremy Allison 2007.
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 3 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, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22
23 extern int smb_read_error;
24
25 /****************************************************************************
26  Change the timeout (in milliseconds).
27 ****************************************************************************/
28
29 unsigned 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
40 int 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 can be set to never return
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
57 static ssize_t client_receive_smb(struct cli_state *cli, BOOL eat_keepalives, size_t maxlen)
58 {
59         ssize_t len;
60         int fd = cli->fd;
61         char *buffer = cli->inbuf;
62         unsigned int timeout = cli->timeout;
63
64         for(;;) {
65                 len = receive_smb_raw(fd, buffer, timeout, maxlen);
66
67                 if (len < 0) {
68                         DEBUG(10,("client_receive_smb failed\n"));
69                         show_msg(buffer);
70                         return len;
71                 }
72
73                 /* Ignore session keepalive packets. */
74                 if (eat_keepalives && (CVAL(buffer,0) == SMBkeepalive)) {
75                         continue;
76                 }
77                 break;
78         }
79
80         if (cli_encryption_on(cli)) {
81                 NTSTATUS status = cli_decrypt_message(cli);
82                 if (!NT_STATUS_IS_OK(status)) {
83                         DEBUG(0, ("SMB decryption failed on incoming packet! Error %s\n",
84                                 nt_errstr(status)));
85                         cli->smb_rw_error = READ_BAD_DECRYPT;
86                         close(cli->fd);
87                         cli->fd = -1;
88                         return -1;
89                 }
90         }
91         show_msg(buffer);
92         return len;
93 }
94
95 /****************************************************************************
96  Recv an smb.
97 ****************************************************************************/
98
99 BOOL cli_receive_smb_internal(struct cli_state *cli, BOOL eat_keepalives)
100 {
101         ssize_t len;
102
103         /* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */
104         if (cli->fd == -1)
105                 return False; 
106
107  again:
108         len = client_receive_smb(cli, eat_keepalives, 0);
109
110         if (len >= 0 && !eat_keepalives && (CVAL(cli->inbuf,0) == SMBkeepalive)) {
111                 /* Give back the keepalive. */
112                 return True;
113         }
114         
115         if (len > 0) {
116                 /* it might be an oplock break request */
117                 if (!(CVAL(cli->inbuf, smb_flg) & FLAG_REPLY) &&
118                     CVAL(cli->inbuf,smb_com) == SMBlockingX &&
119                     SVAL(cli->inbuf,smb_vwv6) == 0 &&
120                     SVAL(cli->inbuf,smb_vwv7) == 0) {
121                         if (cli->oplock_handler) {
122                                 int fnum = SVAL(cli->inbuf,smb_vwv2);
123                                 unsigned char level = CVAL(cli->inbuf,smb_vwv3+1);
124                                 if (!cli->oplock_handler(cli, fnum, level)) {
125                                         return False;
126                                 }
127                         }
128                         /* try to prevent loops */
129                         SCVAL(cli->inbuf,smb_com,0xFF);
130                         goto again;
131                 }
132         }
133
134         /* If the server is not responding, note that now */
135         if (len < 0) {
136                 DEBUG(0, ("Receiving SMB: Server stopped responding\n"));
137                 cli->smb_rw_error = smb_read_error;
138                 close(cli->fd);
139                 cli->fd = -1;
140                 return False;
141         }
142
143         if (!cli_check_sign_mac(cli)) {
144                 /*
145                  * If we get a signature failure in sessionsetup, then
146                  * the server sometimes just reflects the sent signature
147                  * back to us. Detect this and allow the upper layer to
148                  * retrieve the correct Windows error message.
149                  */
150                 if (CVAL(cli->outbuf,smb_com) == SMBsesssetupX &&
151                         (smb_len(cli->inbuf) > (smb_ss_field + 8 - 4)) &&
152                         (SVAL(cli->inbuf,smb_flg2) & FLAGS2_SMB_SECURITY_SIGNATURES) &&
153                         memcmp(&cli->outbuf[smb_ss_field],&cli->inbuf[smb_ss_field],8) == 0 &&
154                         cli_is_error(cli)) {
155
156                         /*
157                          * Reflected signature on login error. 
158                          * Set bad sig but don't close fd.
159                          */
160                         cli->smb_rw_error = READ_BAD_SIG;
161                         return True;
162                 }
163
164                 DEBUG(0, ("SMB Signature verification failed on incoming packet!\n"));
165                 cli->smb_rw_error = READ_BAD_SIG;
166                 close(cli->fd);
167                 cli->fd = -1;
168                 return False;
169         }
170
171         return True;
172 }
173
174 /****************************************************************************
175  Recv an smb - eat keepalives.
176 ****************************************************************************/
177
178 BOOL cli_receive_smb(struct cli_state *cli)
179 {
180         return cli_receive_smb_internal(cli, True);
181 }
182
183 /****************************************************************************
184  Recv an smb - return keepalives.
185 ****************************************************************************/
186
187 BOOL cli_receive_smb_return_keepalive(struct cli_state *cli)
188 {
189         return cli_receive_smb_internal(cli, False);
190 }
191
192 /****************************************************************************
193  Read the data portion of a readX smb.
194  The timeout is in milliseconds
195 ****************************************************************************/
196
197 ssize_t cli_receive_smb_data(struct cli_state *cli, char *buffer, size_t len)
198 {
199         if (cli->timeout > 0) {
200                 return read_socket_with_timeout(cli->fd, buffer, len, len, cli->timeout);
201         } else {
202                 return read_data(cli->fd, buffer, len);
203         }
204 }
205
206 /****************************************************************************
207  Read a smb readX header.
208  We can only use this if encryption and signing are off.
209 ****************************************************************************/
210
211 BOOL cli_receive_smb_readX_header(struct cli_state *cli)
212 {
213         ssize_t len, offset;
214
215         if (cli->fd == -1)
216                 return False; 
217
218  again:
219
220         /* Read up to the size of a readX header reply. */
221         len = client_receive_smb(cli, True, (smb_size - 4) + 24);
222         
223         if (len > 0) {
224                 /* it might be an oplock break request */
225                 if (!(CVAL(cli->inbuf, smb_flg) & FLAG_REPLY) &&
226                     CVAL(cli->inbuf,smb_com) == SMBlockingX &&
227                     SVAL(cli->inbuf,smb_vwv6) == 0 &&
228                     SVAL(cli->inbuf,smb_vwv7) == 0) {
229                         ssize_t total_len = smb_len(cli->inbuf);
230
231                         if (total_len > CLI_SAMBA_MAX_LARGE_READX_SIZE+SAFETY_MARGIN) {
232                                 goto read_err;
233                         }
234
235                         /* Read the rest of the data. */
236                         if ((total_len - len > 0) &&
237                             !cli_receive_smb_data(cli,cli->inbuf+len,total_len - len)) {
238                                 goto read_err;
239                         }
240
241                         if (cli->oplock_handler) {
242                                 int fnum = SVAL(cli->inbuf,smb_vwv2);
243                                 unsigned char level = CVAL(cli->inbuf,smb_vwv3+1);
244                                 if (!cli->oplock_handler(cli, fnum, level)) return False;
245                         }
246                         /* try to prevent loops */
247                         SCVAL(cli->inbuf,smb_com,0xFF);
248                         goto again;
249                 }
250         }
251
252         /* If it's not the above size it probably was an error packet. */
253
254         if ((len == (smb_size - 4) + 24) && !cli_is_error(cli)) {
255                 /* Check it's a non-chained readX reply. */
256                 if (!(CVAL(cli->inbuf, smb_flg) & FLAG_REPLY) ||
257                         (CVAL(cli->inbuf,smb_vwv0) != 0xFF) ||
258                         (CVAL(cli->inbuf,smb_com) != SMBreadX)) {
259                         /* 
260                          * We're not coping here with asnyc replies to
261                          * other calls. Punt here - we need async client
262                          * libs for this.
263                          */
264                         goto read_err;
265                 }
266
267                 /* 
268                  * We know it's a readX reply - ensure we've read the
269                  * padding bytes also.
270                  */
271
272                 offset = SVAL(cli->inbuf,smb_vwv6);
273                 if (offset > len) {
274                         ssize_t ret;
275                         size_t padbytes = offset - len;
276                         ret = cli_receive_smb_data(cli,smb_buf(cli->inbuf),padbytes);
277                         if (ret != padbytes) {
278                                 goto read_err;
279                         }
280                 }
281         }
282
283         return True;
284
285   read_err:
286
287         cli->smb_rw_error = smb_read_error = READ_ERROR;
288         close(cli->fd);
289         cli->fd = -1;
290         return False;
291 }
292
293 static ssize_t write_socket(int fd, const char *buf, size_t len)
294 {
295         ssize_t ret=0;
296                                                                                                                                             
297         DEBUG(6,("write_socket(%d,%d)\n",fd,(int)len));
298         ret = write_data(fd,buf,len);
299
300         DEBUG(6,("write_socket(%d,%d) wrote %d\n",fd,(int)len,(int)ret));
301         if(ret <= 0)
302                 DEBUG(0,("write_socket: Error writing %d bytes to socket %d: ERRNO = %s\n",
303                         (int)len, fd, strerror(errno) ));
304                                                                                                                                             
305         return(ret);
306 }
307
308 /****************************************************************************
309  Send an smb to a fd.
310 ****************************************************************************/
311
312 BOOL cli_send_smb(struct cli_state *cli)
313 {
314         size_t len;
315         size_t nwritten=0;
316         ssize_t ret;
317         char *buf_out = cli->outbuf;
318         BOOL enc_on = cli_encryption_on(cli);
319
320         /* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */
321         if (cli->fd == -1) {
322                 return False;
323         }
324
325         cli_calculate_sign_mac(cli);
326
327         if (enc_on) {
328                 NTSTATUS status = cli_encrypt_message(cli, &buf_out);
329                 if (!NT_STATUS_IS_OK(status)) {
330                         close(cli->fd);
331                         cli->fd = -1;
332                         cli->smb_rw_error = WRITE_ERROR;
333                         DEBUG(0,("Error in encrypting client message. Error %s\n",
334                                 nt_errstr(status) ));
335                         return False;
336                 }
337         }
338
339         len = smb_len(buf_out) + 4;
340
341         while (nwritten < len) {
342                 ret = write_socket(cli->fd,buf_out+nwritten,len - nwritten);
343                 if (ret <= 0) {
344                         if (enc_on) {
345                                 cli_free_enc_buffer(cli, buf_out);
346                         }
347                         close(cli->fd);
348                         cli->fd = -1;
349                         cli->smb_rw_error = WRITE_ERROR;
350                         DEBUG(0,("Error writing %d bytes to client. %d (%s)\n",
351                                 (int)len,(int)ret, strerror(errno) ));
352                         return False;
353                 }
354                 nwritten += ret;
355         }
356
357         cli_free_enc_buffer(cli, buf_out);
358
359         /* Increment the mid so we can tell between responses. */
360         cli->mid++;
361         if (!cli->mid) {
362                 cli->mid++;
363         }
364         return True;
365 }
366
367 /****************************************************************************
368  Setup basics in a outgoing packet.
369 ****************************************************************************/
370
371 void cli_setup_packet(struct cli_state *cli)
372 {
373         cli->rap_error = 0;
374         SSVAL(cli->outbuf,smb_pid,cli->pid);
375         SSVAL(cli->outbuf,smb_uid,cli->vuid);
376         SSVAL(cli->outbuf,smb_mid,cli->mid);
377         if (cli->protocol > PROTOCOL_CORE) {
378                 uint16 flags2;
379                 if (cli->case_sensitive) {
380                         SCVAL(cli->outbuf,smb_flg,0x0);
381                 } else {
382                         /* Default setting, case insensitive. */
383                         SCVAL(cli->outbuf,smb_flg,0x8);
384                 }
385                 flags2 = FLAGS2_LONG_PATH_COMPONENTS;
386                 if (cli->capabilities & CAP_UNICODE)
387                         flags2 |= FLAGS2_UNICODE_STRINGS;
388                 if ((cli->capabilities & CAP_DFS) && cli->dfsroot)
389                         flags2 |= FLAGS2_DFS_PATHNAMES;
390                 if (cli->capabilities & CAP_STATUS32)
391                         flags2 |= FLAGS2_32_BIT_ERROR_CODES;
392                 if (cli->use_spnego)
393                         flags2 |= FLAGS2_EXTENDED_SECURITY;
394                 SSVAL(cli->outbuf,smb_flg2, flags2);
395         }
396 }
397
398 /****************************************************************************
399  Setup the bcc length of the packet from a pointer to the end of the data.
400 ****************************************************************************/
401
402 void cli_setup_bcc(struct cli_state *cli, void *p)
403 {
404         set_message_bcc(NULL,cli->outbuf, PTR_DIFF(p, smb_buf(cli->outbuf)));
405 }
406
407 /****************************************************************************
408  Initialise credentials of a client structure.
409 ****************************************************************************/
410
411 void cli_init_creds(struct cli_state *cli, const char *username, const char *domain, const char *password)
412 {
413         fstrcpy(cli->domain, domain);
414         fstrcpy(cli->user_name, username);
415         pwd_set_cleartext(&cli->pwd, password);
416         if (!*username) {
417                 cli->pwd.null_pwd = True;
418         }
419
420         DEBUG(10,("cli_init_creds: user %s domain %s\n", cli->user_name, cli->domain));
421 }
422
423 /****************************************************************************
424  Set the signing state (used from the command line).
425 ****************************************************************************/
426
427 void cli_setup_signing_state(struct cli_state *cli, int signing_state)
428 {
429         if (signing_state == Undefined)
430                 return;
431
432         if (signing_state == False) {
433                 cli->sign_info.allow_smb_signing = False;
434                 cli->sign_info.mandatory_signing = False;
435                 return;
436         }
437
438         cli->sign_info.allow_smb_signing = True;
439
440         if (signing_state == Required) 
441                 cli->sign_info.mandatory_signing = True;
442 }
443
444 /****************************************************************************
445  Initialise a client structure. Always returns a malloc'ed struct.
446 ****************************************************************************/
447
448 struct cli_state *cli_initialise(void)
449 {
450         struct cli_state *cli = NULL;
451
452         /* Check the effective uid - make sure we are not setuid */
453         if (is_setuid_root()) {
454                 DEBUG(0,("libsmb based programs must *NOT* be setuid root.\n"));
455                 return NULL;
456         }
457
458         cli = SMB_MALLOC_P(struct cli_state);
459         if (!cli) {
460                 return NULL;
461         }
462
463         ZERO_STRUCTP(cli);
464
465         cli->port = 0;
466         cli->fd = -1;
467         cli->cnum = -1;
468         cli->pid = (uint16)sys_getpid();
469         cli->mid = 1;
470         cli->vuid = UID_FIELD_INVALID;
471         cli->protocol = PROTOCOL_NT1;
472         cli->timeout = 20000; /* Timeout is in milliseconds. */
473         cli->bufsize = CLI_BUFFER_SIZE+4;
474         cli->max_xmit = cli->bufsize;
475         cli->outbuf = (char *)SMB_MALLOC(cli->bufsize+SAFETY_MARGIN);
476         cli->inbuf = (char *)SMB_MALLOC(cli->bufsize+SAFETY_MARGIN);
477         cli->oplock_handler = cli_oplock_ack;
478         cli->case_sensitive = False;
479         cli->smb_rw_error = 0;
480
481         cli->use_spnego = lp_client_use_spnego();
482
483         cli->capabilities = CAP_UNICODE | CAP_STATUS32 | CAP_DFS;
484
485         /* Set the CLI_FORCE_DOSERR environment variable to test
486            client routines using DOS errors instead of STATUS32
487            ones.  This intended only as a temporary hack. */    
488         if (getenv("CLI_FORCE_DOSERR"))
489                 cli->force_dos_errors = True;
490
491         if (lp_client_signing()) 
492                 cli->sign_info.allow_smb_signing = True;
493
494         if (lp_client_signing() == Required) 
495                 cli->sign_info.mandatory_signing = True;
496                                    
497         if (!cli->outbuf || !cli->inbuf)
498                 goto error;
499
500         if ((cli->mem_ctx = talloc_init("cli based talloc")) == NULL)
501                 goto error;
502
503         memset(cli->outbuf, 0, cli->bufsize);
504         memset(cli->inbuf, 0, cli->bufsize);
505
506
507 #if defined(DEVELOPER)
508         /* just because we over-allocate, doesn't mean it's right to use it */
509         clobber_region(FUNCTION_MACRO, __LINE__, cli->outbuf+cli->bufsize, SAFETY_MARGIN);
510         clobber_region(FUNCTION_MACRO, __LINE__, cli->inbuf+cli->bufsize, SAFETY_MARGIN);
511 #endif
512
513         /* initialise signing */
514         cli_null_set_signing(cli);
515
516         cli->initialised = 1;
517
518         return cli;
519
520         /* Clean up after malloc() error */
521
522  error:
523
524         SAFE_FREE(cli->inbuf);
525         SAFE_FREE(cli->outbuf);
526         SAFE_FREE(cli);
527         return NULL;
528 }
529
530 /****************************************************************************
531  External interface.
532  Close an open named pipe over SMB. Free any authentication data.
533  Returns False if the cli_close call failed.
534  ****************************************************************************/
535
536 BOOL cli_rpc_pipe_close(struct rpc_pipe_client *cli)
537 {
538         BOOL ret;
539
540         if (!cli) {
541                 return False;
542         }
543
544         ret = cli_close(cli->cli, cli->fnum);
545
546         if (!ret) {
547                 DEBUG(1,("cli_rpc_pipe_close: cli_close failed on pipe %s, "
548                          "fnum 0x%x "
549                          "to machine %s.  Error was %s\n",
550                          cli->pipe_name,
551                          (int) cli->fnum,
552                          cli->cli->desthost,
553                          cli_errstr(cli->cli)));
554         }
555
556         if (cli->auth.cli_auth_data_free_func) {
557                 (*cli->auth.cli_auth_data_free_func)(&cli->auth);
558         }
559
560         DEBUG(10,("cli_rpc_pipe_close: closed pipe %s to machine %s\n",
561                 cli->pipe_name, cli->cli->desthost ));
562
563         DLIST_REMOVE(cli->cli->pipe_list, cli);
564         talloc_destroy(cli->mem_ctx);
565         return ret;
566 }
567
568 /****************************************************************************
569  Close all pipes open on this session.
570 ****************************************************************************/
571
572 void cli_nt_pipes_close(struct cli_state *cli)
573 {
574         struct rpc_pipe_client *cp, *next;
575
576         for (cp = cli->pipe_list; cp; cp = next) {
577                 next = cp->next;
578                 cli_rpc_pipe_close(cp);
579         }
580 }
581
582 /****************************************************************************
583  Shutdown a client structure.
584 ****************************************************************************/
585
586 void cli_shutdown(struct cli_state *cli)
587 {
588         cli_nt_pipes_close(cli);
589
590         /*
591          * tell our peer to free his resources.  Wihtout this, when an
592          * application attempts to do a graceful shutdown and calls
593          * smbc_free_context() to clean up all connections, some connections
594          * can remain active on the peer end, until some (long) timeout period
595          * later.  This tree disconnect forces the peer to clean up, since the
596          * connection will be going away.
597          *
598          * Also, do not do tree disconnect when cli->smb_rw_error is DO_NOT_DO_TDIS
599          * the only user for this so far is smbmount which passes opened connection
600          * down to kernel's smbfs module.
601          */
602         if ( (cli->cnum != (uint16)-1) && (cli->smb_rw_error != DO_NOT_DO_TDIS ) ) {
603                 cli_tdis(cli);
604         }
605         
606         SAFE_FREE(cli->outbuf);
607         SAFE_FREE(cli->inbuf);
608
609         cli_free_signing_context(cli);
610         cli_free_encryption_context(cli);
611
612         data_blob_free(&cli->secblob);
613         data_blob_free(&cli->user_session_key);
614
615         if (cli->mem_ctx) {
616                 talloc_destroy(cli->mem_ctx);
617                 cli->mem_ctx = NULL;
618         }
619
620         if (cli->fd != -1) {
621                 close(cli->fd);
622         }
623         cli->fd = -1;
624         cli->smb_rw_error = 0;
625
626         SAFE_FREE(cli);
627 }
628
629 /****************************************************************************
630  Set socket options on a open connection.
631 ****************************************************************************/
632
633 void cli_sockopt(struct cli_state *cli, const char *options)
634 {
635         set_socket_options(cli->fd, options);
636 }
637
638 /****************************************************************************
639  Set the PID to use for smb messages. Return the old pid.
640 ****************************************************************************/
641
642 uint16 cli_setpid(struct cli_state *cli, uint16 pid)
643 {
644         uint16 ret = cli->pid;
645         cli->pid = pid;
646         return ret;
647 }
648
649 /****************************************************************************
650  Set the case sensitivity flag on the packets. Returns old state.
651 ****************************************************************************/
652
653 BOOL cli_set_case_sensitive(struct cli_state *cli, BOOL case_sensitive)
654 {
655         BOOL ret = cli->case_sensitive;
656         cli->case_sensitive = case_sensitive;
657         return ret;
658 }
659
660 /****************************************************************************
661 Send a keepalive packet to the server
662 ****************************************************************************/
663
664 BOOL cli_send_keepalive(struct cli_state *cli)
665 {
666         if (cli->fd == -1) {
667                 DEBUG(3, ("cli_send_keepalive: fd == -1\n"));
668                 return False;
669         }
670         if (!send_keepalive(cli->fd)) {
671                 close(cli->fd);
672                 cli->fd = -1;
673                 DEBUG(0,("Error sending keepalive packet to client.\n"));
674                 return False;
675         }
676         return True;
677 }
678
679 /****************************************************************************
680  Send/receive a SMBecho command: ping the server
681 ****************************************************************************/
682
683 BOOL cli_echo(struct cli_state *cli, uint16 num_echos,
684               unsigned char *data, size_t length)
685 {
686         char *p;
687         int i;
688
689         SMB_ASSERT(length < 1024);
690
691         memset(cli->outbuf,'\0',smb_size);
692         set_message(NULL,cli->outbuf,1,length,True);
693         SCVAL(cli->outbuf,smb_com,SMBecho);
694         SSVAL(cli->outbuf,smb_tid,65535);
695         SSVAL(cli->outbuf,smb_vwv0,num_echos);
696         cli_setup_packet(cli);
697         p = smb_buf(cli->outbuf);
698         memcpy(p, data, length);
699         p += length;
700
701         cli_setup_bcc(cli, p);
702
703         cli_send_smb(cli);
704
705         for (i=0; i<num_echos; i++) {
706                 if (!cli_receive_smb(cli)) {
707                         return False;
708                 }
709
710                 if (cli_is_error(cli)) {
711                         return False;
712                 }
713         }
714
715         return True;
716 }