/// <summary> /// Sign the packet: Compute the signature and put it in the Signature field of header. /// </summary> /// <param name="clientNextSendSequenceNumber">sequence number for the next signed /// request being sent.</param> /// <param name="sessionKey">the session key.</param> /// <param name="challengeResponse">the challenge response.</param> /// <exception cref="System.ArgumentException"> /// the ClientNextSendSequenceNumber of Connection must be initialized to 2.</exception> public void Sign(ulong clientNextSendSequenceNumber, byte[] sessionKey, byte[] challengeResponse) { if (clientNextSendSequenceNumber < 2) { throw new ArgumentException( "the ClientNextSendSequenceNumber of Connection must be initialized to 2.", "clientNextSendSequenceNumber"); } // update the signature flag this.smbHeader.Flags2 |= SmbFlags2.SMB_FLAGS2_SMB_SECURITY_SIGNATURE; // if the session key is null, // just set the security signature in flag2, // then, return. if (sessionKey == null) { return; } // the 32-bit sequence number is copied in little-endian order (least-significant byte first) // into the first 4 bytes of the SecuritySignature field. this.smbHeader.SecurityFeatures = clientNextSendSequenceNumber; // get md5 hascode of session key and message body byte[] securitySignature = CifsMessageUtils.CreateSignature(this.ToBytes(true), sessionKey, challengeResponse); // update to security signature. this.smbHeader.SecurityFeatures = BitConverter.ToUInt64(securitySignature, 0); }
/// <summary> /// to decode stack packet from the received message bytes. /// the message bytes contains data without transport information /// </summary> /// <param name = "connection">the connection from which the message bytes are received. </param> /// <param name = "packetBytesWithoutTransport">the received message bytes to be decoded. </param> /// <param name = "consumedLength">the length of message bytes consumed by decoder. </param> /// <param name = "expectedLength">the length of message bytes the decoder expects to receive. </param> /// <returns>the stack packets decoded from the received message bytes. </returns> /// <exception cref="InvalidOperationException"> /// thrown when packet security signature is invalid. /// </exception> private SmbPacket[] DecodePacketFromBytesWithoutTransport( SmbServerConnection connection, byte[] packetBytesWithoutTransport, out int consumedLength, out int expectedLength) { expectedLength = 0; consumedLength = 0; SmbPacket[] packets = new SmbPacket[0]; int packetConsumedLength = 0; int packetExpectedLength = 0; // decode packets using cifs decorder. SmbPacket request = this.DecodeSmbRequestFromBytes( packetBytesWithoutTransport, out packetConsumedLength); // valid the signature if (request != null && request.SmbHeader.SecurityFeatures != 0 && connection.GssApi != null && connection.GssApi.SessionKey != null) { byte[] bytesToValid = ArrayUtility.SubArray(packetBytesWithoutTransport, 0); // the signature offset is 14. byte[] zeroSignature = new byte[sizeof(ulong)]; Array.Copy(zeroSignature, 0, bytesToValid, 14, zeroSignature.Length); // the signature offset is 14. zeroSignature = BitConverter.GetBytes((ulong)connection.ServerNextReceiveSequenceNumber); Array.Copy(zeroSignature, 0, bytesToValid, 14, zeroSignature.Length); byte[] signature = CifsMessageUtils.CreateSignature(bytesToValid, connection.GssApi.SessionKey); if (request.SmbHeader.SecurityFeatures != BitConverter.ToUInt64(signature, 0)) { throw new InvalidOperationException("packet security signature is invalid"); } } // Use the decoded packet to UpdateRoleContext if it is not null and ContextUpdate is enabled: if (request != null) { if (this.context.IsUpdateContext) { this.context.UpdateRoleContext(connection, request); } packets = new SmbPacket[] { request }; } // update the length after decode packet. consumedLength += packetConsumedLength; expectedLength += packetExpectedLength; return(packets); }