@@ -52,6 +52,8 @@ sealed class AuthBlock
5252
5353 public bool WireCryptInitialized { get ; private set ; }
5454
55+ private const int STACKALLOC_LIMIT = 512 ;
56+
5557 public AuthBlock ( GdsConnection connection , string user , string password , WireCryptOption wireCrypt )
5658 {
5759 _srp256 = new Srp256Client ( ) ;
@@ -64,64 +66,164 @@ public AuthBlock(GdsConnection connection, string user, string password, WireCry
6466 WireCrypt = wireCrypt ;
6567 }
6668
67- public byte [ ] UserIdentificationData ( )
69+ public byte [ ] UserIdentificationData ( )
6870 {
6971 using ( var result = new MemoryStream ( 256 ) )
7072 {
71- var userString = Environment . GetEnvironmentVariable ( "USERNAME" ) ?? Environment . GetEnvironmentVariable ( "USER" ) ?? string . Empty ;
72- var user = Encoding . UTF8 . GetBytes ( userString ) ;
73- result . WriteByte ( IscCodes . CNCT_user ) ;
74- result . WriteByte ( ( byte ) user . Length ) ;
75- result . Write ( user , 0 , user . Length ) ;
73+ {
74+ var userString = Environment . GetEnvironmentVariable ( "USERNAME" ) ?? Environment . GetEnvironmentVariable ( "USER" ) ?? string . Empty ;
75+ var slen = Encoding . UTF8 . GetByteCount ( userString ) ;
76+ byte [ ] rented = null ;
77+ Span < byte > user = slen > STACKALLOC_LIMIT
78+ ? ( rented = System . Buffers . ArrayPool < byte > . Shared . Rent ( slen ) ) . AsSpan ( 0 , slen )
79+ : stackalloc byte [ slen ] ;
80+ int real_len = Encoding . UTF8 . GetBytes ( userString , user ) ;
81+ result . WriteByte ( IscCodes . CNCT_user ) ;
82+ result . WriteByte ( ( byte ) real_len ) ;
83+ result . Write ( user ) ;
84+ if ( rented != null )
85+ {
86+ System . Buffers . ArrayPool < byte > . Shared . Return ( rented , clearArray : true ) ;
87+ }
88+ }
7689
77- var host = Encoding . UTF8 . GetBytes ( Dns . GetHostName ( ) ) ;
78- result . WriteByte ( IscCodes . CNCT_host ) ;
79- result . WriteByte ( ( byte ) host . Length ) ;
80- result . Write ( host , 0 , host . Length ) ;
90+ {
91+ var hostName = Dns . GetHostName ( ) ;
92+ var slen = Encoding . UTF8 . GetByteCount ( hostName ) ;
93+ byte [ ] rented = null ;
94+ Span < byte > host = slen > STACKALLOC_LIMIT
95+ ? ( rented = System . Buffers . ArrayPool < byte > . Shared . Rent ( slen ) ) . AsSpan ( 0 , slen )
96+ : stackalloc byte [ slen ] ;
97+ int real_len = Encoding . UTF8 . GetBytes ( hostName , host ) ;
98+ result . WriteByte ( IscCodes . CNCT_host ) ;
99+ result . WriteByte ( ( byte ) real_len ) ;
100+ result . Write ( host ) ;
101+ if ( rented != null )
102+ {
103+ System . Buffers . ArrayPool < byte > . Shared . Return ( rented , clearArray : true ) ;
104+ }
105+ }
81106
82107 result . WriteByte ( IscCodes . CNCT_user_verification ) ;
83108 result . WriteByte ( 0 ) ;
84109
85110 if ( ! string . IsNullOrEmpty ( User ) )
86111 {
87- var login = Encoding . UTF8 . GetBytes ( User ) ;
88- result . WriteByte ( IscCodes . CNCT_login ) ;
89- result . WriteByte ( ( byte ) login . Length ) ;
90- result . Write ( login , 0 , login . Length ) ;
91-
92- var pluginNameBytes = Encoding . UTF8 . GetBytes ( _srp256 . Name ) ;
93- result . WriteByte ( IscCodes . CNCT_plugin_name ) ;
94- result . WriteByte ( ( byte ) pluginNameBytes . Length ) ;
95- result . Write ( pluginNameBytes , 0 , pluginNameBytes . Length ) ;
96- var specificData = Encoding . UTF8 . GetBytes ( _srp256 . PublicKeyHex ) ;
97- WriteMultiPartHelper ( result , IscCodes . CNCT_specific_data , specificData ) ;
98-
99- var plugins = string . Join ( "," , new [ ] { _srp256 . Name , _srp . Name } ) ;
100- var pluginsBytes = Encoding . UTF8 . GetBytes ( plugins ) ;
101- result . WriteByte ( IscCodes . CNCT_plugin_list ) ;
102- result . WriteByte ( ( byte ) pluginsBytes . Length ) ;
103- result . Write ( pluginsBytes , 0 , pluginsBytes . Length ) ;
112+ {
113+ var slen = Encoding . UTF8 . GetByteCount ( User ) ;
114+ byte [ ] rented = null ;
115+ Span < byte > bytes = slen > STACKALLOC_LIMIT
116+ ? ( rented = System . Buffers . ArrayPool < byte > . Shared . Rent ( slen ) ) . AsSpan ( 0 , slen )
117+ : stackalloc byte [ slen ] ;
118+ int real_len = Encoding . UTF8 . GetBytes ( User , bytes ) ;
119+ result . WriteByte ( IscCodes . CNCT_login ) ;
120+ result . WriteByte ( ( byte ) real_len ) ;
121+ result . Write ( bytes ) ;
122+ if ( rented != null )
123+ {
124+ System . Buffers . ArrayPool < byte > . Shared . Return ( rented , clearArray : true ) ;
125+ }
126+ }
127+ {
128+ var slen = Encoding . UTF8 . GetByteCount ( _srp256 . Name ) ;
129+ byte [ ] rented = null ;
130+ Span < byte > bytes = slen > STACKALLOC_LIMIT
131+ ? ( rented = System . Buffers . ArrayPool < byte > . Shared . Rent ( slen ) ) . AsSpan ( 0 , slen )
132+ : stackalloc byte [ slen ] ;
133+ int real_len = Encoding . UTF8 . GetBytes ( _srp256 . Name , bytes ) ;
134+ result . WriteByte ( IscCodes . CNCT_plugin_name ) ;
135+ result . WriteByte ( ( byte ) real_len ) ;
136+ result . Write ( bytes [ ..real_len ] ) ;
137+ if ( rented != null )
138+ {
139+ System . Buffers . ArrayPool < byte > . Shared . Return ( rented , clearArray : true ) ;
140+ }
141+ }
142+ {
143+ var slen = Encoding . UTF8 . GetByteCount ( _srp256 . PublicKeyHex ) ;
144+ byte [ ] rented = null ;
145+ Span < byte > specificData = slen > STACKALLOC_LIMIT
146+ ? ( rented = System . Buffers . ArrayPool < byte > . Shared . Rent ( slen ) ) . AsSpan ( 0 , slen )
147+ : stackalloc byte [ slen ] ;
148+ Encoding . UTF8 . GetBytes ( _srp256 . PublicKeyHex . AsSpan ( ) , specificData ) ;
149+ WriteMultiPartHelper ( result , IscCodes . CNCT_specific_data , specificData ) ;
150+ if ( rented != null )
151+ {
152+ System . Buffers . ArrayPool < byte > . Shared . Return ( rented , clearArray : true ) ;
153+ }
154+ }
155+ {
156+ var slen1 = Encoding . UTF8 . GetByteCount ( _srp256 . Name ) ;
157+ byte [ ] rented1 = null ;
158+ Span < byte > bytes1 = slen1 > STACKALLOC_LIMIT
159+ ? ( rented1 = System . Buffers . ArrayPool < byte > . Shared . Rent ( slen1 ) ) . AsSpan ( 0 , slen1 )
160+ : stackalloc byte [ slen1 ] ;
161+ Span < byte > bytes2 = stackalloc byte [ 1 ] ;
162+ var slen3 = Encoding . UTF8 . GetByteCount ( _srp . Name ) ;
163+ byte [ ] rented3 = null ;
164+ Span < byte > bytes3 = slen3 > STACKALLOC_LIMIT
165+ ? ( rented3 = System . Buffers . ArrayPool < byte > . Shared . Rent ( slen3 ) ) . AsSpan ( 0 , slen3 )
166+ : stackalloc byte [ slen3 ] ;
167+ int l1 = Encoding . UTF8 . GetBytes ( _srp256 . Name . AsSpan ( ) , bytes1 ) ;
168+ int l2 = Encoding . UTF8 . GetBytes ( "," . AsSpan ( ) , bytes2 ) ;
169+ int l3 = Encoding . UTF8 . GetBytes ( _srp . Name . AsSpan ( ) , bytes3 ) ;
170+ result . WriteByte ( IscCodes . CNCT_plugin_list ) ;
171+ result . WriteByte ( ( byte ) ( l1 + l2 + l3 ) ) ;
172+ result . Write ( bytes1 ) ;
173+ result . Write ( bytes2 ) ;
174+ result . Write ( bytes3 ) ;
175+ if ( rented1 != null )
176+ {
177+ System . Buffers . ArrayPool < byte > . Shared . Return ( rented1 , clearArray : true ) ;
178+ }
179+ if ( rented3 != null )
180+ {
181+ System . Buffers . ArrayPool < byte > . Shared . Return ( rented3 , clearArray : true ) ;
182+ }
183+ }
104184
105- result . WriteByte ( IscCodes . CNCT_client_crypt ) ;
106- result . WriteByte ( 4 ) ;
107- result . Write ( TypeEncoder . EncodeInt32 ( WireCryptOptionValue ( WireCrypt ) ) , 0 , 4 ) ;
185+ {
186+ result . WriteByte ( IscCodes . CNCT_client_crypt ) ;
187+ result . WriteByte ( 4 ) ;
188+ Span < byte > bytes = stackalloc byte [ 4 ] ;
189+ if ( ! BitConverter . TryWriteBytes ( bytes , IPAddress . NetworkToHostOrder ( WireCryptOptionValue ( WireCrypt ) ) ) )
190+ {
191+ throw new InvalidOperationException ( "Failed to write wire crypt option bytes." ) ;
192+ }
193+ result . Write ( bytes ) ;
194+ }
108195 }
109196 else
110197 {
111- var pluginNameBytes = Encoding . UTF8 . GetBytes ( _sspi . Name ) ;
198+ var slen = Encoding . UTF8 . GetByteCount ( _sspi . Name ) ;
199+ byte [ ] rented = null ;
200+ Span < byte > pluginNameBytes = slen > STACKALLOC_LIMIT
201+ ? ( rented = System . Buffers . ArrayPool < byte > . Shared . Rent ( slen ) ) . AsSpan ( 0 , slen )
202+ : stackalloc byte [ slen ] ;
203+ int pluginNameLen = Encoding . UTF8 . GetBytes ( _sspi . Name . AsSpan ( ) , pluginNameBytes ) ;
112204 result . WriteByte ( IscCodes . CNCT_plugin_name ) ;
113- result . WriteByte ( ( byte ) pluginNameBytes . Length ) ;
114- result . Write ( pluginNameBytes , 0 , pluginNameBytes . Length ) ;
205+ result . WriteByte ( ( byte ) pluginNameLen ) ;
206+ result . Write ( pluginNameBytes [ ..pluginNameLen ] ) ;
207+
115208 var specificData = _sspi . InitializeClientSecurity ( ) ;
116209 WriteMultiPartHelper ( result , IscCodes . CNCT_specific_data , specificData ) ;
117210
118211 result . WriteByte ( IscCodes . CNCT_plugin_list ) ;
119- result . WriteByte ( ( byte ) pluginNameBytes . Length ) ;
120- result . Write ( pluginNameBytes , 0 , pluginNameBytes . Length ) ;
212+ result . WriteByte ( ( byte ) pluginNameLen ) ;
213+ result . Write ( pluginNameBytes [ .. pluginNameLen ] ) ;
121214
122215 result . WriteByte ( IscCodes . CNCT_client_crypt ) ;
123216 result . WriteByte ( 4 ) ;
124- result . Write ( TypeEncoder . EncodeInt32 ( IscCodes . WIRE_CRYPT_DISABLED ) , 0 , 4 ) ;
217+ Span < byte > wireCryptBytes = stackalloc byte [ 4 ] ;
218+ if ( ! BitConverter . TryWriteBytes ( wireCryptBytes , IPAddress . NetworkToHostOrder ( IscCodes . WIRE_CRYPT_DISABLED ) ) )
219+ {
220+ throw new InvalidOperationException ( "Failed to write wire crypt disabled bytes." ) ;
221+ }
222+ result . Write ( wireCryptBytes ) ;
223+ if ( rented != null )
224+ {
225+ System . Buffers . ArrayPool < byte > . Shared . Return ( rented , clearArray : true ) ;
226+ }
125227 }
126228
127229 return result . ToArray ( ) ;
@@ -309,7 +411,21 @@ void ReleaseAuth()
309411 _sspi = null ;
310412 }
311413
312- static void WriteMultiPartHelper ( Stream stream , byte code , byte [ ] data )
414+ static void WriteMultiPartHelper ( MemoryStream stream , byte code , byte [ ] data )
415+ {
416+ const int MaxLength = 255 - 1 ;
417+ var part = 0 ;
418+ for ( var i = 0 ; i < data . Length ; i += MaxLength ) {
419+ stream . WriteByte ( code ) ;
420+ var length = Math . Min ( data . Length - i , MaxLength ) ;
421+ stream . WriteByte ( ( byte ) ( length + 1 ) ) ;
422+ stream . WriteByte ( ( byte ) part ) ;
423+ stream . Write ( data , i , length ) ;
424+ part ++ ;
425+ }
426+ }
427+
428+ static void WriteMultiPartHelper ( MemoryStream stream , byte code , ReadOnlySpan < byte > data )
313429 {
314430 const int MaxLength = 255 - 1 ;
315431 var part = 0 ;
@@ -319,7 +435,7 @@ static void WriteMultiPartHelper(Stream stream, byte code, byte[] data)
319435 var length = Math . Min ( data . Length - i , MaxLength ) ;
320436 stream . WriteByte ( ( byte ) ( length + 1 ) ) ;
321437 stream . WriteByte ( ( byte ) part ) ;
322- stream . Write ( data , i , length ) ;
438+ stream . Write ( data [ i .. ( i + length ) ] ) ;
323439 part ++ ;
324440 }
325441 }
0 commit comments