/// <exception cref="SharpCifs.Smb.SmbException"></exception> public virtual int Read(byte[] b, int off, int len) { if (len <= 0) { return(0); } long start = _fp; // ensure file is open if (_file.IsOpen() == false) { _file.Open(_openFlags, 0, SmbFile.AttrNormal, _options); } int r; int n; SmbComReadAndXResponse response = new SmbComReadAndXResponse(b, off); do { r = len > _readSize ? _readSize : len; _file.Send(new SmbComReadAndX(_file.Fid, _fp, r, null), response); if ((n = response.DataLength) <= 0) { return((int)((_fp - start) > 0L ? _fp - start : -1)); } _fp += n; len -= n; response.Off += n; }while (len > 0 && n == r); return((int)(_fp - start)); }
/// <exception cref="System.IO.IOException"></exception> protected internal override void DoRecv(Response response) { ServerMessageBlock resp = (ServerMessageBlock)response; resp.UseUnicode = UseUnicode; resp.ExtendedSecurity = (Capabilities & SmbConstants.CapExtendedSecurity) == SmbConstants.CapExtendedSecurity; lock (Buf) { Array.Copy(Sbuf, 0, Buf, 0, 4 + SmbConstants.HeaderLength); int size = Encdec.Dec_uint16be(Buf, 2) & 0xFFFF; if (size < (SmbConstants.HeaderLength + 1) || (4 + size) > RcvBufSize) { throw new IOException("Invalid payload size: " + size); } int errorCode = Encdec.Dec_uint32le(Buf, 9) & unchecked ((int)(0xFFFFFFFF)); if (resp.Command == ServerMessageBlock.SmbComReadAndx && (errorCode == 0 || errorCode == unchecked ((int)(0x80000005)))) { // overflow indicator normal for pipe SmbComReadAndXResponse r = (SmbComReadAndXResponse)resp; int off = SmbConstants.HeaderLength; Readn(In, Buf, 4 + off, 27); off += 27; resp.Decode(Buf, 4); int pad = r.DataOffset - off; if (r.ByteCount > 0 && pad > 0 && pad < 4) { Readn(In, Buf, 4 + off, pad); } if (r.DataLength > 0) { Readn(In, r.B, r.Off, r.DataLength); } } else { Readn(In, Buf, 4 + 32, size - 32); resp.Decode(Buf, 4); if (resp is SmbComTransactionResponse) { ((SmbComTransactionResponse)resp).Current(); } } if (Digest != null && resp.ErrorCode == 0) { Digest.Verify(Buf, 4, resp); } if (Log.Level >= 4) { Log.WriteLine(response); if (Log.Level >= 6) { Hexdump.ToHexdump(Log, Buf, 4, size); } } } }
/// <summary>Performs MAC signature verification.</summary> /// <remarks> /// Performs MAC signature verification. This calculates the signature /// of the SMB and compares it to the signature field on the SMB itself. /// </remarks> /// <param name="data">The data.</param> /// <param name="offset">The starting offset at which the SMB header begins.</param> /// <param name="length">The length of the SMB data starting at offset.</param> internal virtual bool Verify(byte[] data, int offset, ServerMessageBlock response ) { Update(_macSigningKey, 0, _macSigningKey.Length); int index = offset; Update(data, index, SmbConstants.SignatureOffset); index += SmbConstants.SignatureOffset; byte[] sequence = new byte[8]; ServerMessageBlock.WriteInt4(response.SignSeq, sequence, 0); Update(sequence, 0, sequence.Length); index += 8; if (response.Command == ServerMessageBlock.SmbComReadAndx) { SmbComReadAndXResponse raxr = (SmbComReadAndXResponse)response; int length = response.Length - raxr.DataLength; Update(data, index, length - SmbConstants.SignatureOffset - 8); Update(raxr.B, raxr.Off, raxr.DataLength); } else { Update(data, index, response.Length - SmbConstants.SignatureOffset - 8); } byte[] signature = Digest(); for (int i = 0; i < 8; i++) { if (signature[i] != data[offset + SmbConstants.SignatureOffset + i]) { if (Log.Level >= 2) { Log.WriteLine("signature verification failure"); Hexdump.ToHexdump(Log, signature, 0, 8); Hexdump.ToHexdump(Log, data, offset + SmbConstants.SignatureOffset, 8); } return(response.VerifyFailed = true); } } return(response.VerifyFailed = false); }
/// <summary> /// This method will copy the file or directory represented by this /// <tt>SmbFile</tt> and it's sub-contents to the location specified by the /// <tt>dest</tt> parameter. /// </summary> /// <remarks> /// This method will copy the file or directory represented by this /// <tt>SmbFile</tt> and it's sub-contents to the location specified by the /// <tt>dest</tt> parameter. This file and the destination file do not /// need to be on the same host. This operation does not copy extended /// file attibutes such as ACLs but it does copy regular attributes as /// well as create and last write times. This method is almost twice as /// efficient as manually copying as it employs an additional write /// thread to read and write data concurrently. /// <p/> /// It is not possible (nor meaningful) to copy entire workgroups or /// servers. /// </remarks> /// <param name="dest">the destination file or directory</param> /// <exception cref="SmbException">SmbException</exception> /// <exception cref="SharpCifs.Smb.SmbException"></exception> public virtual void CopyTo(SmbFile dest) { SmbComReadAndX req; SmbComReadAndXResponse resp; WriterThread w; int bsize; byte[][] b; if (_share == null || dest._share == null) { throw new SmbException("Invalid operation for workgroups or servers"); } req = new SmbComReadAndX(); resp = new SmbComReadAndXResponse(); Connect0(); dest.Connect0(); ResolveDfs(null); try { if (GetAddress().Equals(dest.GetAddress()) && _canon.RegionMatches(true, 0, dest._canon , 0, Math.Min(_canon.Length, dest._canon.Length))) { throw new SmbException("Source and destination paths overlap."); } } catch (UnknownHostException) { } w = new WriterThread(this); w.SetDaemon(true); w.Start(); SmbTransport t1 = Tree.Session.transport; SmbTransport t2 = dest.Tree.Session.transport; if (t1.SndBufSize < t2.SndBufSize) { t2.SndBufSize = t1.SndBufSize; } else { t1.SndBufSize = t2.SndBufSize; } bsize = Math.Min(t1.RcvBufSize - 70, t1.SndBufSize - 70); b = new[] { new byte[bsize], new byte[bsize] }; try { CopyTo0(dest, b, bsize, w, req, resp); } finally { w.Write(null, -1, null, 0); } }
/// <exception cref="SharpCifs.Smb.SmbException"></exception> internal virtual void CopyTo0(SmbFile dest, byte[][] b, int bsize, WriterThread w, SmbComReadAndX req, SmbComReadAndXResponse resp) { int i; if (_attrExpiration < Runtime.CurrentTimeMillis()) { _attributes = AttrReadonly | AttrDirectory; _createTime = 0L; _lastModified = 0L; _isExists = false; IInfo info = QueryPath(GetUncPath0(), Trans2QueryPathInformationResponse.SMB_QUERY_FILE_BASIC_INFO ); _attributes = info.GetAttributes(); _createTime = info.GetCreateTime(); _lastModified = info.GetLastWriteTime(); _isExists = true; _attrExpiration = Runtime.CurrentTimeMillis() + AttrExpirationPeriod; } if (IsDirectory()) { SmbFile[] files; SmbFile ndest; string path = dest.GetUncPath0(); if (path.Length > 1) { try { dest.Mkdir(); dest.SetPathInformation(_attributes, _createTime, _lastModified); } catch (SmbException se) { if (se.GetNtStatus() != NtStatus.NtStatusAccessDenied && se.GetNtStatus() != NtStatus .NtStatusObjectNameCollision) { throw; } } } files = ListFiles("*", AttrDirectory | AttrHidden | AttrSystem, null, null); try { for (i = 0; i < files.Length; i++) { ndest = new SmbFile(dest, files[i].GetName(), files[i].Type, files[i]._attributes, files[i]._createTime, files[i]._lastModified, files[i]._size); files[i].CopyTo0(ndest, b, bsize, w, req, resp); } } catch (UnknownHostException uhe) { throw new SmbException(Url.ToString(), uhe); } catch (UriFormatException mue) { throw new SmbException(Url.ToString(), mue); } } else { long off; try { Open(ORdonly, 0, AttrNormal, 0); try { dest.Open(OCreat | OWronly | OTrunc, SmbConstants.FileWriteData | SmbConstants.FileWriteAttributes, _attributes, 0); } catch (SmbAuthException sae) { if ((dest._attributes & AttrReadonly) != 0) { dest.SetPathInformation(dest._attributes & ~AttrReadonly, 0L, 0L); dest.Open(OCreat | OWronly | OTrunc, SmbConstants.FileWriteData | SmbConstants.FileWriteAttributes, _attributes, 0); } else { throw; } } i = 0; off = 0L; for (; ; ) { req.SetParam(Fid, off, bsize); resp.SetParam(b[i], 0); Send(req, resp); lock (w) { if (w.E != null) { throw w.E; } while (!w.Ready) { try { Runtime.Wait(w); } catch (Exception ie) { throw new SmbException(dest.Url.ToString(), ie); } } if (w.E != null) { throw w.E; } if (resp.DataLength <= 0) { break; } w.Write(b[i], resp.DataLength, dest, off); } i = i == 1 ? 0 : 1; off += resp.DataLength; } dest.Send(new Trans2SetFileInformation(dest.Fid, _attributes, _createTime, _lastModified ), new Trans2SetFileInformationResponse()); dest.Close(0L); } catch (SmbException se) { if (IgnoreCopyToException == false) { throw new SmbException("Failed to copy file from [" + ToString() + "] to [" + dest + "]", se); } if (Log.Level > 1) { Runtime.PrintStackTrace(se, Log); } } finally { Close(); } } }
/// <exception cref="System.IO.IOException"></exception> public virtual int ReadDirect(byte[] b, int off, int len) { if (len <= 0) { return(0); } long start = _fp; if (_tmp == null) { throw new IOException("Bad file descriptor"); } // ensure file is open File.Open(_openFlags, _access, SmbFile.AttrNormal, 0); if (File.Log.Level >= 4) { File.Log.WriteLine("read: fid=" + File.Fid + ",off=" + off + ",len=" + len); } SmbComReadAndXResponse response = new SmbComReadAndXResponse(b, off); if (File.Type == SmbFile.TypeNamedPipe) { response.ResponseTimeout = 0; } int r; int n; do { r = len > _readSize ? _readSize : len; if (File.Log.Level >= 4) { File.Log.WriteLine("read: len=" + len + ",r=" + r + ",fp=" + _fp); } try { SmbComReadAndX request = new SmbComReadAndX(File.Fid, _fp, r, null); if (File.Type == SmbFile.TypeNamedPipe) { request.MinCount = request.MaxCount = request.Remaining = 1024; } File.Send(request, response); } catch (SmbException se) { if (File.Type == SmbFile.TypeNamedPipe && se.GetNtStatus() == NtStatus.NtStatusPipeBroken) { return(-1); } throw SeToIoe(se); } if ((n = response.DataLength) <= 0) { return((int)((_fp - start) > 0L ? _fp - start : -1)); } _fp += n; len -= n; response.Off += n; }while (len > 0 && n == r); return((int)(_fp - start)); }
/// <exception cref="System.IO.IOException"></exception> public virtual int ReadDirect(byte[] b, int off, int len) { if (len <= 0) { return 0; } long start = _fp; if (_tmp == null) { throw new IOException("Bad file descriptor"); } // ensure file is open File.Open(_openFlags, _access, SmbFile.AttrNormal, 0); if (File.Log.Level >= 4) { File.Log.WriteLine("read: fid=" + File.Fid + ",off=" + off + ",len=" + len); } SmbComReadAndXResponse response = new SmbComReadAndXResponse(b, off); if (File.Type == SmbFile.TypeNamedPipe) { response.ResponseTimeout = 0; } int r; int n; do { r = len > _readSize ? _readSize : len; if (File.Log.Level >= 4) { File.Log.WriteLine("read: len=" + len + ",r=" + r + ",fp=" + _fp); } try { SmbComReadAndX request = new SmbComReadAndX(File.Fid, _fp, r, null); if (File.Type == SmbFile.TypeNamedPipe) { request.MinCount = request.MaxCount = request.Remaining = 1024; } File.Send(request, response); } catch (SmbException se) { if (File.Type == SmbFile.TypeNamedPipe && se.GetNtStatus() == NtStatus.NtStatusPipeBroken) { return -1; } throw SeToIoe(se); } if ((n = response.DataLength) <= 0) { return (int)((_fp - start) > 0L ? _fp - start : -1); } _fp += n; len -= n; response.Off += n; } while (len > 0 && n == r); return (int)(_fp - start); }
/// <exception cref="SharpCifs.Smb.SmbException"></exception> public virtual int Read(byte[] b, int off, int len) { if (len <= 0) { return 0; } long start = _fp; // ensure file is open if (_file.IsOpen() == false) { _file.Open(_openFlags, 0, SmbFile.AttrNormal, _options); } int r; int n; SmbComReadAndXResponse response = new SmbComReadAndXResponse(b, off); do { r = len > _readSize ? _readSize : len; _file.Send(new SmbComReadAndX(_file.Fid, _fp, r, null), response); if ((n = response.DataLength) <= 0) { return (int)((_fp - start) > 0L ? _fp - start : -1); } _fp += n; len -= n; response.Off += n; } while (len > 0 && n == r); return (int)(_fp - start); }