c# ClientCertificates.Add() certificate not attached to httpwebrequest - c#

I'm grabbing a self-signed piv auth X509certificate from a smart card inserted in a USB reader and am attaching it to the HttpWebRequest via the code below:
HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(uriInfo);
Request.ClientCertificates.Add(theCert);
Request.Method = "POST";
//get the response back (the mini driver will prompt for a PIN at this point)
HttpWebResponse Response = (HttpWebResponse)Request.GetResponse();
Here is the thing that is confusing me, this code works on some machines but not on others. It's worked on Win7 on one machine and not on Win7 on another, it works in Win8. I've even tried running it in a Virtual Machine of Win8 which works, which is a guest of a Win7 host machine that doesn't work.
I've read a lot of articles on stack overflow, and tried many different things to get this to work, but nothing seems to. Since my certificate doesn't contain the private key info, that seems to be why it is not included in the request? Which is similar to this question: HttpWebRequest doesn't seem to be sending a client SSL certificate
Since it works on some machines and not others is this something I need to configure differently on the machines where it is not working?
I know the cert is not being attached because of some wireshark investigating. The certificate I'm using has been set up on the server, so it should trust it (and does in some cases).
Some things I'm doing different than other posts is I'm getting the cert from a piv smart card and simply attaching it to the request. When I call GetResponse, the microsoft minidriver steps in a prompts for a PIN to be entered. But since the certificate is not being attached to the request, I never get the prompt for the PIN and the server returns a 403 Forbidden error.
Any ideas?
(This is my first post here, so please forgive any sins which I've committed)

Ok, I finally found out what the problem was. I noticed that the when the smart card was inserted into the reader, the certificate was not propagated to the personal store. Then I found that the thing responsible for doing this was the a service called "Certificate Propagation".
I noticed that service was not running and when I tried starting it, it would stop right away giving the message,
"The Certificate Propagation service on Local Computer has started
then stopped. Some services stop automatically if they are not in use
by other services or programs."
After some digging on why this service would start but not stay running I found it was due to a Group Policy setting stashed in the registry. Changing the following registry setting from 0 to 1 fixed the issue for me:
HKLM\Software\Policies\Microsoft\Windows\Certprop\CertPropEnabled = 1

Related

Connect-Azure AD in PowerShell Script called from C# fails in a specific way THE FIRST TIME, then works?

Here's the gist of my issue. I have a C# program that is calling several PowerShell cmdlets.
All the calls work, except when I get to "Connect-AzureAD -TenantId XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
But the way it "fails" is odd. It only lets me enter my Microsoft Account, but not the password. IF I RUN IT AGAIN, I can log in correctly and it works.
I thought I was hitting a timeout of some kind, but each call bellow results in a Null Reference Exception. You can see my comments of frustration.
// All of these are set to null...so what gives?
// all generate NRE's
//Debug.Print("MaxIdle Timeout is |{0}|", runspace.ConnectionInfo.MaxIdleTimeout.ToString());
//Debug.Print("Current Idle Timeout is |{0}|", runspace.ConnectionInfo.IdleTimeout.ToString());
//Debug.Print("Operation Timeout is |{0}|", runspace.ConnectionInfo.OperationTimeout.ToString());
Thoughts, ideas, comments?
I can post more of the code, if needed, but everything else works all the time.
Per a comment, I added a CR, but it appeared to do nothing (I will try a CR+LF, because I have no idea what's actually broken here, so there's no harm in trying).
So...after the PowerShell invoke call, I collect the results as follows:
foreach (PSObject outputObject in results)
and my results collection has these four errors in it:
{One or more errors occurred.: The browser based authentication dialog failed to complete. Reason: The server or proxy was not found.}
{One or more errors occurred.}
{ The browser based authentication dialog failed to complete. Reason: The server or proxy was not found.}
{One or more errors occurred.: The browser based authentication dialog failed to complete. Reason: The server or proxy was not found.}
It's telling me what I already know (that auth didn't work), but I'm still clueless as to what the actual issue is.
Adding some more detail
So...I've tried a few things. I added my Microsoft account to the connect. The result was even more odd -- a long delay, no password screen, and failure to log in.
Then I pivoted to setting up an application principal as detailed here: "Using a Service Principal to connect to a directory in PowerShell" https://learn.microsoft.com/en-us/powershell/azure/active-directory/signing-in-service-principal?view=azureadps-2.0
I got it all set up and verified in PowerShell that I can connect, then I placed the exact same (I copied and pasted it) Connect-AzureAD with the tenant, application ID, and certificate thumbprint that I used in PowerShell. It failed with these "new" errors -- still four somehow:
One or more errors occurred.
An error occurred while sending the request.
The remote name could not be resolved: 'login.microsoftonline.com'
One or more errors occurred.
Tomorrow, I'll fire up Wireshark. I'm getting the feeling that these errors are all misleading, although the fact that it works on the second try is just mind boggling.

RemoteCertificateChainErrors - Empty ChainElementStatus C#

Strange issue happening intermittently whereby my HTTPS call to another service results in an exception being thrown (Underlying channel closed, remote certificate invalid according to callback...etc).
I'm hosting .net core (461) inside an azure app service.
My SSL certificate on the service being consumed is a public CA (GeoTrust/Digicert) certificate, and the same calls work almost all of the time, but I get periods when they routinely fail without any code change or deployments.
The strange part is, I supplied my own delegate (ServerCertificateValidationCallback) to skim the details of the certificate being returned, its chain, policy errors, etc - and when I get the error, the SSLPolicyError is set to RemoteCertificateChainErrors, yet when iterating over the ChainElements of the X509Chain, it returns a single element (my certificate) - and the ChainElementStatus is empty, with no corresponding deep-dive detail as to why the remote chain was considered invalid, it just states that it is.
I have compared this to an automated test using badssl.com as a test bed and I correctly get full chain details, including the reason as to why one of the elements was considered bad.
What possible reason could cause a RemoteCertificateChainErrors SSLPolicyError without having any corresponding chain information? Could it be a piece of networking kit has failed to call the CA itself to assess validity of the certificate?
Most strange error, appreciate any input!
We finally resolved this, by having to include the intermediate certificate alongside our ssl certificate on the service end. We still think the issue is in the failure to verify the intermediate certificate remotely in good time when not included in the bundle, but have yet to verify this.

C#/UWP : How to manage certificate errors with HttpClient?

I've developed an UWP app for a client, which uses WebServices that are hosted in its domain.
Until now, the URL WebServices were related to a test server that don't use SSL
But now, the WebServices URL are related to the prod server that use SSL
As I'm a subcontractor, I don't have an AD account, and I need to use the VPN to access to the client's WebServices.
I didn't get any problem to access to the test server, but it's no longer the case with the prod server.
When I try to access to access to the URL through a navigator, I get a security warning message (DLG_FLAGS_INVALID_CA), but I can "force" the navigation to the URL.
But when I call the WebService from the app with HttpCLient, I also get an error (HttpRequestException) and I don't see how I could fix it.
Here are the details of the exception:
HResult = -2147012851
InnerException =
{System.Runtime.InteropServices.COMException (0x80072F0D): Can't find text related to the error code. The certificate authority is invalid or is incorrect at
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task) ...
Message = "An error occurred while sending the request."
Source = "System.Net.Http"
I've already tried to install handly the certificates on my computer, but this doesn't fix the issue...
Is there another approach?
Edit: add "user" certificate
The client sent me the "user" certificate and I installed it on my computer in "User\Trusted Root Certification Authorities Certificate Store": there is no longer problem from the navigator. However, in the app, the problem is still present.
Is it normal? Do I need to "attach" the certificate to the app? This is not really usefull, as the client's users don't need this problem: it's only me as I'm a subcontractor using the VPN...
Edit: add "computer" certificate
Finally the client sent me the "computer" certificate and I installed it on my computer in "Computer\Trusted Root Certification Authorities Certificate Store": this time I could use the app without problem.
It's good to know that the UWP app and the navigators don't use the same certificate.
The problem has been fixed by installing the "user" and "computer" certificates that has been sent by the client.

C# Cannot load XML document from server

I had an XMLDocument loading a document from a server with no problems till, almost randomly, I started getting a connection refused error.
It also doesn't matter what host I put in, whether it's a legit one or unresolvable. It always gives the same result.
Here's the code:
XmlDocument doc = new XmlDocument();
doc.Load("http://doesnotmatterifIresolveornot.com");
And here is the error:
{"No connection could be made because the target machine actively refused it 127.0.0.1:8888"}
I've turned off any applicable firewalls I can find in Win7, but it's weird cause it happened while I was testing it.
Find out why it's trying to go to 127.0.0.1:8888.
My guess is that for some reason, it thinks that's your HTTP proxy. Did you run something like Fiddler recently? Fiddler runs on 8888 and changes your default proxy settings - maybe they got stuck incorrectly?
Look in Control Panel, or in the Internet Explorer settings.
Are you serving your XML document using IIS? If so, you may need to add a mime-type definition to IIS to serve XML files. This article should help with that (if it is indeed the problem).
you may also try the HTTP loader to get a more detailed picture of what the server is responding with (HTTP headers, in particular, could be useful for troubleshooting).
I suspect the primary issue is that you're trying to connect to a socket (server + port) that the server isn't configured to listen on -- that means you'll get this error regardless of whether or not the URL resolves, since the server isn't configured to deal with a socket connection of the sort you're sending it.

Using .NET's HttpWebRequest to download a multitude of files in a row

I have an application that needs to download several files in a row in succession (sometimes a few thousand). However, what ends up happening when several files need to be downloaded is I get an exception with an inner exception of type SocketException and the error code 10048 (WSAEADDRINUSE). I did some digging and basically it's because the server has run out of sockets (and they are all waiting for 240s or so before they become available again) - not coincidentally it starts happening around the 1024 file range. I would expect that the HttpWebRequest/ServicePointManager would be reusing my connection, but apparently it is not (and the files are https, so that may be part of it). I never saw this problem in the C++ code that this was ported from (but that doesn't mean it didn't ever happen - I'd be surprised if it was, though).
I am properly closing the WebRequest object and the HttpWebRequest object has KeepAlive set to true by default. Next my intent is to fiddle around with ServicePointManager.SetTcpKeepAlive(). However, I can't see how more people haven't run into this problem.
Has anyone else run into the problem, and if so, what did you do to get around it? Currently I have a retry scheme that detects this error and waits it out, but that doesn't seem like the right thing to do.
Here's some basic code to verify what I'm doing (just in case I'm missing closing something):
WebRequest webRequest = WebRequest.Create(uri);
webRequest.Method = "GET";
webRequest.Credentials = new NetworkCredential(username, password);
WebResponse webResponse = webRequest.GetResponse();
try
{
using(Stream stream = webResponse.GetResponseStream())
{
// read the stream
}
}
finally
{
webResponse.Close()
}
What kind of application is this? You mentioned that the server is running out of ports, but then you mentioned HttpWebRequest. Are you running this code in a webservice or ASP.NET page, which is trying to then download multiple files for the same incoming request from the client?
What kind of authentication is the page using? If it is using NTLM authentication, then the connections cannot be shared if the credentials being used are different for each request.
What I would suggest is to group your request per credential. So, for eg, all requests using username "John" would be grouped. You can specify the "ConnectionGroupName" property on the service point, so the system will try to reuse connections for the same credential and server.
If that also doesnt work, you will need to do one or more of the following:
1) Throttle your requests.
2) Increase the wildcard port range.
3) Use the BindIPConnectionCallback on ServicePoint to make it bind to a non-wildcard port (i.e a port in the range 1024-16384)
More digging seems to point to it possibly being due to authentication and the UnsafeAuthenticatedConnectionSharing property might alleviate this. However, I'm not sure that's the best thing, either.

Categories

Resources