/// <exception cref="WinrtCifs.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); }
/// <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)); }