Showing posts with label Certificates. Show all posts
Showing posts with label Certificates. Show all posts

Tuesday, 17 December 2013

The Network Device Enrollment Service received an http message without the "Operation" tag, or with an invalid "Operation" tag.

We were facing this issue on one of our Microsoft NDES server setup, when tried to enrol/request certificate. IIS logs(C:\inetpub\logs\LogFiles\W3SVC1) shows the http response code being returned is 404.15.

HTTP Error 404.15 - Not Found
The request filtering module is configured to deny a request where the query string is too long.

So server denies our request because while enrol/requesting certificate, we need to send the CSR(certificate response)in query string, so length is big. Checking the CertSrv/mscep's Request Filtering/Max Query String(bytes) setting on that erroneous server was 2048. Increasing this size to 65536 solved the issue. Between by default when you install NDES, the limit would be 65536, but looks like not always the case to be. We can also directly edit the values in applicatioHost.config(C:\Windows\system32\inetsrv\config)

Thursday, 11 July 2013

The Network Device Enrollment Service cannot retrieve one of its required certificates (0x80070057). The parameter is incorrect.

There could be multiple reasons, and try one of below

1. While installing NDES, when you use domain account as service account, and change it to AppPoolIdentity(in AppPool settings screen), then you may face this error. For this you have either revert it to domain account or give private key Read permission for CEP Encryption(CEPEncryption) and Exchange Enrollment Agent(offline request) to SCEP app pool identity.

Thursday, 30 May 2013

Message Security with Certificates for Client/Server validation

few reads

http://msdn.microsoft.com/en-us/library/ms733098.aspx
http://msdn.microsoft.com/en-us/library/ms751516.aspx
http://stackoverflow.com/questions/1570939/wcf-message-security-without-certificate-and-windows-auth

and create two certificates - for client/server.

Server

ICalculator.cs
using System.ServiceModel;
 
namespace MySimpleCalculator
{
    [ServiceContract]
    public interface ICalculator
    {
        [OperationContract]
        int Add(int num1, int num2);
 
        [OperationContract]
        string GetCallerIdentity();
    }
}

Calculator.svc
<%@ ServiceHost Language="C#" Debug="true" Service="MySimpleCalculator.Calculator" CodeBehind="Calculator.svc.cs" %>
Calculator.svc.cs

using System.ServiceModel;
namespace MySimpleCalculator
{
    public class Calculator : ICalculator
    {
        public int Add(int num1, int num2)
        {
            return num1 + num2;
        }
 
        public string GetCallerIdentity()
        {
            // The client certificate is not mapped to a Windows identity by default.
            // ServiceSecurityContext.PrimaryIdentity is populated based on the information
            // in the certificate that the client used to authenticate itself to the service.
            return ServiceSecurityContext.Current.PrimaryIdentity.Name;
        }
    }
}
 
web.config 

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceCredentialsBehavior">
          <serviceCredentials>
            <serviceCertificate findValue="CN=Server" 
                 x509FindType="FindBySubjectDistinguishedName"/>
            <clientCertificate>
              <authentication certificateValidationMode="PeerOrChainTrust" 
                    revocationMode="NoCheck" />
            </clientCertificate>
          </serviceCredentials>
          <!-- To avoid disclosing metadata information, set the value below to false 
                and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the 
                value below to true.  Set to false before deployment to avoid disclosing 
                exception information -->
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service name="MySimpleCalculator.Calculator" behaviorConfiguration="ServiceCredentialsBehavior">
        <endpoint contract="MySimpleCalculator.ICalculator" address="/SimpleCalculator" 
                  binding="wsHttpBinding"
                  bindingConfiguration="MessageUsingCertificate" />
      </service>
    </services>
    <bindings>
      <wsHttpBinding>
        <binding name="MessageUsingCertificate">
          <security mode="Message">
            <message clientCredentialType="Certificate"/>
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
  
</configuration>
------------------------------------------------------------------------

client

class Program
{
   static void Main(string[] args)
   {
      ServiceReference1.CalculatorClient client = new ServiceReference1.CalculatorClient();
 
      Console.WriteLine(client.Add(1, 2));
      Console.WriteLine(client.GetCallerIdentity());
 
      Console.ReadLine();
    }
}
 
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="WSHttpBinding_ICalculator">
                    <security>
                        <message clientCredentialType="Certificate" />
                    </security>
                </binding>
            </wsHttpBinding>
        </bindings>
      <behaviors>
        <endpointBehaviors>
          <behavior name="endpointCredentialsBehavior">
            <clientCredentials>
              <clientCertificate findValue="CN=client"
                 storeLocation="LocalMachine"
                x509FindType="FindBySubjectDistinguishedName" />
              <serviceCertificate>
                <authentication revocationMode="NoCheck"/>
              </serviceCertificate>
            </clientCredentials>
          </behavior>
        </endpointBehaviors>
      </behaviors>
        <client>
            <endpoint address="http://localhost:18499/Calculator.svc/SimpleCalculator"
                binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ICalculator"
                contract="ServiceReference1.ICalculator" name="WSHttpBinding_ICalculator"
                behaviorConfiguration="endpointCredentialsBehavior">
                <identity>
                    <certificate encodedValue="server certificate value" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration> 


Issues

1. {"The request for security token could not be satisfied because authentication failed."} - It means
   Server tries to authenticate Client certificate and its revocation status. So add 'No Revocation'
   @ server side for client certificate.
 
2. SOAP security negotiation with "uri" fails.

   The X.509 certificate CN=subject chain building failed. The certificate that was used has 
   a trust chain that cannot be verified. Replace the certificate or change the 
   certificateValidationMode. The revocation function was unable to check revocation for 
   the certificate. - This happens if server certificate is not trusted by client, add no revocation.
 
     

Wednesday, 29 May 2013

Certificate may not have a private key that is capable of key exchange or the process may not have access rights for the private key

When we add certificate into IIS\Server Certificates, please make sure you have given 'Read' permission for the users that's hosting your web service/site.

Start MMC and add the Certificate Snap-in, selecting the right container owner for your SSL certificate. Find the certificate (it's probably in the personal store), right click on it and choose All Tasks > Manage Private key. Grant read access to the private key to the user hosting your service.

Thursday, 14 July 2011

Create PFX with the Asymmetric keys genereated during CSR phase

This will not work with CNG(KSP)

Steps 1

1. When we create key/pair, store the KeyContainerName.
2. Sign CSR with created keys and get the certificate(one of CER/DER/PEM/CRT) format.
3. Open the certificate using x509certificate2 class, create CspParameter class. Assign the KeyContainerName to CspParamater class.
4. Create RsaCryptoProvider class using CspParamater, and assign it to PrivateKey of x509certificate2.
5. Using Export(pfx, password) option.
6. Clear RsaCryptoProvider using PersistCsp = false, and Clear().

Note
1. If you don't pass valid KeyContainerName, default will be created. But assigning to PrivateKey property will throw exception about Key mismatch(after all they are strongly related).
2. Clear the KeyContainer for better security purposes.

Sample code to get u started.

CspParameters p = new CspParameters();

p.ProviderName = "Microsoft Enhanced Cryptographic Provider v1.0";
p.ProviderType = 1;
p.KeyContainerName = "your container name";
p.KeyNumber = (int)AT_KEYEXCHANGE;

RSACryptoServiceProvider csp = new RSACryptoServiceProvider(p);

X509Certificate2 cer = new X509Certificate2("sss.cer");

cer.PrivateKey = csp;

byte[] bytes = cer.Export(X509ContentType.Pfx, "12345");

FileStream stream = new FileStream("CASigned.pfx", FileMode.CreateNew);

stream.Write(bytes, 0, bytes.Length);

stream.Close();

X509Certificate2 c1 = new X509Certificate2("CASigned.pfx", "12345");

bool value = c1.HasPrivateKey;