Skip to content

Commit 3d3e596

Browse files
mconnewStephenBonikowsky
authored andcommitted
Modify digest service to fail if wrong type of authentication is sent
1 parent a0837bc commit 3d3e596

File tree

1 file changed

+45
-5
lines changed

1 file changed

+45
-5
lines changed

src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/DigestServiceAuthorizationManager.cs

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)