/**************************************************************************** check for existance of a dir ****************************************************************************/ static BOOL chkpath(char *path,BOOL report) { pstring path2; pstring inbuf,outbuf; char *p; pstrcpy(path2,path); trim_string(path2,NULL,"\\"); if (!*path2) *path2 = '\\'; bzero(outbuf,smb_size); set_message(outbuf,0,4 + strlen(path2),True); SCVAL(outbuf,smb_com,SMBchkpth); SSVAL(outbuf,smb_tid,cnum); cli_setup_pkt(outbuf); p = smb_buf(outbuf); *p++ = 4; pstrcpy(p,path2); #if 0 { /* this little bit of code can be used to extract NT error codes. Just feed a bunch of "cd foo" commands to smbclient then watch in netmon (tridge) */ static int code=0; SIVAL(outbuf, smb_rcls, code | 0xC0000000); SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | (1<<14)); code++; } #endif send_smb(Client,outbuf); client_receive_smb(Client,inbuf,CLIENT_TIMEOUT); if (report && CVAL(inbuf,smb_rcls) != 0) DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf))); return(CVAL(inbuf,smb_rcls) == 0); }
BOOL cli_receive_smb(struct cli_state *cli) { extern int smb_read_error; BOOL ret; /* fd == -1 causes segfaults -- Tom ([email protected]) */ if (cli->fd == -1) return False; again: ret = client_receive_smb(cli->fd,cli->inbuf,abs(cli->timeout)); if (ret) { /* it might be an oplock break request */ if (!(CVAL(cli->inbuf, smb_flg) & FLAG_REPLY) && CVAL(cli->inbuf,smb_com) == SMBlockingX && SVAL(cli->inbuf,smb_vwv6) == 0 && SVAL(cli->inbuf,smb_vwv7) == 0) { if (cli->oplock_handler) { int fnum = SVAL(cli->inbuf,smb_vwv2); unsigned char level = CVAL(cli->inbuf,smb_vwv3+1); if (!cli->oplock_handler(cli, fnum, level)) return False; } /* try to prevent loops */ SCVAL(cli->inbuf,smb_com,0xFF); goto again; } } /* If the server is not responding, note that now */ if (!ret) { cli->smb_rw_error = smb_read_error; close(cli->fd); cli->fd = -1; } return ret; }
bool cli_receive_smb(struct cli_state *cli) { ssize_t len; uint16_t mid; uint32_t seqnum; /* fd == -1 causes segfaults -- Tom ([email protected]) */ if (cli->fd == -1) return false; again: len = client_receive_smb(cli, 0); if (len > 0) { /* it might be an oplock break request */ if (!(CVAL(cli->inbuf, smb_flg) & FLAG_REPLY) && CVAL(cli->inbuf,smb_com) == SMBlockingX && SVAL(cli->inbuf,smb_vwv6) == 0 && SVAL(cli->inbuf,smb_vwv7) == 0) { if (cli->oplock_handler) { int fnum = SVAL(cli->inbuf,smb_vwv2); unsigned char level = CVAL(cli->inbuf,smb_vwv3+1); if (!NT_STATUS_IS_OK(cli->oplock_handler(cli, fnum, level))) { return false; } } /* try to prevent loops */ SCVAL(cli->inbuf,smb_com,0xFF); goto again; } } /* If the server is not responding, note that now */ if (len < 0) { DEBUG(0, ("Receiving SMB: Server stopped responding\n")); close(cli->fd); cli->fd = -1; return false; } mid = SVAL(cli->inbuf,smb_mid); seqnum = cli_state_get_seqnum(cli, mid); if (!cli_check_sign_mac(cli, cli->inbuf, seqnum+1)) { /* * If we get a signature failure in sessionsetup, then * the server sometimes just reflects the sent signature * back to us. Detect this and allow the upper layer to * retrieve the correct Windows error message. */ if (CVAL(cli->outbuf,smb_com) == SMBsesssetupX && (smb_len(cli->inbuf) > (smb_ss_field + 8 - 4)) && (SVAL(cli->inbuf,smb_flg2) & FLAGS2_SMB_SECURITY_SIGNATURES) && memcmp(&cli->outbuf[smb_ss_field],&cli->inbuf[smb_ss_field],8) == 0 && cli_is_error(cli)) { /* * Reflected signature on login error. * Set bad sig but don't close fd. */ cli->smb_rw_error = SMB_READ_BAD_SIG; return true; } DEBUG(0, ("SMB Signature verification failed on incoming packet!\n")); cli->smb_rw_error = SMB_READ_BAD_SIG; close(cli->fd); cli->fd = -1; return false; }; return true; }