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