00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "includes.h"
00022
00023 extern int smb_read_error;
00024
00025
00026
00027
00028
00029 unsigned int cli_set_timeout(struct cli_state *cli, unsigned int timeout)
00030 {
00031 unsigned int old_timeout = cli->timeout;
00032 cli->timeout = timeout;
00033 return old_timeout;
00034 }
00035
00036
00037
00038
00039
00040 int cli_set_port(struct cli_state *cli, int port)
00041 {
00042 cli->port = port;
00043 return port;
00044 }
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 static BOOL client_receive_smb(int fd,char *buffer, size_t bufsize, unsigned int timeout)
00057 {
00058 BOOL ret;
00059
00060 for(;;) {
00061 ret = receive_smb_raw(fd, buffer, bufsize, timeout);
00062
00063 if (!ret) {
00064 DEBUG(10,("client_receive_smb failed\n"));
00065 show_msg(buffer);
00066 return ret;
00067 }
00068
00069
00070 if(CVAL(buffer,0) != SMBkeepalive)
00071 break;
00072 }
00073 show_msg(buffer);
00074 return ret;
00075 }
00076
00077
00078
00079
00080
00081 BOOL cli_receive_smb(struct cli_state *cli)
00082 {
00083 BOOL ret;
00084
00085
00086 if (cli->fd == -1)
00087 return False;
00088
00089 again:
00090 ret = client_receive_smb(cli->fd,cli->inbuf, cli->bufsize, cli->timeout);
00091
00092 if (ret) {
00093
00094 if (!(CVAL(cli->inbuf, smb_flg) & FLAG_REPLY) &&
00095 CVAL(cli->inbuf,smb_com) == SMBlockingX &&
00096 SVAL(cli->inbuf,smb_vwv6) == 0 &&
00097 SVAL(cli->inbuf,smb_vwv7) == 0) {
00098 if (cli->oplock_handler) {
00099 int fnum = SVAL(cli->inbuf,smb_vwv2);
00100 unsigned char level = CVAL(cli->inbuf,smb_vwv3+1);
00101 if (!cli->oplock_handler(cli, fnum, level)) return False;
00102 }
00103
00104 SCVAL(cli->inbuf,smb_com,0xFF);
00105 goto again;
00106 }
00107 }
00108
00109
00110 if (!ret) {
00111 DEBUG(0, ("Receiving SMB: Server stopped responding\n"));
00112 cli->smb_rw_error = smb_read_error;
00113 close(cli->fd);
00114 cli->fd = -1;
00115 return ret;
00116 }
00117
00118 if (!cli_check_sign_mac(cli)) {
00119
00120
00121
00122
00123
00124
00125 if (CVAL(cli->outbuf,smb_com) == SMBsesssetupX &&
00126 (smb_len(cli->inbuf) > (smb_ss_field + 8 - 4)) &&
00127 (SVAL(cli->inbuf,smb_flg2) & FLAGS2_SMB_SECURITY_SIGNATURES) &&
00128 memcmp(&cli->outbuf[smb_ss_field],&cli->inbuf[smb_ss_field],8) == 0 &&
00129 cli_is_error(cli)) {
00130
00131
00132
00133
00134
00135 cli->smb_rw_error = READ_BAD_SIG;
00136 return True;
00137 }
00138
00139 DEBUG(0, ("SMB Signature verification failed on incoming packet!\n"));
00140 cli->smb_rw_error = READ_BAD_SIG;
00141 close(cli->fd);
00142 cli->fd = -1;
00143 return False;
00144 };
00145 return True;
00146 }
00147
00148 static ssize_t write_socket(int fd, const char *buf, size_t len)
00149 {
00150 ssize_t ret=0;
00151
00152 DEBUG(6,("write_socket(%d,%d)\n",fd,(int)len));
00153 ret = write_data(fd,buf,len);
00154
00155 DEBUG(6,("write_socket(%d,%d) wrote %d\n",fd,(int)len,(int)ret));
00156 if(ret <= 0)
00157 DEBUG(0,("write_socket: Error writing %d bytes to socket %d: ERRNO = %s\n",
00158 (int)len, fd, strerror(errno) ));
00159
00160 return(ret);
00161 }
00162
00163
00164
00165
00166
00167 BOOL cli_send_smb(struct cli_state *cli)
00168 {
00169 size_t len;
00170 size_t nwritten=0;
00171 ssize_t ret;
00172
00173
00174 if (cli->fd == -1)
00175 return False;
00176
00177 cli_calculate_sign_mac(cli);
00178
00179 len = smb_len(cli->outbuf) + 4;
00180
00181 while (nwritten < len) {
00182 ret = write_socket(cli->fd,cli->outbuf+nwritten,len - nwritten);
00183 if (ret <= 0) {
00184 close(cli->fd);
00185 cli->fd = -1;
00186 cli->smb_rw_error = WRITE_ERROR;
00187 DEBUG(0,("Error writing %d bytes to client. %d (%s)\n",
00188 (int)len,(int)ret, strerror(errno) ));
00189 return False;
00190 }
00191 nwritten += ret;
00192 }
00193
00194 cli->mid++;
00195 if (!cli->mid)
00196 cli->mid++;
00197 return True;
00198 }
00199
00200
00201
00202
00203
00204 void cli_setup_packet(struct cli_state *cli)
00205 {
00206 cli->rap_error = 0;
00207 SSVAL(cli->outbuf,smb_pid,cli->pid);
00208 SSVAL(cli->outbuf,smb_uid,cli->vuid);
00209 SSVAL(cli->outbuf,smb_mid,cli->mid);
00210 if (cli->protocol > PROTOCOL_CORE) {
00211 uint16 flags2;
00212 if (cli->case_sensitive) {
00213 SCVAL(cli->outbuf,smb_flg,0x0);
00214 } else {
00215
00216 SCVAL(cli->outbuf,smb_flg,0x8);
00217 }
00218 flags2 = FLAGS2_LONG_PATH_COMPONENTS;
00219 if (cli->capabilities & CAP_UNICODE)
00220 flags2 |= FLAGS2_UNICODE_STRINGS;
00221 if ((cli->capabilities & CAP_DFS) && cli->dfsroot)
00222 flags2 |= FLAGS2_DFS_PATHNAMES;
00223 if (cli->capabilities & CAP_STATUS32)
00224 flags2 |= FLAGS2_32_BIT_ERROR_CODES;
00225 if (cli->use_spnego)
00226 flags2 |= FLAGS2_EXTENDED_SECURITY;
00227 SSVAL(cli->outbuf,smb_flg2, flags2);
00228 }
00229 }
00230
00231
00232
00233
00234
00235 void cli_setup_bcc(struct cli_state *cli, void *p)
00236 {
00237 set_message_bcc(cli->outbuf, PTR_DIFF(p, smb_buf(cli->outbuf)));
00238 }
00239
00240
00241
00242
00243
00244 void cli_init_creds(struct cli_state *cli, const char *username, const char *domain, const char *password)
00245 {
00246 fstrcpy(cli->domain, domain);
00247 fstrcpy(cli->user_name, username);
00248 pwd_set_cleartext(&cli->pwd, password);
00249 if (!*username) {
00250 cli->pwd.null_pwd = True;
00251 }
00252
00253 DEBUG(10,("cli_init_creds: user %s domain %s\n", cli->user_name, cli->domain));
00254 }
00255
00256
00257
00258
00259
00260 void cli_setup_signing_state(struct cli_state *cli, int signing_state)
00261 {
00262 if (signing_state == Undefined)
00263 return;
00264
00265 if (signing_state == False) {
00266 cli->sign_info.allow_smb_signing = False;
00267 cli->sign_info.mandatory_signing = False;
00268 return;
00269 }
00270
00271 cli->sign_info.allow_smb_signing = True;
00272
00273 if (signing_state == Required)
00274 cli->sign_info.mandatory_signing = True;
00275 }
00276
00277
00278
00279
00280
00281 struct cli_state *cli_initialise(void)
00282 {
00283 struct cli_state *cli = NULL;
00284
00285
00286 if (is_setuid_root()) {
00287 DEBUG(0,("libsmb based programs must *NOT* be setuid root.\n"));
00288 return NULL;
00289 }
00290
00291 cli = SMB_MALLOC_P(struct cli_state);
00292 if (!cli) {
00293 return NULL;
00294 }
00295
00296 ZERO_STRUCTP(cli);
00297
00298 cli->port = 0;
00299 cli->fd = -1;
00300 cli->cnum = -1;
00301 cli->pid = (uint16)sys_getpid();
00302 cli->mid = 1;
00303 cli->vuid = UID_FIELD_INVALID;
00304 cli->protocol = PROTOCOL_NT1;
00305 cli->timeout = 20000;
00306 cli->bufsize = CLI_BUFFER_SIZE+4;
00307 cli->max_xmit = cli->bufsize;
00308 cli->outbuf = (char *)SMB_MALLOC(cli->bufsize+SAFETY_MARGIN);
00309 cli->inbuf = (char *)SMB_MALLOC(cli->bufsize+SAFETY_MARGIN);
00310 cli->oplock_handler = cli_oplock_ack;
00311 cli->case_sensitive = False;
00312 cli->smb_rw_error = 0;
00313
00314 cli->use_spnego = lp_client_use_spnego();
00315
00316 cli->capabilities = CAP_UNICODE | CAP_STATUS32 | CAP_DFS;
00317
00318
00319
00320
00321 if (getenv("CLI_FORCE_DOSERR"))
00322 cli->force_dos_errors = True;
00323
00324 if (lp_client_signing())
00325 cli->sign_info.allow_smb_signing = True;
00326
00327 if (lp_client_signing() == Required)
00328 cli->sign_info.mandatory_signing = True;
00329
00330 if (!cli->outbuf || !cli->inbuf)
00331 goto error;
00332
00333 if ((cli->mem_ctx = talloc_init("cli based talloc")) == NULL)
00334 goto error;
00335
00336 memset(cli->outbuf, 0, cli->bufsize);
00337 memset(cli->inbuf, 0, cli->bufsize);
00338
00339
00340 #if defined(DEVELOPER)
00341
00342 clobber_region(FUNCTION_MACRO, __LINE__, cli->outbuf+cli->bufsize, SAFETY_MARGIN);
00343 clobber_region(FUNCTION_MACRO, __LINE__, cli->inbuf+cli->bufsize, SAFETY_MARGIN);
00344 #endif
00345
00346
00347 cli_null_set_signing(cli);
00348
00349 cli->initialised = 1;
00350
00351 return cli;
00352
00353
00354
00355 error:
00356
00357 SAFE_FREE(cli->inbuf);
00358 SAFE_FREE(cli->outbuf);
00359 SAFE_FREE(cli);
00360 return NULL;
00361 }
00362
00363
00364
00365
00366
00367
00368
00369 BOOL cli_rpc_pipe_close(struct rpc_pipe_client *cli)
00370 {
00371 BOOL ret;
00372
00373 if (!cli) {
00374 return False;
00375 }
00376
00377 ret = cli_close(cli->cli, cli->fnum);
00378
00379 if (!ret) {
00380 DEBUG(1,("cli_rpc_pipe_close: cli_close failed on pipe %s, "
00381 "fnum 0x%x "
00382 "to machine %s. Error was %s\n",
00383 cli->pipe_name,
00384 (int) cli->fnum,
00385 cli->cli->desthost,
00386 cli_errstr(cli->cli)));
00387 }
00388
00389 if (cli->auth.cli_auth_data_free_func) {
00390 (*cli->auth.cli_auth_data_free_func)(&cli->auth);
00391 }
00392
00393 DEBUG(10,("cli_rpc_pipe_close: closed pipe %s to machine %s\n",
00394 cli->pipe_name, cli->cli->desthost ));
00395
00396 DLIST_REMOVE(cli->cli->pipe_list, cli);
00397 talloc_destroy(cli->mem_ctx);
00398 return ret;
00399 }
00400
00401
00402
00403
00404
00405 void cli_nt_pipes_close(struct cli_state *cli)
00406 {
00407 struct rpc_pipe_client *cp, *next;
00408
00409 for (cp = cli->pipe_list; cp; cp = next) {
00410 next = cp->next;
00411 cli_rpc_pipe_close(cp);
00412 }
00413 }
00414
00415
00416
00417
00418
00419 void cli_shutdown(struct cli_state *cli)
00420 {
00421 cli_nt_pipes_close(cli);
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435 if ( (cli->cnum != (uint16)-1) && (cli->smb_rw_error != DO_NOT_DO_TDIS ) ) {
00436 cli_tdis(cli);
00437 }
00438
00439 SAFE_FREE(cli->outbuf);
00440 SAFE_FREE(cli->inbuf);
00441
00442 cli_free_signing_context(cli);
00443 data_blob_free(&cli->secblob);
00444 data_blob_free(&cli->user_session_key);
00445
00446 if (cli->mem_ctx) {
00447 talloc_destroy(cli->mem_ctx);
00448 cli->mem_ctx = NULL;
00449 }
00450
00451 if (cli->fd != -1) {
00452 close(cli->fd);
00453 }
00454 cli->fd = -1;
00455 cli->smb_rw_error = 0;
00456
00457 SAFE_FREE(cli);
00458 }
00459
00460
00461
00462
00463
00464 void cli_sockopt(struct cli_state *cli, const char *options)
00465 {
00466 set_socket_options(cli->fd, options);
00467 }
00468
00469
00470
00471
00472
00473 uint16 cli_setpid(struct cli_state *cli, uint16 pid)
00474 {
00475 uint16 ret = cli->pid;
00476 cli->pid = pid;
00477 return ret;
00478 }
00479
00480
00481
00482
00483
00484 BOOL cli_set_case_sensitive(struct cli_state *cli, BOOL case_sensitive)
00485 {
00486 BOOL ret = cli->case_sensitive;
00487 cli->case_sensitive = case_sensitive;
00488 return ret;
00489 }
00490
00491
00492
00493
00494
00495 BOOL cli_send_keepalive(struct cli_state *cli)
00496 {
00497 if (cli->fd == -1) {
00498 DEBUG(3, ("cli_send_keepalive: fd == -1\n"));
00499 return False;
00500 }
00501 if (!send_keepalive(cli->fd)) {
00502 close(cli->fd);
00503 cli->fd = -1;
00504 DEBUG(0,("Error sending keepalive packet to client.\n"));
00505 return False;
00506 }
00507 return True;
00508 }
00509
00510
00511
00512
00513
00514 BOOL cli_echo(struct cli_state *cli, unsigned char *data, size_t length)
00515 {
00516 char *p;
00517
00518 SMB_ASSERT(length < 1024);
00519
00520 memset(cli->outbuf,'\0',smb_size);
00521 set_message(cli->outbuf,1,length,True);
00522 SCVAL(cli->outbuf,smb_com,SMBecho);
00523 SSVAL(cli->outbuf,smb_tid,65535);
00524 SSVAL(cli->outbuf,smb_vwv0,1);
00525 cli_setup_packet(cli);
00526 p = smb_buf(cli->outbuf);
00527 memcpy(p, data, length);
00528 p += length;
00529
00530 cli_setup_bcc(cli, p);
00531
00532 cli_send_smb(cli);
00533 if (!cli_receive_smb(cli)) {
00534 return False;
00535 }
00536
00537 if (cli_is_error(cli)) {
00538 return False;
00539 }
00540 return True;
00541 }