Welcome to MSDN Blogs Sign in | Join | Help

Orcas SP1 Released

The first service pack for .NET Framework 3.5 came out yesterday, primarily focusing on fixing bugs and performance issues.  There are some new features, notably around improving the support for REST based services and around serialization.

Here are some known issues related to WCF in this release.

Authentication failure when Windows authentication is used over certain transports

WCF now specifies a default domain target name in Windows authentication scenarios. When upgrading, the client may see an authentication failure when the following conditions exist:

  • The scenario uses ClientCredentialType.Windows, which specifies the Negotiate authentication scheme.
  • The scenario uses http, https, or net.tcp.
  • The service runs under a non-domain account.

An example of the authentication failure is "System.ComponentModel.Win32Exception The target principal name is incorrect"

To resolve this issue:

The client must override the default domain target name by specifying the Service Principal Name of the server in the SpnEndpointIdentity class, or User Principal Name in the UpnEndpointIdentity class, and then passing the identity to the EndpointAddress. If the client uses Https and requires X509CertificateEndpointIdentity, the client must still specify the SpnEndpointIdentity or UpnEndpointIdentity. The X509CertificateEndpointIdentity enables validation of thumbprints. The client can work around the loss of validation by registering for the System.Net.ServicePointManager.ServerCertificateValidationCallback and performing thumbprint validation manually.

Breaking changes in the SspiNegotiatedOverTransport authentication mode

When WSHttpBinding, WS2007HttpBinding, or NetTcpBinding is used with SecurityMode = TransportWithMessageCredential and a client credential type of Windows, clients that previously authenticated to a service by using NTLM will now fail to authenticate, with the following error:

"System.ComponentModel.Win32Exception: Security Support Provider Interface (SSPI) authentication failed. The server may not be running in an account with identity 'host/<hostname>'. If the server is running in a service account (Network Service for example), specify the account's ServicePrincipalName as the identity in the EndpointAddress for the server. If the server is running in a user account, specify the account's UserPrincipalName as the identity in the EndpointAddress for the server."

The error appears when the service is running on an account that has an identity other than 'host/<hostname>'. This issue also applies to CustomBindings, which specify the SspiNegotiatedOverTransport authentication mode.

To resolve this issue:

If possible, clients should be updated by using a UPN or SPN endpoint identity that specifies the identity of the service so that Kerberos authentication occurs. The following configuration snippet shows how to do this in the UPN case; the SPN case is similar, but the <servicePrincipalName> element is used instead.

<system.serviceModel>
<client>
<endpoint>
<identity>
<userPrincipalName value="user@domain" />
</identity>
</endpoint>
</client>
</system.serviceModel>

Additionally, clients that use NetTcpBinding or CustomBindings, with SspiNegotiatedOverTransport specified in the stack over SslStreamSecurityBindingElement, must specify a custom IdentityVerifier in the code to perform the CN check of the service's certificate. The following code snippets show how to do this and provide a starting point for IdentityVerifier implementations.

NetTcpBinding tcpBinding = new NetTcpBinding(SecurityMode.TransportWithMessageCredential);
CustomBinding customBinding = new CustomBinding(tcpBinding.CreateBindingElements());
SslStreamSecurityBindingElement ssl = customBinding.Elements.Find<SslStreamSecurityBindingElement>();
ssl.IdentityVerifier = new DnsIdentityVerifier(new DnsEndpointIdentity("DNS.name.of.service.certificate"));
public class DnsIdentityVerifier : IdentityVerifier
{
DnsEndpointIdentity _expectedIdentity;

public DnsIdentityVerifier(DnsEndpointIdentity expectedIdentity)
{
_expectedIdentity = expectedIdentity;
}

public override bool CheckAccess(EndpointIdentity identity, AuthorizationContext authContext)
{
List<Claim> dnsClaims = new List<Claim>();
foreach (ClaimSet claimSet in authContext.ClaimSets)
{
foreach (Claim claim in claimSet)
{
if (ClaimTypes.Dns == claim.ClaimType)
{
dnsClaims.Add(claim);
}
}
}
if (1 != dnsClaims.Count)
{
throw new InvalidOperationException(String.Format("Found {0} DNS claims in authorization context.", dnsClaims.Count));
}
return String.Equals((string)_expectedIdentity.IdentityClaim.Resource, (string)dnsClaims[0].Resource, StringComparison.OrdinalIgnoreCase);
}

public override bool TryGetIdentity(EndpointAddress reference, out EndpointIdentity identity)
{
identity = _expectedIdentity;
return true;
}
}
Published Tuesday, August 12, 2008 5:00 AM by Nicholas Allen
Filed under: , ,

Comments

# WMOC#15 - Visual Studio 2008 SP1 and .NET Framework 3.5 SP1 RTM! - Service Endpoint

New Comments to this post are disabled
 
Page view tracker