Does changing SSL Cert on a server break code? - c#

EDIT:
What should I use to catch the error?
I have this where it fails to connect for an error message and defaults to a generic message.
public string ResponseError {
get {
string retVal = "";
try {
retVal = xmlElements.GetElementValue( FullResponse, "/VancoWS/Response/Errors/Error/ErrorDescription" );
} catch {
retVal = "There has been a problem processing your request. Please try again!";
}
return retVal;
}
}
A payment gateway said they made a change to their SSL Cert and since then our web application has not made a successful connection. The code was written in VS.NET 2008 .NET 3.5 I believe in C#. From what I can tell this looks like the code making the connection:
/* Method to perform web post */
private void SendBuffer(string strXml, out string fullResponse, out bool success)
{
String BaseAddress = Url + "?xml=";
try
{
System.Net.WebClient objRequest = new System.Net.WebClient();
objRequest.Encoding = System.Text.Encoding.ASCII;
byte[] buffer = System.Text.Encoding.ASCII.GetBytes(strXml);
byte[] responseBuffer = objRequest.UploadData(BaseAddress, "POST", buffer);
fullResponse = System.Text.Encoding.ASCII.GetString(responseBuffer);
success = true;
}
catch (Exception ex)
{
fullResponse = ex.ToString();
success = false;
}
}
The payment gateway says they are not getting any connections from our server to theirs. I contacted out webhost and they said they have not changed anything to block connections.
The host says they could access the URL fine with no invalid certificate.
URL in question: https://www.vancoservices.com/cgi-bin/ws2.vps
They also are still running SSLv3 so it's not a problem with protocol change or being forced to TLS 1.x
Any ideas as to what would break this?

Looks like they have set up a certificate which is either not signed by a valid authority or your web server doesn't have the authority that signed this certificate in its trusted CA.
To understand whether it is a problem with the certificate you may try connecting to the webserver that is executing this code, opening a webbrowser and attempting to connect to the address. The browser will tell you whether the certificate is valid or not (probably you will get a warning if it is not).
If you want to disable certificate validations in your code you may try the following:
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
Obviously this is not something you wanna be doing with a Production system, but you could just experiment with it to know whether it is a problem with the SSL certificate they set up and if it is self signed.

The "try" clause around the code is hiding any errors that are happening. One thing you could try is commenting out the try statement allowing the code to break and fall over with an error:
// try
{
...
}
or add a catch clause:
try
{
...
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}

just add the following to your config and change the log file path. this will give a sense if handshake/validation for cert is happening
http://msdn.microsoft.com/en-us/library/ty48b824(v=vs.110).aspx

Related

Trying to verify a LDAP over SSL certificate, Server cannot be reached

I'm currently trying to connect to a LDAPS Server using the following VB.NET Code, which should set the right parameters and use the function seen below to verify the certificate when the Bind function is called.
The value of LdapHost is the IP, 10.100.11.10, and the value for LdapPort is 7636.
connection = new LdapConnection(new LdapDirectoryIdentifier(LdapHost, LdapPort));
connection.AuthType = 2; // Negotiate
connection.SessionOptions.SecureSocketLayer = true;
connection.SessionOptions.VerifyServerCertificate = new VerifyServerCertificateCallback(VerifyServerCertificate);
//Both username and password are correct
connection.Credential = new System.Net.NetworkCredential(strUsername, strPassword);
connection.Bind();
This,
But upon trying to verify the Server Certificate, using the following code:
private bool VerifyServerCertificate(LdapConnection ldapConnection, X509Certificate certificate)
{
try
{
X509Certificate2 certificate2 = new X509Certificate2(certificate);
return certificate2.Verify();
}
catch (Exception ex)
{
throw new LdapException(9999, "Invalid certificate or path.");
}
}
It Errors out at the Bind function saying that it cannot connect to the LDAP Server at all with the message "The LDAP Server cannot be reached"
Although upon testing the connection via PowerShell, the Server is available just fine.
Is there something wrong with my verification method? Should I try a different approach entirely?
I have found the reason why the verification did not work.
Using
X509Chain chain = new X509Chain();
X509Certificate2 certificate2 = new X509Certificate2(certificate);
var chainBuilt = chain.Build(certificate2);
LogEvent("Val", 0, "Chain building status: " + chainBuilt);
if (chainBuilt == false) {
foreach (X509ChainStatus chainStatus in chain.ChainStatus)
LogEvent("Val", 0, "Chain error: " + chainStatus.Status + " " + chainStatus.StatusInformation);
chain.Reset();
return false;
} else {
chain.Reset();
return true;
}
if the verification fails helped me understand that the Root Certificate was not trusted on that specific server.
Furthermore, it told me that it could not reach the Revokation Server to check if the Certificate is still valid.
This couldn't be checked though, since the configuration uses a StartTLS certificate, which does not have a Revokation Server.
Therefore, I added
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreRootRevocationUnknown | X509VerificationFlags.IgnoreEndRevocationUnknown | X509VerificationFlags.IgnoreCtlSignerRevocationUnknown;
to ignore every property regarding the Revokation Server. It can now connect as intended.

X509Certificate2 usage issues since moving to Azure App Service

I have several remote servers that communicate with a central SOAP Service, where they can download the latest X509Certificate2 which can then be used to call a third-party API that requires this certificate to authenticate the requests.
Some of these remote servers are hosted by some of our clients on their own Windows Servers, which may be VMs or physical boxes, and others are hosted by us on Azure VMs.
We have had no previous issue with this functionality until recently when we moved our APIs from being hosted on a physical box to now being hosted in an Azure App Service (with an App Gateway handling requests).
What now happens is that all of the non-Azure servers, download the certificate successfully, but the certificate fails when used with the third-party rejecting the certificate with the error:
The request was aborted: Could not create SSL/TLS secure channel.
I have confirmed that if I manually copy the certificate to the servers, it works fine, but for some reason somewhere in the process of downloading it from the Azure SOAP API it now fails.
The code that we have to export the certificate on the API side so that it can be downloaded is something like:
[WebMethod]
public ClientCertificateMessage GetCertificate(LoginMessage login, string customer)
{
ClientCertificateMessage returnValue = new ClientCertificateMessage();
if (Authentication.VerifyLogin(login))
{
try
{
string filePathNameCertificate = ConfigurationManager.AppSettings["PathToLocalCert"].ToString() + customer + ".p12";
string filePathNamePassword = ConfigurationManager.AppSettings["PathToLocalCert"].ToString() + customer + ".txt";
string password = File.ReadAllText(filePathNamePassword);
X509Certificate2 x509Certificate2 = new X509Certificate2( filePathNameCertificate, password, X509KeyStorageFlags.Exportable);
returnValue.Certificate = x509Certificate2.Export(X509ContentType.Pkcs12, password);
}
catch (Exception ex)
{
// Log Error stuff here is removed
}
}
else
{
// error stuff here is removed
}
return returnValue;
}
The service that retrieves this certificate and uses it looks like:
public static X509Certificate2 GetCertificate(int certificateID, string password, string customer)
{
X509Certificate2 x509Certificate2 = null;
try
{
SoapClient client = new SoapClient();
Login login = CreateLogin();
ClientCertificateMessage clientCertificateMessage = null;
try
{
clientCertificateMessage = client.GetCertificate(login, customer);
}
catch (Exception ex)
{
// error logging removed
}
if ((clientCertificateMessage != null) && (clientCertificateMessage.Certificate != null))
{
using (CertificateData cd = new CertificateData())
{
dynamic revisedCertificate = new ExpandoObject();
revisedCertificate.Certificate = clientCertificateMessage.Certificate;
cd.Update(revisedCertificate, certificateID); // Save certificate data in database for later use
}
x509Certificate2 = new X509Certificate2(clientCertificateMessage.Certificate, password);
}
else
{
// handle logic got no certificate remove
}
}
catch (Exception ex)
{
// error logging removed
}
return x509Certificate2;
}
I cannot see anything that would explain why VMs on Azure continue to work, but all other VMs do not. We know those other servers can communicate and download the certificate, and when recreating the certificate from the byte array saved in the database the thumbprint and everything else matches.
I have seen other articles regarding Certificates on App Services where you need add Settings for WEBSITE_LOAD_CERTIFICATES or WEBSITE_LOAD_USER_PROFILE, however, we have not done this as the certificates do not fail to be generated.
Is there anything that I am missing where perhaps some odd Azure configuration or even some obvious technical reason for why a certificate downloaded fails, but the same certificate manually copied to the server works?
Thanks in advance for helping out.

How to create google translation using windows application without getting the error The Application Default Credentials are not available.?

I am trying to create a google api to extract text from image and later do a translation to English, my sample code bellow
try
{
var JsonFilePath = #"C:\Users\shanjeeva\source\repos\TranslatorWindowsApp\Translator-fa8e022a7ba1.json";
//Authenticate to the service by using Service Account
var credential = GoogleCredential.FromFile(JsonFilePath).CreateScoped(ImageAnnotatorClient.DefaultScopes);
var channel = new Grpc.Core.Channel(ImageAnnotatorClient.DefaultEndpoint.ToString(), credential.ToChannelCredentials());
var client = ImageAnnotatorClient.Create(); // getting an error here
var image = Image.FromFile(#"D:\Work Temp\Translate.JPG");
// Performs label detection on the image file
var response = client.DetectLabels(image);
foreach (var annotation in response)
{
if (annotation.Description != null)
Console.WriteLine(annotation.Description);
}
}
catch (AnnotateImageException ex)
{
AnnotateImageResponse response = ex.Response;
Console.WriteLine(response.Error);
}
catch (Exception ee)
{
Console.WriteLine(ee.Message);
throw;
}
}
also I have setup google cloud application, generated necessary json file eg- Translator-XXXXX.json
some suggested to setup environment variable with the key "GOOGLE_APPLICATION_CREDENTIALS" also I tried, but am getting bellow error
'The Application Default Credentials are not available. They are available if running in Google Compute Engine. Otherwise, the environment variable GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defining the credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.'
Can someone please help me?
I was able to resolve with experts help, sample code bellow, added bellow code just before all other code and it works fine
try
{
var GAC = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS");
if (GAC == null)
{
var path = #"D:\Work Temp\translator-298603-2bb5a20655a2.json";
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", path);
}
}
catch (Exception)
{
}

Oauth initiate failing in Magento 1 site

I am using Nick Vane's Magento REST API and the Oauth authentication works on one client and fails on another.
I have tried resetting the consumer information, client key and secret but on the second site still fails.
var client = new MagentoApi();
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
try
{
if (AdminURLPart.Length > 0)
{
client.SetCustomAdminUrlPart(AdminURLPart);
}
client.Initialize(URL, ConsumerKey, ConsumerSecret);
client.AuthenticateAdmin(MagentoUser, MagentoPassword);
}
catch (Exception e1)
{
BCCUtils.Logger("Authentication Error: " + e1.Message, true, CurrentModule);
return -1;
}
There was a problem with oauth at 'https://www.xxxxz.com/oauth/initiate' for consumer key 'xxxxxxx'. Message: 'oauth_problem=parameter_absent&oauth_parameters_absent=oauth_consumer_key'
It may be helpful to the community that we resolved this problem by removing "www." from the URL being used within the application. Once we did that, the MagentoAPI authentication function within the Nick Vane project worked correctly. This was the case only for the one client where we were having difficulty authenticating.

Reading WebService Wsdl using c#.Net

We have a SOAP based web service and we are able to read its wsdl when we type in the url in Browser. We sit behind a proxy in our network but its not blocking anything and we are always able to read wsdl using browser.But when we enter the url in Browser say http://ist.services/CoreServices/coreservices?wsdl it asks for username and password which is not same as my windows credentials. So when i enter the username and password shared by the dev team , it returns the wsdl page. Please note that this webservice is developed and deployed on java based server.
How do i do the same in c#.net code and how do i pass the Security Crednetials in DiscoveryClientProtocol? I tried the below code which works for the webservices which doesn't ask for the Security credentials.
// Specify the URL to discover.
string sourceUrl = "http://ist.services/CoreServices/coreservices?wsdl";
string outputDirectory = "C:\\Temp";
DiscoveryClientProtocol client = new DiscoveryClientProtocol();
var credentials = new NetworkCredential("sunuser1", "xxxxxxx", "");
WebProxy proxy = new WebProxy("http://proxy.bingo:8000/", true) { Credentials = credentials };
client.Credentials = credentials;
// Use default credentials to access the URL being discovered.
//client.Credentials = credentials;//CredentialCache.DefaultCredentials;
client.Proxy = proxy;
String DiscoverMode = "DiscoverAny";
String ResolveMode = "ResolveAll";
try
{
DiscoveryDocument doc;
// Check to see if whether the user wanted to read in existing discovery results.
if (DiscoverMode == "ReadAll")
{
DiscoveryClientResultCollection results = client.ReadAll(Path.Combine("C:\\Temp", "results.discomap"));
//SaveMode.Value = "NoSave";
}
else
{
// Check to see if whether the user wants the capability to discover any kind of discoverable document.
if (DiscoverMode == "DiscoverAny")
{
doc = client.DiscoverAny(sourceUrl);
}
else
// Discover only discovery documents, which might contain references to other types of discoverable documents.
{
doc = client.Discover(sourceUrl);
}
// Check to see whether the user wants to resolve all possible references from the supplied URL.
if (ResolveMode == "ResolveAll")
client.ResolveAll();
else
{
// Check to see whether the user wants to resolve references nested more than one level deep.
if (ResolveMode == "ResolveOneLevel")
client.ResolveOneLevel();
else
Console.WriteLine("empty");
}
}
}
catch (Exception e2)
{
//DiscoveryResultsGrid.Columns.Clear();
//Status.Text = e2.Message;
Console.WriteLine(e2.Message);
}
// If documents were discovered, display the results in a data grid.
if (client.Documents.Count > 0)
Console.WriteLine(client);
}
}
Since the code didn't help me much , i opened the fiddler to trace the http calls when i manual read the wsdl in browser and i see it takes the credentials i entered as "Authorization: Basic cGDFDdsfdfsdsfdsgsgfg=" . In fiddler i see three calls with responses 401,302 and 200. But in my c#.net code i don't get the 200 response and it always throws me the 404 error.
I further debugged this and in httpresponse of client object i see the flag status as INVOCATION_FLAGS_INITIALIZED | INVOCATION_FLAGS_NEED_SECURITY
So looks like i need to pass the credentials as Security Credentials rather than Network credentials.
The below code has fixed the issue.
CredentialCache myCredentialCache = new CredentialCache { { new Uri(sourceUrl),
"Basic", networkCredential } };
discoveryClientProtocol.AllowAutoRedirect = true;
discoveryClientProtocol.Credentials = myCredentialCache;

Categories

Resources