ntlm: avoid breaking anti-aliasing rules
PATCH 1/1 ntlm: avoid breaking anti-aliasing rules
From: Antonio Quartulli <[email protected]...>
The problem is visible when compiling with -O2:
ntlm.c: In function ‘ntlm_phase_3’:
ntlm.c:305:9: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
if ((*((long *)&buf2[0x14]) & 0x00800000) == 0x00800000)
The spec suggests to interpret those 4 bytes as a long, but this needs to be done carefully.
---
I have tried to make the statement more clear and "aliasing safe" at the same time. However, this is only compiled tested as I have no way to test the whole NTLM thing. Sorry :(
Cheers,
src/openvpn/ntlm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
src/openvpn/ntlm.c +2 -1
@@ -302,7 +302,8 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2,/* Add target information block to the blob */ /* Check for Target Information block */ -if ((*((long *)&buf2[0x14 ]) &0x00800000 ) ==0x00800000 ) +unsigned long *flags = (unsigned long *)(buf2 +0x14 ); +if ((*flags &htonl (0x00800000 )) ==htonl (0x00800000 )) { tib_len = buf2[0x28 ];/* Get Target Information block size */ if (tib_len >96 )
Signature · 1 line
2.14.0
Hi,
Quoted 29 lines · Antonio Quartulli
From: Antonio Quartulli <[email protected]...>
The problem is visible when compiling with -O2:
ntlm.c: In function ‘ntlm_phase_3’:
ntlm.c:305:9: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]if ((*((long *)&buf2[0x14]) & 0x00800000) == 0x00800000)The spec suggests to interpret those 4 bytes as a long, but this needs to be done carefully.
Signed-off-by Antonio Quartulli <[email protected]...>---
I have tried to make the statement more clear and "aliasing safe" at the same time. However, this is only compiled tested as I have no way to test the whole NTLM thing. Sorry :(
Cheers,
src/openvpn/ntlm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)src/openvpn/ntlm.c +0
-0
src/openvpn/ntlm.c ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, · line 309
Quoted 9 lines
src/openvpn/ntlm.c +2
-1@@ -302,7 +302,8 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2,/* Add target information block to the blob */ /* Check for Target Information block */ -if ((*((long *)&buf2[0x14 ]) &0x00800000 ) ==0x00800000 ) +unsigned long *flags = (unsigned long *)(buf2 +0x14 ); +if ((*flags &htonl (0x00800000 )) ==htonl (0x00800000 )) { tib_len = buf2[0x28 ];/* Get Target Information block size */ if (tib_len >96 )
I *think* this will break the functionality. Consider the following test code:
#include <arpa/inet.h>
#include <stdio.h>
int main(char *argv[], int argc)
{
unsigned char buf[4] = {0, 0, 0x80, 0};
if ((*((long *)&buf[0]) & 0x00800000) == 0x00800000)
printf("old: true\n");
else
printf("old: false\n");
unsigned long *flags = (unsigned long *)(buf);
if ((*flags & htonl(0x00800000)) == htonl(0x00800000))
printf("new: true\n");
else
printf("new: false\n");
return 0;
}On amd64, this prints:
old: true
new: false
I'd expect some 'ntohl' call in this code somewhere, but that assumes that the NTLM spec was designed somewhat sane and uses network byte order...
For now, I'd suggest to stick to just fixing the type-punned dereference and leave out any htonl/ntohl calls.
-Steffan
Quoted 67 lines · Steffan Karger
Hi,
Quoted 29 lines · Antonio Quartulli
From: Antonio Quartulli <[email protected]...>
The problem is visible when compiling with -O2:
ntlm.c: In function ‘ntlm_phase_3’:
ntlm.c:305:9: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]if ((*((long *)&buf2[0x14]) & 0x00800000) == 0x00800000)The spec suggests to interpret those 4 bytes as a long, but this needs to be done carefully.
Signed-off-by Antonio Quartulli <[email protected]...>---
I have tried to make the statement more clear and "aliasing safe" at the same time. However, this is only compiled tested as I have no way to test the whole NTLM thing. Sorry :(
Cheers,
src/openvpn/ntlm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)src/openvpn/ntlm.c +0
-0src/openvpn/ntlm.c ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, · line 309
Quoted 9 lines
src/openvpn/ntlm.c +2
-1@@ -302,7 +302,8 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2,/* Add target information block to the blob */ /* Check for Target Information block */ -if ((*((long *)&buf2[0x14 ]) &0x00800000 ) ==0x00800000 ) +unsigned long *flags = (unsigned long *)(buf2 +0x14 ); +if ((*flags &htonl (0x00800000 )) ==htonl (0x00800000 )) { tib_len = buf2[0x28 ];/* Get Target Information block size */ if (tib_len >96 )I *think* this will break the functionality. Consider the following test code:
#include <
arpa/inet.h>
#include <stdio.h>int
main(char *argv[], int argc){ unsigned char buf[4] = {0, 0, 0x80, 0}; if ((*((long *)&buf[0]) & 0x00800000) == 0x00800000) printf("old: true\n"); else printf("old: false\n"); unsigned long *flags = (unsigned long *)(buf); if ((*flags & htonl(0x00800000)) == htonl(0x00800000)) printf("new: true\n"); else printf("new: false\n"); return 0; }
Quoted 8 lines
On amd64, this prints:
old: true
new: falseI'd expect some 'ntohl' call in this code somewhere, but that assumes that the NTLM spec was designed somewhat sane and uses network byte order...
Right, that's also what I imagined, otherwise the code as it is wouldn't work on every platform (not sure it does on LE archs)
Quoted 3 lines
For now, I'd suggest to stick to just fixing the type-punned dereference and leave out any htonl/ntohl calls.
yeah, might be safer. Will send v2.
Cheers,
Signature · 1 line
Antonio Quartulli
PATCH v2 1/1 ntlm: avoid breaking anti-aliasing rules
From: Antonio Quartulli <[email protected]...>
The problem is visible when compiling with -O2:
ntlm.c: In function ‘ntlm_phase_3’:
ntlm.c:305:9: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
if ((*((long *)&buf2[0x14]) & 0x00800000) == 0x00800000)
The spec suggests to interpret those 4 bytes as a long, but this needs to be done carefully.
---
v2: remove htonl/ntohl conversion as there is none in the original code
src/openvpn/ntlm.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
src/openvpn/ntlm.c +13 -1
@@ -302,7 +302,19 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2,/* Add target information block to the blob */ /* Check for Target Information block */ -if ((*((long *)&buf2[0x14 ]) &0x00800000 ) ==0x00800000 ) +/* The NTLM spec instructs to interpret these 4 consecutive bytes as a +* 32bit long integer. However, no endianness is specified. +* The code here and that found in other NTLM implementations point +* towards the assumption that the byte order on the wire has to +* match the order on the sending and receiving hosts. Probably NTLM has +* been thought to be always running on x86_64/i386 machine thus +* implying Little-Endian everywhere. +* +* This said, in case of future changes, we should keep in mind that the +* byte order on the wire for the NTLM header is LE. +*/ +unsigned long *flags = (unsigned long *)(buf2 +0x14 ); +if ((*flags &0x00800000 ) ==0x00800000 ) { tib_len = buf2[0x28 ];/* Get Target Information block size */ if (tib_len >96 )
Signature · 1 line
2.14.0
PATCH v3 1/1 ntlm: avoid breaking anti-aliasing rules
From: Antonio Quartulli <[email protected]...>
The problem is visible when compiling with -O2:
ntlm.c: In function ‘ntlm_phase_3’:
ntlm.c:305:9: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
if ((*((long *)&buf2[0x14]) & 0x00800000) == 0x00800000)
The spec suggests to interpret those 4 bytes as a long, but this needs to be done carefully.
---
v2: remove htonl/ntohl conversion as there is none in the original code
v3: correct author's email
src/openvpn/ntlm.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
src/openvpn/ntlm.c +13 -1
@@ -302,7 +302,19 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2,/* Add target information block to the blob */ /* Check for Target Information block */ -if ((*((long *)&buf2[0x14 ]) &0x00800000 ) ==0x00800000 ) +/* The NTLM spec instructs to interpret these 4 consecutive bytes as a +* 32bit long integer. However, no endianness is specified. +* The code here and that found in other NTLM implementations point +* towards the assumption that the byte order on the wire has to +* match the order on the sending and receiving hosts. Probably NTLM has +* been thought to be always running on x86_64/i386 machine thus +* implying Little-Endian everywhere. +* +* This said, in case of future changes, we should keep in mind that the +* byte order on the wire for the NTLM header is LE. +*/ +unsigned long *flags = (unsigned long *)(buf2 +0x14 ); +if ((*flags &0x00800000 ) ==0x00800000 ) { tib_len = buf2[0x28 ];/* Get Target Information block size */ if (tib_len >96 )
Signature · 1 line
2.14.0
PATCH v4 1/1 ntlm: avoid breaking anti-aliasing rules
From: Antonio Quartulli <[email protected]...>
The problem is visible when compiling with -O2:
ntlm.c: In function ‘ntlm_phase_3’:
ntlm.c:305:9: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
if ((*((long *)&buf2[0x14]) & 0x00800000) == 0x00800000)
The spec suggests to interpret those 4 bytes as a long, but this needs to be done carefully.
---
v2: remove htonl/ntohl conversion as there is none in the original code
v3: correct author's email
v4: code used in v3 was not really alias-safe (thanks Steffan), fix it
src/openvpn/ntlm.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
src/openvpn/ntlm.c +15 -1
@@ -302,7 +302,21 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2,/* Add target information block to the blob */ /* Check for Target Information block */ -if ((*((long *)&buf2[0x14 ]) &0x00800000 ) ==0x00800000 ) +/* The NTLM spec instructs to interpret these 4 consecutive bytes as a +* 32bit long integer. However, no endianness is specified. +* The code here and that found in other NTLM implementations point +* towards the assumption that the byte order on the wire has to +* match the order on the sending and receiving hosts. Probably NTLM has +* been thought to be always running on x86_64/i386 machine thus +* implying Little-Endian everywhere. +* +* This said, in case of future changes, we should keep in mind that the +* byte order on the wire for the NTLM header is LE. +*/ +const size_t hoff =0x14 ; +unsigned long flags = buf2[hoff] | (buf2[hoff +1 ] <<8 ) | + (buf2[hoff +2 ] <<16 ) | (buf2[hoff +3 ] <<24 ); +if ((flags &0x00800000 ) ==0x00800000 ) { tib_len = buf2[0x28 ];/* Get Target Information block size */ if (tib_len >96 )
Signature · 1 line
2.14.0
Hi,
Quoted 40 lines · Antonio Quartulli
From: Antonio Quartulli <[email protected]...>
The problem is visible when compiling with -O2:
ntlm.c: In function ‘ntlm_phase_3’:
ntlm.c:305:9: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]if ((*((long *)&buf2[0x14]) & 0x00800000) == 0x00800000)The spec suggests to interpret those 4 bytes as a long, but this needs to be done carefully.
Signed-off-by Antonio Quartulli <[email protected]...>---
v2: remove htonl/ntohl conversion as there is none in the original code
v3: correct author's email
v4: code used in v3 was not really alias-safe (thanks Steffan), fix itsrc/openvpn/ntlm.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)src/openvpn/ntlm.c +8
-1@@ -302,7 +302,21 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2,/* Add target information block to the blob */ /* Check for Target Information block */ -if ((*((long *)&buf2[0x14 ]) &0x00800000 ) ==0x00800000 ) +/* The NTLM spec instructs to interpret these 4 consecutive bytes as a +* 32bit long integer. However, no endianness is specified. +* The code here and that found in other NTLM implementations point +* towards the assumption that the byte order on the wire has to +* match the order on the sending and receiving hosts. Probably NTLM has +* been thought to be always running on x86_64/i386 machine thus +* implying Little-Endian everywhere. +*
src/openvpn/ntlm.c ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, · line 322
Quoted 10 lines
src/openvpn/ntlm.c +7
-0+* This said, in case of future changes, we should keep in mind that the +* byte order on the wire for the NTLM header is LE. +*/ +const size_t hoff =0x14 ; +unsigned long flags = buf2[hoff] | (buf2[hoff +1 ] <<8 ) | + (buf2[hoff +2 ] <<16 ) | (buf2[hoff +3 ] <<24 ); +if ((flags &0x00800000 ) ==0x00800000 ) { tib_len = buf2[0x28 ];/* Get Target Information block size */ if (tib_len >96 )
This fixes the strict aliasing, makes the LE assumption explicit, and doesn't change the behaviour on LE machines. Good enough for me, ACK.
-Steffan
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
Your patch has been applied to the following branches
commit e84b6994b4d2b53bcebd5415a58de4cecd411a7b (master) commit 30e0778a57a8db3d57d144471a869647037a115b (release/2.4)
Author: Antonio Quartulli Date: Wed Aug 16 20:18:06 2017 +0800
ntlm: avoid breaking anti-aliasing rules
Signed-off-by: Antonio Quartulli <[email protected]...>
Acked-by: Steffan Karger <[email protected]...>
Message-Id: <[email protected]...>
URL: https://www.mail-archive.com/[email protected]/msg15268.html
Signed-off-by: David Sommerseth <[email protected]...>- --
kind regards,
David Sommerseth
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (GNU/Linux)
iQIcBAEBCgAGBQJZlGAXAAoJEIbPlEyWcf3yypsP/302vOTwTQ/HizJ83s9QJYPh 9xRA2/4fwV9iNyoj76SHskMnAtkyIZGUlWN/mMIw9ekZF0lydIQn6XK0ftvhuwEr XYiaLhUzB1wIDTXRhU8scSW+Xe0ZzbQ1EQMKuUW6muTcGCVlCWRIQkZ8FFfJsxFi PnXFpEL1UuNCwaFbLdPbdVSXb14vgQ9q7++PCNFIc2Z7dyocsoFzFJlHL1fmaGd/ 1G2cURTDtFXinIphFOzTFdsog6CyRciqnqTWm8k8COAE23ESqdaU/74CbqT+W9W4 YCmixcNttTImeeVMIepPoCrC/zEEyyRMVha6MPhZu6o2zYVjgkkgXek0hoJoY8ns z6cFbDXs9IyeSQmO1rCQnm5f79yA/UQ3GZNNtaWg6vkl+Jp6KDhUpW5Vxh9z+VXo PGqCWxyGqVw+ycAs2X0bddHVIAwg5pTjGXVXcthZTgg584RlqmOXKZZ5VP940CCh JZ1SZam64wQqjWlxFcVmZ9AVnOWN+FSOoKvK8I4h9xHbrQMT6DkBzwoDXRBwb1il TSTl0Rev6HKrB6HF290BgLcHzpUzaKcRcw/bIMXRUO6L1Lp/ciOeEyiBTBrGdQw7 tT4rjvbJg0/iL0lM9GkDmjI0tWNmVS0V4+HC1r0mdtOxq9j0AJTBKtkiEY6Y+XWv gsmqfSDNCqn6d/osOEKx
=8ER+
-----END PGP SIGNATURE-----