Connecting to RESTful site using Script Task - c#

I have been trying various combinations of HttpWebRequest objects (in SSIS) to connect to webservices geocoding site to pull back individual geocoding information with no luck. This is a JSON response and https URL.
string wUrl = "https://geocoding.geo.census.gov/geocoder/geographies/onelineaddress?address=1600+Pennsylvania+Ave+NW,+Washington,+DC,+20500&benchmark=Public_AR_Current&vintage=4&format=json";
X509Certificate cert = X509Certificate.CreateFromCertFile("C:\\Users\\kwhauser\\geocode.cer");
HttpWebRequest httpWReq = (HttpWebRequest)WebRequest.Create(wUrl);
//WebRequest httpWReq = WebRequest.Create(wUrl);
//httpWReq.Method = "GET";
httpWReq.ClientCertificates.Add(cert);
//httpWReq.ContentType = "application/json";
//ServicePointManager.ServerCertificateValidationCallback = (s, cert, chain, ssl) => true;
//ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
//HttpWebResponse httpWResp = (HttpWebResponse)httpWReq.GetResponse();
//HttpWebResponse response = (HttpWebResponse)httpWReq.GetResponse();
try
{
HttpWebResponse response = (HttpWebResponse)httpWReq.GetResponse();
//WebResponse response = httpWReq.GetResponse();
//Stream responseStream = response.GetResponseStream();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
if (ex.InnerException != null)
MessageBox.Show(" InnerException: " + ex.InnerException.Message);
}
It doesn't matter if I try to load cert from file or use the callback one, I still get the same error message:
System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.
DotNet framework version is 4.7. The site expects TLS12. I've added simple REST Client extension to chrome and tested the URL with success. It fails on the GetResponse.
What am I missing?

System.Net.ServicePointManager.SecurityProtocol = (System.Net.SecurityProtocolType)3072;

Related

Could not create SSL/TLS secure channel - HttpWebRequest

I am trying to make a connection to my kubernetes api and cant seem to get SSL to work from C#.
When i run the following via curl, everything seems to work as expected:
And I have this for c# to do the same:
try
{
// use the TLS protocol
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
// create HTTP web request with proper content type
HttpWebRequest request = WebRequest.Create(Constants.K8_API_RC_URI) as HttpWebRequest;
request.ContentType = "application/json;charset=UTF8";
request.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + Constants.K8_TOKEN);
// load the X.509 certificate and add to the web request
X509Certificate cert = new X509Certificate(Constants.K8_CRT);
request.ClientCertificates.Add(cert);
// call the web service and get response
WebResponse response = request.GetResponse();
Stream responseStream = response.GetResponseStream();
string jsonContents = new StreamReader(responseStream).ReadToEnd();
}
catch (Exception exc)
{
// log and print out error
log.Info(exc.Message);
}
Where
Constants.K8_CRT is the Path to ca.crt
and ca.crt contains the following:
-----BEGIN CERTIFICATE-----
MIIDMDCCAhigAwIBAgIIcwd9rrnaPcowDQYJKoZIhvcNAQELBQAwEzERMA8GA1UEAwwIYWNzazhz
and more letters.......
cwSfuIp7e49KC3HSqcU3Mz4oFNm5bw==
-----END CERTIFICATE-----
I get the following error:
Could not create SSL/TLS secure channel.
P.S. I know there are Kubernetes clients for .Net out there and I have tried just about all of them but since I am integrating this with Azure Functions most of the third party libraries do not work for various reasons.
The CA cert should be used to validate server cert chain, not passed as an ClientCertificate.
Here is an example.
ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => {
if (errors == SslPolicyErrors.None) return true;
X509Certificate2 serverCert = new X509Certificate2(certificate);
X509Certificate2 caCert = new X509Certificate2(#"./ca.cert");
chain.ChainPolicy.ExtraStore.Add(caCert);
chain.Build(serverCert);
foreach (var chainStatus in chain.ChainStatus) {
if (chainStatus.Status == X509ChainStatusFlags.UntrustedRoot) continue;
if (chainStatus.Status != X509ChainStatusFlags.NoError) return false;
}
return true;
};
HttpWebRequest request = WebRequest.CreateHttp("https://master:6443/api/v1");
request.Headers[HttpRequestHeader.Authorization] = "Bearer " + "SOME_TOKEN";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
var content = new StreamReader(response.GetResponseStream()).ReadToEnd();
Console.WriteLine(content);
Thanks for #Jimi's comments i was able to get this to work with adding the following:
System.Net.ServicePointManager.ServerCertificateValidationCallback +=
delegate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate,
System.Security.Cryptography.X509Certificates.X509Chain chain,
System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
return true; // **** Always accept
};
NOTE: Im certain this just ignores the SSL validation and continues without it. In our case this may be acceptable.

C# Dynamics CRM Online “The request was aborted: Could not create SSL/TLS secure channel.”

This is an example of web request from CodeActivity on Dynamics CRM Online .
public class CodeActivity1 : CodeActivity
{
protected override void Execute(CodeActivityContext context)
{
var postUrl = "https://jsonplaceholder.typicode.com/posts/";
var request = (HttpWebRequest)WebRequest.Create(postUrl);
request.Method = "GET";
request.ContentType = "application/xml";
request.ContentLength = 0;
HttpWebResponse webresponse = (HttpWebResponse)request.GetResponse();
Encoding enc = System.Text.Encoding.GetEncoding("utf-8");
StreamReader responseStream = new StreamReader(webresponse.GetResponseStream(), enc);
var result = responseStream.ReadToEnd();
webresponse.Close();
.....
}
...
}
I receive "The request was aborted: Could not create SSL/TLS secure channel." error. From the Microsoft documentation (https://msdn.microsoft.com/en-us/library/gg334752.aspx) are the following limitations:
Only the HTTP and HTTPS protocols are allowed.
Access to localhost (loopback) is not permitted.
IP addresses cannot be used. You must use a named web address that requires DNS name resolution.
Anonymous authentication is supported and recommended. There is no provision for prompting the logged on user for credentials or saving those credentials.
Do you have suggestions or ideas relating to the nature of the problem ??
It could be that something in your environment is changing server cert on the fly. Many sniffing app can do it (for example Fiddler). In other words make sure that certificate that you get from httpbin.org is correct. You can check if problem is in validating server certificate by adding validation handler that will ignore any cert error at the beginning of you code:
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
I Rewrite the correct scriptin the hope that it can be useful to someone.
Thanks to #pen for suggestions
public class CodeActivity1 : CodeActivity
{
protected override void Execute(CodeActivityContext context)
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
ITracingService tracingService = context.GetExtension<ITracingService>();
var postUrl = "https://jsonplaceholder.typicode.com/posts/1";
var request = (HttpWebRequest)WebRequest.Create(postUrl);
request.Method = "GET";
request.ContentType = "application/xml";
request.ContentLength = 0;
request.ServicePoint.Expect100Continue = true;
HttpWebResponse webresponse = (HttpWebResponse)request.GetResponse();
Encoding enc = System.Text.Encoding.GetEncoding("utf-8");
StreamReader responseStream = new StreamReader(webresponse.GetResponseStream(), enc);
var result = responseStream.ReadToEnd();
webresponse.Close();
.....
}
...
}

Invoking a SOAP web service: the request was aborted: Could not create SSL/TLS secure channel

I'm trying to invoke a SOAP web service from a .NET application. The web services uses HTTPS (I got that from the URL inside the WSDL) but I can't figure out whether I should invoke it with TLS or SSL. Here's my code:
try
{
string soap = "<BigXmlSOAPHeader></BigXmlSOAPHeader>"
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(ws_uri);
ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, error) =>
{
return true;
};
byte[] bytes;
bytes = System.Text.Encoding.ASCII.GetBytes(soap);
request.ContentType = "text/xml; encoding='utf-8'";
request.Timeout = 1000000000;
request.ContentLength = bytes.Length;
request.Method = "POST";
Stream requestStream = request.GetRequestStream(); // it fails here
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
HttpWebResponse response;
response = (HttpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
XmlTextReader reader = new XmlTextReader(responseStream);
}
catch (Exception ex)
{
DoSomethingWithException(ex);
}
The Exception message is The request was aborted: Could not create SSL/TLS secure channel.
When I copied my header (from debugging) and used it in SoapUI to invoke the web service, it worked which means there's no problem with the web service itself.
UPDATE:
I restarted my application pool in IIS when this occured and it solved the problem. I can't find a logical explanation to this...
Please help.

SSL HttpWebRequest Issues

I am attempting to access an api which they had me install a local cert via mmc I have done so on my local windows 7 machine so I could test out the service. I'm using a simple winforms app to test. I'm assuming this is a self signed cert server side so I'm hoping to bypass the exception for dev purposes.
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(postData);
req.Method = "POST";
req.ContentType = "application/x-www-form-uriencoded";
req.KeepAlive = true;
req.AllowAutoRedirect = false;
X509Store store = new X509Store(StoreName.Root,StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
X509Certificate cert = new X509Certificate();
for (int i = 0; i < store.Certificates.Count; i++)
{
if (store.Certificates[i].SerialNumber == "XXXX")
{
cert = store.Certificates[i];
}
}
req.ClientCertificates.Add(cert);
req.PreAuthenticate = true;
try
{
using (WebResponse resp = req.GetResponse())
{
Stream responseStream = resp.GetResponseStream();
using (StreamReader responseStreamReader = new
StreamReader(responseStream, new ASCIIEncoding()))
{
respString = responseStreamReader.ReadToEnd();
}
}
}
catch (Exception ex)
{
// there is a problem
}
I'm getting the following exception in the try catch:
The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
I do have a certificate object in the variable "cert"
When I go to the api url in my browser I get the caution warning but then can proceed and get data.
I have tried the other fixes recommended on stackoverflow such as suppressing the exception.
ServicePointManager.ServerCertificateValidationCallback = new
RemoteCertificateValidationCallback
(
delegate { return true; }
);
I realize there are quite a few of these questions similar to this and trust me I have read through them all. Thanks for any suggestions they are appreciated.
Hey the following finally fixed it for me. I went to the api server address in my browser and exported their certificate to a file on my desktop. I then opened mmc and installed the certificate like in the following link:
http://support.esri.com/en/knowledgebase/techarticles/detail/38408
After I installed I had no issues calling the webservice and the exception went away.

Accessing ssl server (web service) from .net client

I’m tryng to access a ssl server (web service) from a .net client (c#). I have access to a java client code that can connect to the server. Included in the source code are 3 files (saPubKey.jks, WebServices.pfx and trustStore) and I think that only 2 of the 3 are used in the java example.
private void setSSLConnection(WSBindingProvider bp){
KeyStore ks = KeyStore.getInstance("pkcs12");
ks.load(this.getClass().getClassLoader().getResourceAsStream("WebServices.pfx"), "password".toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, "password".toCharArray());
SSLContext sslContext = SSLContext.getInstance("TLS");
KeyStore ts = KeyStore.getInstance("JKS");
ts.load(this.getClass().getClassLoader().getResourceAsStream("trustStore"), "pass".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ts);
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
bp.getRequestContext().put(JAXWSProperties.SSL_SOCKET_FACTORY, sslContext.getSocketFactory());
}
The code I have for the c# client is this
var clientCertificate = new X509Certificate2(#"C:\WebServices.pfx", "password");
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://blablabla.org:700/fws/ftrs");
req.ClientCertificates.Add(clientCertificate);
req.Headers.Add("SOAPAction", "\"https://blablabla.org:700/fws/ftrs/Rgdvice\"");
req.ContentType = "text/xml;charset=\"utf-8\"";
req.Accept = "text/xml";
req.Method = "POST";
using (Stream stm = req.GetRequestStream())
{
using (StreamWriter stmw = new StreamWriter(stm))
{
stmw.Write(soap);
}
}
WebResponse response = req.GetResponse(); //(500) Internal Server Error.
Stream responseStream = response.GetResponseStream();
Method req.GetResponse() throws "(500) Internal Server Error."
With no client certificates added I get: "An unexpected error occurred on a send."
I also tried this line of code with no luck:
ServicePointManager.ServerCertificateValidationCallback = ((sender, certificate, chain, sslPolicyErrors) => true);
I'm new to ssl and certificates, and really need help accessing the ssl server from c#.
This could be unrelated but make sure web service is not in the app_code folder.

Categories

Resources