Subject: [tsvwg] 回复： Some unclear points about rfc4960 (SCTP).

From: "一念之后★だ" <[email-masked]>
Date: Sun, 22 Aug 2021 12:13:16 +0800

HI,
I am sorry for late reply. I combined the reply for several emails:&nbsp;

Which version of the Linux kernel are you using (what is the output of uname -a)?
 
Zhouming: I test ubuntu16.04 LTS and ubuntu20.04 LTS, they both have these problems.

&nbsp;uname -a

Linux ubuntu 4.4.0-142-generic #168-Ubuntu SMP Wed Jan 16 21:00:45 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
 
# uname -a
 
Linux ubuntu 5.11.0-27-generic #29~20.04.1-Ubuntu SMP Wed Aug 11 15:58:17 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

NCAT version:&nbsp; &nbsp;Ncat: Version 7.80 ( https://nmap.org/ncat )

---------------

I agree that the your attached .pcap file indicates that the implementation used has the bug you are describing. I used packetdrill (from https://github.com/nplab/packetdrill) with the &nbsp;attached script on a 5.11 kernel, and the attached script passes, which means that that stack does not have the problem. I'm also attaching the corresponding .pcapng file.

So it seems that this bug was fixed recently in Linux, or am I missing something?

 Zhouming:&nbsp; I checked the source code of 5.11 kernel, and find nothing fix about the problems we discussed. I guess maybe you missed something, I have no idea if packetdrill is suitable for this test.

---------------

&gt; This has already been clarified in draft-ietf-tsvwg-rfc4960-bis-13.
&gt;
&gt; It states now:
&gt; <t&gt;If the value of the Initiate Tag in a received INIT chunk is found to be 0,
&gt; the receiver MUST treat it as an error and silently discard the packet.</t&gt;
&gt;
&gt; For OS = 0 or MIS = 0, the INIT chunk MUST be dropped and an ABORT chunk
&gt; SHOULD be sent. So the next revision will contain:
&gt;
&gt; <t&gt;A receiver of an INIT chunk with the OS value set to 0 MUST discard the
&gt; packet and SHOULD send a packet in response containing an ABORT chunk and using
&gt; the Initiate Tag as the Verification Tag.
&gt; Any existing association MUST NOT be affected.</t&gt;
&gt;
&gt; <t&gt;A receiver of an INIT chunk with the MIS value set to 0 MUST discard the
&gt; packet and SHOULD send a packet in response containing an ABORT chunk and using
&gt; the Initiate Tag as the Verification Tag.
&gt; Any existing association MUST NOT be affected.</t&gt;
&gt;
&gt; I guess this makes the description for the INIT chunk crystal clear.

Zhouming:&nbsp; situation(2) is missing in&nbsp;draft-ietf-tsvwg-rfc4960-bis-13 or it no need to be&nbsp;clarified&nbsp;&nbsp;??&nbsp; &nbsp; I have test this, an init msg with&nbsp;mandatory parameters not fully carried can also&nbsp;trigger an Abort msg to release the association.

---

As can be seen from the above description, when an init message or init ACK message is received,

(1)If the init tag in the message is 0, the association must be released

(2)If the mandatory parameters in the message are not fully carried, the association must be released

(3)When the OS value or MIS value in the message is 0, it is strongly recommended to release this association

&gt;&gt; Unfortunately, the SCTP implementation of Linux will be affected by the attacks described above, such as the open source lksctp.
&gt; Have you reported that issue? If not, I can let them know.

Zhouming:&nbsp; I still do not report this issue to them, I think I need disscuss it with you first, so you can let them know about it.

-------------

&gt; Please let me know how to write your name in ASCII to give you credit.

Zhouming:&nbsp; Thanks very much,&nbsp;&nbsp;it's a great honor，my English name is Zhouming.

------------------&nbsp;原始邮件&nbsp;------------------
发件人:                                                                                                                        "Michael Tuexen"                                                                                    <[email-masked]&gt;;
发送时间:&nbsp;2021年8月21日(星期六) 上午6:03
收件人:&nbsp;"一念之后★だ"<[email-masked]&gt;;
抄送:&nbsp;"tsvwg"<[email-masked]&gt;;"draft-ietf-tsvwg-2960bis"<[email-masked]&gt;;
主题:&nbsp;Re: [tsvwg] Some unclear points about rfc4960 (SCTP).

&gt; On 18. Aug 2021, at 18:46, Michael Tuexen <[email-masked]&gt; wrote:
&gt; 
&gt;&gt; On 17. Aug 2021, at 18:56, 一念之后★だ <[email-masked]&gt; wrote:
&gt;&gt; 
&gt;&gt; Dear IETF experts，
&gt;&gt; 
&gt;&gt; I read rfc4960 (SCTP) and felt that there were some unclear descriptions in the document. I hope to get your reply, so I wrote this email to you. And I think it's better to describe these more clearly in the subsequent version of the RFC.
&gt;&gt; The following description describes some scenarios requiring abort Association in rfc4960:
&gt;&gt; Page25
&gt;&gt; 
&gt;&gt; 
&gt;&gt; <[email-masked]&gt;
&gt;&gt; 
&gt;&gt; Page26
&gt;&gt; <[email-masked]&gt;
&gt;&gt; 
&gt;&gt; Page30
&gt;&gt; <[email-masked]&gt;
&gt;&gt; 
&gt;&gt; Page31
&gt;&gt; <[email-masked]&gt;
&gt;&gt; 
&gt;&gt; Page56
&gt;&gt; <[email-masked]&gt;
&gt;&gt; 
&gt;&gt; As can be seen from the above description, when an init message or init ACK message is received,
&gt;&gt; (1)If the init tag in the message is 0, the association must be released
&gt;&gt; (2)If the mandatory parameters in the message are not fully carried, the association must be released
&gt;&gt; (3)When the OS value or MIS value in the message is 0, it is strongly recommended to release this association
&gt; You are correct, using an initiate tag of 0 or limit the number of streams to 0 is not allowed.
&gt; 
&gt; Please note the in the case of an initiate tag of 0 in an INIT chunk, you can't send an ABORT
&gt; since you have no tag different from 0 you could use as the verification tag.
&gt; This has already been clarified in draft-ietf-tsvwg-rfc4960-bis-13.
&gt; 
&gt; It states now:
&gt; <t&gt;If the value of the Initiate Tag in a received INIT chunk is found to be 0,
&gt; the receiver MUST treat it as an error and silently discard the packet.</t&gt;
&gt; 
&gt; For OS = 0 or MIS = 0, the INIT chunk MUST be dropped and an ABORT chunk
&gt; SHOULD be sent. So the next revision will contain:
&gt; 
&gt; <t&gt;A receiver of an INIT chunk with the OS value set to 0 MUST discard the
&gt; packet and SHOULD send a packet in response containing an ABORT chunk and using
&gt; the Initiate Tag as the Verification Tag.
&gt; Any existing association MUST NOT be affected.</t&gt;
&gt; 
&gt; <t&gt;A receiver of an INIT chunk with the MIS value set to 0 MUST discard the
&gt; packet and SHOULD send a packet in response containing an ABORT chunk and using
&gt; the Initiate Tag as the Verification Tag.
&gt; Any existing association MUST NOT be affected.</t&gt;
&gt; 
&gt; I guess this makes the description for the INIT chunk crystal clear.
&gt; 
&gt; The situation for the INIT-ACK is different. The INIT-ACK is only processed, if
&gt; the verification tag in the common header was correct. In this case it is OK
&gt; to destroy the association. A potential attacker has to guess the 32-bit
&gt; verification tag and if the attacker can do this, the attacker can send a
&gt; packet containing an ABORT chunk.
&gt; However, the consistency of the text can be improved.
Here are the suggested changes to improve the consistency of the handling
of illegal parameters in the INIT ACK chunk:

For the Initiate Tag:
<t&gt;If an endpoint in the COOKIE-WAIT state receives an INIT ACK chunk with the
Initiate Tag set to 0, it MUST destroy the TCB and SHOULD send an ABORT chunk
with the T bit set.
If such an INIT-ACK chunk is received in any state other than CLOSED or
COOKIE-WAIT, it SHOULD be discarded silently
(see <xref target='sec_unexpected_init_ack'/&gt;).</t&gt;

For OS:
<t&gt;If an endpoint in the COOKIE-WAIT state receives an INIT ACK chunk with the
OS value set to 0, it MUST destroy the TCB and SHOULD send an ABORT chunk.
If such an INIT-ACK chunk is received in any state other than CLOSED or
COOKIE-WAIT, it SHOULD be discarded silently
(see <xref target='sec_unexpected_init_ack'/&gt;).</t&gt;

For MIS:
<t&gt;If an endpoint in the COOKIE-WAIT state receives an INIT ACK chunk with the
MIS value set to 0, it MUST destroy the TCB and SHOULD send an ABORT chunk.
If such an INIT-ACK chunk is received in any state other than CLOSED or
COOKIE-WAIT, it SHOULD be discarded silently
(see <xref target='sec_unexpected_init_ack'/&gt;).</t&gt;

Best regards
Michael
&gt;&gt; 
&gt;&gt; The following description also shows that there can only be one SCTP association between two SCTP endpoints at any time:
&gt;&gt; <[email-masked]&gt;
&gt;&gt; 
&gt;&gt; 
&gt;&gt; Because init messages can be forged arbitrarily, take the scenario where the initial tag in init message is 0 as an example.
&gt;&gt; In this scenario, a malicious attacker can destroy other associations at a very low cost:
&gt;&gt; <[email-masked]&gt;
&gt;&gt; 
&gt;&gt; For the other two scenarios, i.e. init message with missing mandatory parameters or init message with OS value / MIS value of 0, the effect may be similar.
&gt;&gt; I think from the original intention of the protocol design, these error scenarios should be handled according to the following. However, the RFC does not specify how to deal with the established association endpoint when receiving this wrong init (or init ACK) message, and whether the corresponding association should still be removed.
&gt; I agree. I think the suggested changes above make this crystal clear.
&gt;&gt; <[email-masked]&gt;
&gt;&gt; 
&gt;&gt; Unfortunately, the SCTP implementation of Linux will be affected by the attacks described above, such as the open source lksctp.
&gt; Have you reported that issue? If not, I can let them know.
&gt;&gt; I hope to receive your reply to clarify the above unclear areas.
&gt;&gt; Thank you very much.
&gt; Thank you very mich for reporting the issue.
&gt;&gt; 
&gt;&gt; Yours faithfully!
&gt;&gt; Zhouming.
&gt; Please let me know how to write your name in ASCII to give you credit.
&gt; 
&gt; Best regards
&gt; Michael
&gt;

---

From: Michael Tuexen <[email-masked]>
Date: Tue, 24 Aug 2021 13:50:53 +0200

> On 22. Aug 2021, at 06:13, 一念之后★だ <[email-masked]> wrote:
> 
> HI,
> I am sorry for late reply. I combined the reply for several emails: 
> 
>  uname -a
> NCAT version:   Ncat: Version 7.80 ( https://nmap.org/ncat )
> 
> 
> 
> ---------------
> 
> I agree that the your attached .pcap file indicates that the implementation used has the bug you are describing. I used packetdrill (from https://github.com/nplab/packetdrill) with the  attached script on a 5.11 kernel, and the attached script passes, which means that that stack does not have the problem. I'm also attaching the corresponding .pcapng file.
> 
> Zhouming:  I checked the source code of 5.11 kernel, and find nothing fix about the problems we discussed. I guess maybe you missed something, I have no idea if packetdrill is suitable for this test.
OK, I spend some more time and now figured out what is going on:

* The linux kernel implementation handles the reception of an INIT chunk with 
  (1) initiate tag = 0
  (2) os = 0
  (3) mis = 0
  (4) partial chunk (chunk length >= 20, but but not enough bytes in the packet)
  (5) missing mandatory parameters (chunk length < 20, number of bytes in the packet as described by chunk length)
  in state ESTABLSHED in the same way:
  (a) It does not affect the state of the association at the endpoint receiving the INIT chunk
  (b) It sends out a packet with an ABORT chunk. The verification tag of this packet it the verification
      tag expected by the peer.

* packetdrill was not verifying the verification tag used in the outgoing packets containing the ABORT
  chunks. This is fixed now in packetdrill.

So I can confirm that Linux has a bug. It should not send a packet containing an ABORT chunk when condition (1)
is true. When sending a packet containing an ABORT chunk because it received an INIT chunk with (2), (3), (4), or
(5), it should use the initiate tag of the received INIT chunk. If that is not possible, no ABORT should be sent.

I guess we agree now on the current state of the Linux implementation. Sorry for not seeing this initially,
since I was only focussing on the endpoint receiving the INIT chunk and was happy that it stays in ESTABLISHED.
I'm also attaching a .pcapng file showing (4) and (5).
> 
> 
> 
> ---------------
> 
> > This has already been clarified in draft-ietf-tsvwg-rfc4960-bis-13.
> >
> > It states now:
> > <t>If the value of the Initiate Tag in a received INIT chunk is found to be 0,
> > the receiver MUST treat it as an error and silently discard the packet.</t>
> >
> > For OS = 0 or MIS = 0, the INIT chunk MUST be dropped and an ABORT chunk
> > SHOULD be sent. So the next revision will contain:
> >
> > <t>A receiver of an INIT chunk with the OS value set to 0 MUST discard the
> > packet and SHOULD send a packet in response containing an ABORT chunk and using
> > the Initiate Tag as the Verification Tag.
> > Any existing association MUST NOT be affected.</t>
> >
> > <t>A receiver of an INIT chunk with the MIS value set to 0 MUST discard the
> > packet and SHOULD send a packet in response containing an ABORT chunk and using
> > the Initiate Tag as the Verification Tag.
> > Any existing association MUST NOT be affected.</t>
> >
> > I guess this makes the description for the INIT chunk crystal clear.
> 
> Zhouming:  situation(2) is missing in draft-ietf-tsvwg-rfc4960-bis-13 or it no need to be clarified  ??    I have test this, an init msg with mandatory parameters not fully carried can also trigger an Abort msg to release the association.
I agree that there is a problem in the Linux implementation.

I changed the text in Section 5.1 from

OLD:
The Verification Tag field in the common header of the outbound SCTP packet containing the
ABORT chunk MUST be set to the Initiate Tag value of the peer.

NEW:
The Verification Tag field in the common header of the outbound SCTP packet
containing the ABORT chunk MUST be set to the Initiate Tag value of the
received INIT or INIT ACK chunk this ABORT chunk is responding to.</t>

I guess the makes things clearer.
> >> Unfortunately, the SCTP implementation of Linux will be affected by the attacks described above, such as the open source lksctp.
> > Have you reported that issue? If not, I can let them know.
> 
> Zhouming:  I still do not report this issue to them, I think I need disscuss it with you first, so you can let them know about it.
OK. I think we agree now on the state? Please CC me on the mail you send to lksctp mailing
list, I can provide a packetdrill script.
> 
> -------------
> 
> > Please let me know how to write your name in ASCII to give you credit.
> 
> Zhouming:  Thanks very much,  it's a great honor，my English name is Zhouming.
OK, thank you. I have added your name to the acknowledgement section of RFC 4960bis.

Best regards
Michael

> 
> 
> 
> ------------------ 原始邮件 ------------------
> 发件人: "Michael Tuexen" <[email-masked]>;
> 发送时间: 2021年8月21日(星期六) 上午6:03
> 收件人: "一念之后★だ"<[email-masked]>;
> 抄送: "tsvwg"<[email-masked]>;"draft-ietf-tsvwg-2960bis"<[email-masked]>;
> 主题: Re: [tsvwg] Some unclear points about rfc4960 (SCTP).
> 
> > On 18. Aug 2021, at 18:46, Michael Tuexen <[email-masked]> wrote:
> > 
> >> On 17. Aug 2021, at 18:56, 一念之后★だ <[email-masked]> wrote:
> >> 
> >> Dear IETF experts，
> >> 
> >> I read rfc4960 (SCTP) and felt that there were some unclear descriptions in the document. I hope to get your reply, so I wrote this email to you. And I think it's better to describe these more clearly in the subsequent version of the RFC.
> >> The following description describes some scenarios requiring abort Association in rfc4960:
> >> Page25
> >> 
> >> 
> >> 
> >> Page26
> >> 
> >> Page30
> >> 
> >> Page31
> >> 
> >> Page56
> >> 
> > You are correct, using an initiate tag of 0 or limit the number of streams to 0 is not allowed.
> > 
> > Please note the in the case of an initiate tag of 0 in an INIT chunk, you can't send an ABORT
> > since you have no tag different from 0 you could use as the verification tag.
> > This has already been clarified in draft-ietf-tsvwg-rfc4960-bis-13.
> > 
> > It states now:
> > <t>If the value of the Initiate Tag in a received INIT chunk is found to be 0,
> > the receiver MUST treat it as an error and silently discard the packet.</t>
> > 
> > For OS = 0 or MIS = 0, the INIT chunk MUST be dropped and an ABORT chunk
> > SHOULD be sent. So the next revision will contain:
> > 
> > <t>A receiver of an INIT chunk with the OS value set to 0 MUST discard the
> > packet and SHOULD send a packet in response containing an ABORT chunk and using
> > the Initiate Tag as the Verification Tag.
> > Any existing association MUST NOT be affected.</t>
> > 
> > <t>A receiver of an INIT chunk with the MIS value set to 0 MUST discard the
> > packet and SHOULD send a packet in response containing an ABORT chunk and using
> > the Initiate Tag as the Verification Tag.
> > Any existing association MUST NOT be affected.</t>
> > 
> > I guess this makes the description for the INIT chunk crystal clear.
> > 
> > The situation for the INIT-ACK is different. The INIT-ACK is only processed, if
> > the verification tag in the common header was correct. In this case it is OK
> > to destroy the association. A potential attacker has to guess the 32-bit
> > verification tag and if the attacker can do this, the attacker can send a
> > packet containing an ABORT chunk.
> > However, the consistency of the text can be improved.
> <t>If an endpoint in the COOKIE-WAIT state receives an INIT ACK chunk with the
> (see <xref target='sec_unexpected_init_ack'/>).</t>
> 
> 
> For OS:
> <t>If an endpoint in the COOKIE-WAIT state receives an INIT ACK chunk with the
> (see <xref target='sec_unexpected_init_ack'/>).</t>
> 
> For MIS:
> <t>If an endpoint in the COOKIE-WAIT state receives an INIT ACK chunk with the
> (see <xref target='sec_unexpected_init_ack'/>).</t>
> 
> Best regards
> Michael
> >> 
> >> The following description also shows that there can only be one SCTP association between two SCTP endpoints at any time:
> >> 
> >> 
> >> Because init messages can be forged arbitrarily, take the scenario where the initial tag in init message is 0 as an example.
> >> In this scenario, a malicious attacker can destroy other associations at a very low cost:
> >> 
> >> For the other two scenarios, i.e. init message with missing mandatory parameters or init message with OS value / MIS value of 0, the effect may be similar.
> >> I think from the original intention of the protocol design, these error scenarios should be handled according to the following. However, the RFC does not specify how to deal with the established association endpoint when receiving this wrong init (or init ACK) message, and whether the corresponding association should still be removed.
> > I agree. I think the suggested changes above make this crystal clear.
> >> 
> >> Unfortunately, the SCTP implementation of Linux will be affected by the attacks described above, such as the open source lksctp.
> > Have you reported that issue? If not, I can let them know.
> >> I hope to receive your reply to clarify the above unclear areas.
> >> Thank you very much.
> > Thank you very mich for reporting the issue.
> >> 
> >> Yours faithfully!
> >> Zhouming.
> > Please let me know how to write your name in ASCII to give you credit.
> > 
> > Best regards
> > Michael
> > 
>

---

From: Marcelo Ricardo Leitner <[email-masked]>
Date: Tue, 24 Aug 2021 11:36:54 -0300

Hi,

Thanks Michael for the ping.

I tried to catch up with the thread here but I'm very confused. Can
somebody do a write up on the issue please? :-)

Thanks,
Marcelo

On Tue, Aug 24, 2021 at 01:50:53PM +0200, Michael Tuexen wrote:
> So I can confirm that Linux has a bug. It should not send a packet
> containing an ABORT chunk when condition (1) is true. When sending a
> packet containing an ABORT chunk because it received an INIT chunk
> with (2), (3), (4), or (5), it should use the initiate tag of the
> received INIT chunk. If that is not possible, no ABORT should be
> sent.
> 
> I guess we agree now on the current state of the Linux
> implementation. Sorry for not seeing this initially, since I was
> only focussing on the endpoint receiving the INIT chunk and was
> happy that it stays in ESTABLISHED.  I'm also attaching a .pcapng
> file showing (4) and (5).
> > 
> > 
> > 
> > ---------------
> >

---

From: Michael Tuexen <[email-masked]>
Date: Wed, 25 Aug 2021 01:19:06 +0200

> On 24. Aug 2021, at 16:36, Marcelo Ricardo Leitner <[email-masked]> wrote:
> 
> Hi,
> 
Hi Marcelo,

Zhouming reported the issues in the Linux SCTP stack based on experiments
with the handling of INIT chunks. It was assumed that the handling of
INIT ACK has similar problems, but as far as my testing shows, there
is a different issue with INIT ACK chunks. 

(A) Problems with invalid INIT chunks

When an packet containing an invalid INIT chunk is received and there is an
existing SCTP association with the same IP-addresses and port
numbers, the SCTP stacks sends back a packet containing an ABORT chunk.
The state of the end points does not change. All of this is OK.

The conditions of being invalid are:
 (1) initiate tag = 0
 (2) os = 0
 (3) mis = 0
 (4) partial chunk (chunk length >= 20, but but not enough bytes in the packet)
 (5) missing mandatory parameters (chunk length < 20, number of bytes in the packet as described by chunk length)

The problem is that the Linux stack uses when sending the packet with the
ABORT chunk the verification tag of the existing SCTP association. This will
result in the peer accepting the ABORT chunk and removing the SCTP association.

The correct behaviour is to use the initiate tag of the received INIT chunk
as the verification tag of the packet containing the ABORT chunk. You would
not send this packet, if the initiate tag is zero, since the only valid SCTP
packets with a zero verification tag a packets containing an INIT chunk.
It also might not make sense to send an ABORT chunk if the initiate tag
does actually match the initiate tag of the original INIT chunk (which was
correct).

I'm attaching a packetdrill script (linux_passive.pkt) for testing the
Linux stack (it will not pass right now) and a .pcapng file (linux_passive.pcapng)
which shows the current behaviour.
Please use a current version of packetdrill from https://github.com/nplab/packetdrill

(B) Problems with invalid INIT-ACK chunks

When an packet containing an invalid INIT ACK chunk is received and there is an
existing SCTP association with the same IP-addresses and port
numbers, the SCTP stacks just drops it in case of (1), (2), (3), or (5).
This is correct.
However, if the INIT-ACK chunk is incorrect due to (4), the Linux stack
sends back a packet containing an ABORT chunk and removes the association.
What is important here is that the packet containing the INIT-ACK is processed
even if the verification tag is wrong.
I'm attaching a packetdrill script (linux_active.pkt) for testing the
Linux stack (it will not pass right now).

(A) and (B) are critical, since they allow a blind attacker to kill an
existing association if the attacker knows the IP-addresses and port numbers
being used and the attacker can send packets with spoofed IP addresses.
The attacker does not need to know the verification tag.

Does that make things clearer?

Best regards
Michael

---

From: Marcelo Ricardo Leitner <[email-masked]>
Date: Thu, 26 Aug 2021 22:53:47 -0300

> is a different issue with INIT ACK chunks. 
...
> Does that make things clearer?

It does. Thanks Michael. I could reproduce the issues here as well.

On a quick debug now (nearly 11pm here, be warned ;) ), it seems (B)
is a more generic issue. The abort is being generated here:

packetdrill  4099 [014]   268.865045: probe:sctp_sf_violation_chunklen: (ffffffffc05edd1e)
        ffffffffc05edd1f sctp_sf_discard_chunk+0x4f (/lib/modules/5.14.0-rc6+/kernel/net/sctp/sctp.>
        ffffffffc05f0d94 sctp_do_sm+0x84 (/lib/modules/5.14.0-rc6+/kernel/net/sctp/sctp.ko)
        ffffffffc05f5deb sctp_assoc_bh_rcv+0xfb (/lib/modules/5.14.0-rc6+/kernel/net/sctp/sctp.ko)

By the check in [1]. The function sctp_sf_discard_chunk() is a generic
handler, and other chunk types (not just INIT_ACK) should be able to
trigger it as it is used in many other places [2] (search for it on
the defines. Line 95 is just an example). Whooops.

1.https://elixir.bootlin.com/linux/latest/source/net/sctp/sm_statefuns.c#L4545
2.https://elixir.bootlin.com/linux/latest/source/net/sctp/sm_statetable.c#L95

Best regards,
Marcelo