@@ -58,11 +58,16 @@ public override bool CheckAccess(OperationContext operationContext, ref Message
5858 }
5959
6060 var digestState = new DigestAuthenticationState ( operationContext , GetRealm ( ref message ) ) ;
61- if ( ! digestState . IsRequestDigestAuth )
61+ if ( string . IsNullOrEmpty ( digestState . AuthMechanism ) ) // No authentication requested
6262 {
6363 return UnauthorizedResponse ( digestState ) ;
6464 }
6565
66+ if ( ! digestState . IsRequestDigestAuth ) // Authentication requested but not Digest
67+ {
68+ return BadAuthenticationResponse ( digestState , operationContext ) ;
69+ }
70+
6671 string password ;
6772 if ( ! GetPassword ( ref message , digestState . Username , out password ) )
6873 {
@@ -90,6 +95,21 @@ public virtual string GetRealm(ref Message message)
9095
9196 public abstract bool GetPassword ( ref Message message , string username , out string password ) ;
9297
98+ private bool BadAuthenticationResponse ( DigestAuthenticationState digestState , OperationContext operationContext )
99+ {
100+ object responsePropertyObject ;
101+ if ( ! operationContext . OutgoingMessageProperties . TryGetValue ( HttpResponseMessageProperty . Name , out responsePropertyObject ) )
102+ {
103+ responsePropertyObject = new HttpResponseMessageProperty ( ) ;
104+ operationContext . OutgoingMessageProperties [ HttpResponseMessageProperty . Name ] = responsePropertyObject ;
105+ }
106+
107+ var responseMessageProperty = ( HttpResponseMessageProperty ) responsePropertyObject ;
108+ responseMessageProperty . StatusCode = HttpStatusCode . Forbidden ;
109+ responseMessageProperty . StatusDescription = "Authentication should use Digest auth, received " + digestState . AuthMechanism + " auth instead" ;
110+ return false ;
111+ }
112+
93113 private bool UnauthorizedResponse ( DigestAuthenticationState digestState )
94114 {
95115 digestState . NonceExpiryTime = GetNonceExpiryTime ( ) ;
@@ -120,7 +140,7 @@ public void ApplyDispatchBehavior(ServiceDescription serviceDescription, Service
120140
121141 private struct DigestAuthenticationState
122142 {
123- private const string DigestAuthenticationMechanism = "Digest " ;
143+ private const string DigestAuthenticationMechanism = "Digest" ;
124144 private const int DigestAuthenticationMechanismLength = 7 ; // DigestAuthenticationMechanism.Length;
125145 private const string UriAuthenticationParameter = "uri" ;
126146 private const string UsernameAuthenticationParameter = "username" ;
@@ -145,7 +165,7 @@ public DigestAuthenticationState(OperationContext operationContext, string realm
145165 _password = null ;
146166 _authorized = new bool ? ( ) ;
147167 _authorizationHeader = GetAuthorizationHeader ( operationContext , out _method ) ;
148- if ( _authorizationHeader . Length < DigestAuthenticationMechanismLength || ! _authorizationHeader . StartsWith ( DigestAuthenticationMechanism ) )
168+ if ( ! _authorizationHeader . StartsWith ( DigestAuthenticationMechanism ) )
149169 {
150170 _authorized = false ;
151171 _nonceString = string . Empty ;
@@ -179,7 +199,27 @@ public bool Authorized
179199 }
180200 }
181201
182- public bool IsRequestDigestAuth { get { return _authorizationHeader . StartsWith ( DigestAuthenticationMechanism ) ; } }
202+ public bool IsRequestDigestAuth
203+ {
204+ get
205+ {
206+ return AuthMechanism . Equals ( DigestAuthenticationMechanism ) ;
207+ }
208+ }
209+
210+ public string AuthMechanism
211+ {
212+ get
213+ {
214+ string [ ] authMechAndData = _authorizationHeader . Split ( ' ' ) ;
215+ if ( authMechAndData . Length >= 2 )
216+ {
217+ return authMechAndData [ 0 ] ;
218+ }
219+
220+ return string . Empty ;
221+ }
222+ }
183223
184224 public string Nonce { get { return _nonceString ; } }
185225
@@ -267,7 +307,7 @@ private string CalculateHash(string plaintext)
267307
268308 public void SetChallengeResponse ( HttpStatusCode statusCode , string statusDescription )
269309 {
270- StringBuilder authChallenge = new StringBuilder ( DigestAuthenticationMechanism ) ;
310+ StringBuilder authChallenge = new StringBuilder ( DigestAuthenticationMechanism ) . Append ( ' ' ) ;
271311 authChallenge . AppendFormat ( RealmAuthenticationParameter + "=\" {0}\" , " , _realm ) ;
272312 authChallenge . AppendFormat ( NonceAuthenticationParameter + "=\" {0}\" , " , Nonce ) ;
273313 authChallenge . Append ( "opaque=\" 0000000000000000\" , " ) ;
0 commit comments