/// <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);
        }
예제 #2
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);
        }