11using System ;
2- using System . Collections . Generic ;
3- using Microsoft . Extensions . Logging ;
42using Npgsql . Internal ;
53
64namespace Npgsql . BackendMessages ;
@@ -44,23 +42,48 @@ internal static AuthenticationMD5PasswordMessage Load(NpgsqlReadBuffer buf)
4442 => Salt = salt ;
4543}
4644
45+ #region SHA256Password
46+
4747sealed class AuthenticationSHA256PasswordMessage : AuthenticationRequestMessage
4848{
4949 internal override AuthenticationRequestType AuthRequestType => AuthenticationRequestType . SHA256Password ;
50+ internal PasswordStoreType PasswordStoreType { get ; }
51+ internal string RandomCode { get ; }
52+ internal string Token { get ; set ; }
53+ internal int Iteration { get ; }
5054
51- internal byte [ ] Salt { get ; }
52-
53- internal static AuthenticationSHA256PasswordMessage Load ( NpgsqlReadBuffer buf )
55+ public AuthenticationSHA256PasswordMessage
56+ (
57+ PasswordStoreType passwordStoreType ,
58+ NpgsqlReadBuffer buf
59+ )
5460 {
55- var salt = new byte [ 32 ] ; // SHA-256盐值通常为32字节
56- buf . ReadBytes ( salt , 0 , 32 ) ;
57- return new AuthenticationSHA256PasswordMessage ( salt ) ;
61+ PasswordStoreType = passwordStoreType ;
62+ RandomCode = buf . ReadString ( 64 ) ;
63+ Token = buf . ReadString ( 8 ) ;
64+ Iteration = buf . ReadInt32 ( ) ;
5865 }
5966
60- AuthenticationSHA256PasswordMessage ( byte [ ] salt )
61- => Salt = salt ;
67+ internal static AuthenticationRequestMessage Load ( NpgsqlReadBuffer buf )
68+ {
69+ var passwordStoreTypeValue = buf . ReadInt32 ( ) ;
70+ var passwordStoreType = ( PasswordStoreType ) passwordStoreTypeValue ;
71+
72+ return passwordStoreType switch
73+ {
74+ PasswordStoreType . PlainText => AuthenticationCleartextPasswordMessage . Instance ,
75+ PasswordStoreType . MD5 => AuthenticationMD5PasswordMessage . Load ( buf ) ,
76+ PasswordStoreType . SHA256 => new AuthenticationSHA256PasswordMessage (
77+ passwordStoreType , buf
78+ ) ,
79+ _ => throw new InvalidOperationException ( $ "Not supported password store type({ passwordStoreTypeValue } )")
80+ } ;
81+ }
6282}
6383
84+ #endregion SHA256Password
85+
86+
6487sealed class AuthenticationGSSMessage : AuthenticationRequestMessage
6588{
6689 internal override AuthenticationRequestType AuthRequestType => AuthenticationRequestType . GSS ;
@@ -95,118 +118,6 @@ sealed class AuthenticationSSPIMessage : AuthenticationRequestMessage
95118 AuthenticationSSPIMessage ( ) { }
96119}
97120
98- #region SASL
99-
100- sealed class AuthenticationSASLMessage : AuthenticationRequestMessage
101- {
102- internal override AuthenticationRequestType AuthRequestType => AuthenticationRequestType . SASL ;
103- internal List < string > Mechanisms { get ; } = [ ] ;
104-
105- internal AuthenticationSASLMessage ( NpgsqlReadBuffer buf )
106- {
107- while ( buf . Buffer [ buf . ReadPosition ] != 0 )
108- Mechanisms . Add ( buf . ReadNullTerminatedString ( ) ) ;
109- buf . ReadByte ( ) ;
110- if ( Mechanisms . Count == 0 )
111- throw new NpgsqlException ( "Received AuthenticationSASL message with 0 mechanisms!" ) ;
112- }
113- }
114-
115- sealed class AuthenticationSASLContinueMessage : AuthenticationRequestMessage
116- {
117- internal override AuthenticationRequestType AuthRequestType => AuthenticationRequestType . SASLContinue ;
118- internal byte [ ] Payload { get ; }
119-
120- internal AuthenticationSASLContinueMessage ( NpgsqlReadBuffer buf , int len )
121- {
122- Payload = new byte [ len ] ;
123- buf . ReadBytes ( Payload , 0 , len ) ;
124- }
125- }
126-
127- sealed class AuthenticationSCRAMServerFirstMessage
128- {
129- internal string Nonce { get ; }
130- internal string Salt { get ; }
131- internal int Iteration { get ; }
132-
133- internal static AuthenticationSCRAMServerFirstMessage Load ( byte [ ] bytes , ILogger connectionLogger )
134- {
135- var data = NpgsqlWriteBuffer . UTF8Encoding . GetString ( bytes ) ;
136- string ? nonce = null , salt = null ;
137- var iteration = - 1 ;
138-
139- foreach ( var part in data . Split ( ',' ) )
140- {
141- if ( part . StartsWith ( "r=" , StringComparison . Ordinal ) )
142- nonce = part . Substring ( 2 ) ;
143- else if ( part . StartsWith ( "s=" , StringComparison . Ordinal ) )
144- salt = part . Substring ( 2 ) ;
145- else if ( part . StartsWith ( "i=" , StringComparison . Ordinal ) )
146- iteration = int . Parse ( part . Substring ( 2 ) ) ;
147- else
148- connectionLogger . LogDebug ( "Unknown part in SCRAM server-first message:" + part ) ;
149- }
150-
151- if ( nonce == null )
152- throw new NpgsqlException ( "Server nonce not received in SCRAM server-first message" ) ;
153- if ( salt == null )
154- throw new NpgsqlException ( "Server salt not received in SCRAM server-first message" ) ;
155- if ( iteration == - 1 )
156- throw new NpgsqlException ( "Server iterations not received in SCRAM server-first message" ) ;
157-
158- return new AuthenticationSCRAMServerFirstMessage ( nonce , salt , iteration ) ;
159- }
160-
161- AuthenticationSCRAMServerFirstMessage ( string nonce , string salt , int iteration )
162- {
163- Nonce = nonce ;
164- Salt = salt ;
165- Iteration = iteration ;
166- }
167- }
168-
169- sealed class AuthenticationSASLFinalMessage : AuthenticationRequestMessage
170- {
171- internal override AuthenticationRequestType AuthRequestType => AuthenticationRequestType . SASLFinal ;
172- internal byte [ ] Payload { get ; }
173-
174- internal AuthenticationSASLFinalMessage ( NpgsqlReadBuffer buf , int len )
175- {
176- Payload = new byte [ len ] ;
177- buf . ReadBytes ( Payload , 0 , len ) ;
178- }
179- }
180-
181- sealed class AuthenticationSCRAMServerFinalMessage
182- {
183- internal string ServerSignature { get ; }
184-
185- internal static AuthenticationSCRAMServerFinalMessage Load ( byte [ ] bytes , ILogger connectionLogger )
186- {
187- var data = NpgsqlWriteBuffer . UTF8Encoding . GetString ( bytes ) ;
188- string ? serverSignature = null ;
189-
190- foreach ( var part in data . Split ( ',' ) )
191- {
192- if ( part . StartsWith ( "v=" , StringComparison . Ordinal ) )
193- serverSignature = part . Substring ( 2 ) ;
194- else
195- connectionLogger . LogDebug ( "Unknown part in SCRAM server-first message:" + part ) ;
196- }
197-
198- if ( serverSignature == null )
199- throw new NpgsqlException ( "Server signature not received in SCRAM server-final message" ) ;
200-
201- return new AuthenticationSCRAMServerFinalMessage ( serverSignature ) ;
202- }
203-
204- internal AuthenticationSCRAMServerFinalMessage ( string serverSignature )
205- => ServerSignature = serverSignature ;
206- }
207-
208- #endregion SASL
209-
210121enum AuthenticationRequestType
211122{
212123 Ok = 0 ,
@@ -215,8 +126,12 @@ enum AuthenticationRequestType
215126 GSS = 7 ,
216127 GSSContinue = 8 ,
217128 SSPI = 9 ,
218- SASL = 10 ,
219- SASLContinue = 11 ,
220- SASLFinal = 12 ,
221- SHA256Password = 13
129+ SHA256Password = 10
130+ }
131+
132+ enum PasswordStoreType
133+ {
134+ PlainText = 0 ,
135+ MD5 = 1 ,
136+ SHA256 = 2
222137}
0 commit comments