Stomp.Net example: need explanation - c#

I test STOMP example Stomp.Net.Example.SendReceiveCore. In connection factory:
SslSettings =
{
ServerName = serverName,
ClientCertSubject = subject,
KeyStoreName = "My",
KeyStoreLocation = "LocalMachine"
}
What should be in ClientCertSubject? In certificate properties, I see Subject is CN = fpclientcert (value fpclientcert). Submitting that value gives error:
[Warn] Found no matching cert. with Subject 'fpclientcert' (SelectLocalCertificate Ln 161 [C:_git\Stomp.Net.Src\Stomp.Net\Transport\SslTransport.cs])
Certificate was created and imported into trust store on a server. Exported client's certificate has been imported into Personal store on client machine.
I can establish connection with that certificates using SslStream socket.

Related

I cannot connect to a remote PC with WinXP OS with CimSession. I get Error "Microsoft.Management.Infrastructure.CimException:..."

In my application I have to connect to remote PC's mostly with WinXP OS (Older production machines) from my office server. I am starting a CIMSession in order to read the CPU Load of the remote PC. If I use following code I get Error:
"Microsoft.Management.Infrastructure.CimException: The client cannot connect to the destination specified in the request. Verify that the service on the destination is running and is accepting requests. Consult the logs and documentation for the WS-Management service running on the destination, most commonly IIS or WinRM. If the destination is the WinRM service, run the following command on the destination to analyze and configure the WinRM service: "winrm quickconfig" "
The remote IP is added into the TrustedHosts list on the server where my app is running
public void Read_CPU_Load()
{
string Namespace = #"root\cimv2";
string OSQuery = "SELECT * FROM Win32_PerfFormattedData_PerfOS_Processor where Name='_Total'";
string domain = "";
string username = "xxxxxx";
var s = new SecureString();
s.AppendChar('P');
s.AppendChar('a');
s.AppendChar('s');
s.AppendChar('s');
s.AppendChar('w');
s.AppendChar('o');
s.AppendChar('r');
s.AppendChar('d');
// create Credentials
CimCredential Credentials = new CimCredential(PasswordAuthenticationMechanism.Default,
domain,
username,
s);
// create SessionOptions using Credentials
WSManSessionOptions SessionOptions = new WSManSessionOptions();
SessionOptions.AddDestinationCredentials(Credentials);
// create Session using computer, SessionOptions
CimSession mySession = CimSession.Create(TagService.IP_to_Connect, SessionOptions);
IEnumerable<CimInstance> queryInstance = mySession.QueryInstances(Namespace, "WQL", OSQuery);
foreach (CimInstance process in queryInstance)
{
CPU_Load_WMI_int = Convert.ToInt16(process.CimInstanceProperties["PercentProcessorTime"]);
}
}

Does RabbitMQ connection fallback from SSL to unsecured, if SSL is not available?

I have setup the following connection factory
var factory = new ConnectionFactory() {
HostName = this.ApplicationConfigurationManager.QueueHostname,
UserName = ...,
Password = ...,
Ssl = new SslOption
{
Enabled = true,
ServerName = this.ApplicationConfigurationManager.QueueHostname,
AcceptablePolicyErrors = SslPolicyErrors.RemoteCertificateNameMismatch | SslPolicyErrors.RemoteCertificateChainErrors
}
};
The factory endpoint correctly shows as {amqp://localhost:5671}, as 5671 is for SSL, 5672 is for unsecured.
Note that locally I have not yet enabled SSL for RabbitMQ.
What I notice is that when I create a connection:
using (var connection = factory.CreateConnection())
and inspect the remote endpoint, it shows as {[::1]:5672}.
Why? I would expect it to try to connect to 5671 and fail (correctly, as I have not enabled it yet).
Does RabbitMQ ConnectionFactory fallback to 5672 (unsecure) if it finds out that SSL (5671) is not enabled?

SSL Certification works with localhost but not computer name or ip

We have a web application running on server and it posts http requests via XDomainRequest (because of IE9).
There are lots of client computers which have a console application listening on a port via socket listener. Clients open web application with their
IE9 browsers and when they click on a link, the web page sends requests like that:
"https://localhost:portNumber/applicationName/doSomething"
"https://computerName:portNumber/applicationName/doSomething"
"https://ipAddress:portNumber/applicationName/doSomething"
The second and third requests are made to console applications of other users' computers.
The problem is that if requests come with localhost, console application does not have a problem about reading incoming data and sending response back. But
if the request comes with computer name or ip address then browser shows certification warning and wants user to click on
"Continue to this web site (not recommended)" link.
We thought creating three different certificates via code.
But even using sslstream with three of them is possible we cannot decide to select true certification because we make authenticatiton first and then receive data. So when we catch incoming request the authentication must already be done.
Another way is forcing socket listener or sslstream to behave all these three requests as if they are localhost. So for each one authentication will be made as localhost. But I could not find an actual way for that.
Here is the code. I give the code because maybe there is some wrong usage of SslStream.
using System;
using System.Net.Sockets;
using System.Net;
using System.Configuration;
using System.Security.Cryptography.X509Certificates;
using System.Windows.Forms;
using System.IO;
using System.Net.Security;
using System.Security.Authentication;
using System.Threading;
using System.Text;
namespace StackOverFlowProject
{
class StackOverFlowSample
{
private static ManualResetEvent _manualResetEvent = new ManualResetEvent(false);
private static X509Certificate _cert = null;
static void Main(string[] args)
{
StackOverFlowSample stackOverFlowSample = new StackOverFlowSample();
stackOverFlowSample.StartListening();
}
private void StartListening()
{
GetCertificate();
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 1234);
if (localEndPoint != null)
{
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
if (listener != null)
{
listener.Bind(localEndPoint);
listener.Listen(10);
Console.WriteLine("Socket listener is running. Waiting for requests...");
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
}
}
}
private static void GetCertificate()
{
byte[] pfxData = File.ReadAllBytes(Application.StartupPath + #"\" + "localhost.pfx");
_cert = new X509Certificate2(pfxData, "password", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
}
private void AcceptCallback(IAsyncResult result)
{
Socket listener = null;
Socket handler = null;
StateObject state = null;
SslStream sslStream = null;
_manualResetEvent.Set();
listener = (Socket)result.AsyncState;
handler = listener.EndAccept(result);
state = new StateObject();
if (handler.RemoteEndPoint != null)
{
state.clientIP = ((IPEndPoint)handler.RemoteEndPoint).Address.ToString();
}
sslStream = new SslStream(new NetworkStream(handler, true));
sslStream.AuthenticateAsServer(_cert, false, SslProtocols.Tls, true);
sslStream.ReadTimeout = 100000;
sslStream.WriteTimeout = 100000;
state.workStream = sslStream;
if (state.workStream.IsAuthenticated)
{
state.workStream.BeginRead(state.buffer, 0, StateObject.BufferSize, ReceiveCallback, state);
}
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
}
private void ReceiveCallback(IAsyncResult result)
{
StateObject stateObject = null;
SslStream sslStreamReader = null;
byte[] byteData = null;
stateObject = (StateObject)result.AsyncState;
sslStreamReader = stateObject.workStream;
int byteCount = sslStreamReader.EndRead(result);
Decoder decoder = Encoding.UTF8.GetDecoder();
char[] chars = new char[decoder.GetCharCount(stateObject.buffer, 0, byteCount)];
decoder.GetChars(stateObject.buffer, 0, byteCount, chars, 0);
stateObject.sb.Append(chars);
if (byteCount > 0)
{
stateObject.totalReceivedBytes += byteCount;
string[] lines = stateObject.sb.ToString().Split('\n');
if (lines[lines.Length - 1] != "<EOF>")
{
// We didn't receive all data. Continue reading...
sslStreamReader.BeginRead(stateObject.buffer, 0, stateObject.buffer.Length, new AsyncCallback(ReceiveCallback), stateObject);
}
else
{
Console.WriteLine("We received all data. Sending response...");
byteData = Encoding.UTF8.GetBytes("Hello! I received your request!");
string httpHeaders = "HTTP/1.1" + "\r\n"
+ "Cache-Control: no-cache" + "\r\n"
+ "Access-Control-Allow-Origin: *" + "\r\n"
+ "\r\n";
byte[] byteHttpHeaders = Encoding.UTF8.GetBytes(httpHeaders);
byte[] concat = new byte[byteHttpHeaders.Length + byteData.Length];
Buffer.BlockCopy(byteHttpHeaders, 0, concat, 0, byteHttpHeaders.Length);
Buffer.BlockCopy(byteData, 0, concat, byteHttpHeaders.Length, byteData.Length);
stateObject.sslStreamReader = sslStreamReader;
sslStreamReader.BeginWrite(concat, 0, concat.Length, new AsyncCallback(SendCallback), stateObject);
}
}
}
private void SendCallback(IAsyncResult ar)
{
SslStream sslStreamSender = null;
StateObject stateObject = (StateObject)ar.AsyncState;
sslStreamSender = stateObject.sslStreamReader;
sslStreamSender.EndWrite(ar);
Console.WriteLine(stateObject.totalReceivedBytes.ToString() + " bytes sent to " + stateObject.clientIP + " address");
sslStreamSender.Close();
sslStreamSender.Dispose();
}
}
public class StateObject
{
public SslStream workStream = null;
public SslStream sslStreamReader = null;
public const int BufferSize = 1024;
public byte[] buffer = new byte[BufferSize];
public StringBuilder sb = new StringBuilder();
public string clientIP = "";
public int totalReceivedBytes = 0;
}
}
Your security guy is right. The way you are trying to make this happen wont work with SSL.
If you have a certificate, it is set to authenticate one CN. So, for an oversimplified example. Google has a certificate. It authenticates https://*.google.com. This means that any requests to google.com come up as having a valid certificate. And your browser is happy.
Now open a command prompt, ping google.com. Grab the ip address (in my case it came up as 216.58.210.14). Enter https://216.58.210.14. Your browser complains that the site is insecure etc. The reason being that the server may be the same one that served your earlier request, but the way you are getting to it is not valid according to the certificate,as the CN is not google.com, but an IP address.
So if you have a service which needs to connect to (for eg) 127.0.0.1, 10.92.1.4 AND myserver.com, you will need a cert which is valid for each case.
The certificate warning that you are encountering is really a name mismatch error, which indicates that the common name (domain name) in the SSL certificate does not match the URL/address used to access the web site/server.
https://www.sslshopper.com/ssl-certificate-name-mismatch-error.html
In your usage scenario, you may want to transition away from localhost and ip addresses in favor of a simple domain model that leverages the computer name. (e.g. computerName.someDomain.com)
Then, you could obtain a wildcard certificate (e.g. *.someDomain.com) which could be used to authenticate inter-process communication.
https://www.sslshopper.com/best-ssl-wildcard-certificate.html
I am not sure what your "https://computerName:portNumber/applicationName/doSomething" means. So not sure if you are using the certificate right or whether the paths/connection that you are accessing or using in code are correct. https://technet.microsoft.com/en-us/library/dd891009.aspx
It can access any protocol not restricted to TCP. https://technet.microsoft.com/en-us/library/cc784450(v=ws.10).aspx
Wildcard SSL Certificates allow admins to secure an unlimited number of subdomains on the same domain with a single SSL Certificate. A WildCard SSL Certificate is issued to *.yourdomain.com giving cost savings benefits from having to purchase numerous SSL Certificates for each subdomain, and also only require the use of one IP address.
Typical SSL Certificates only secure one Fully Qualified Domain Name. Unified Communications certificates allow you to assign multiple host names—known as Subject Alternative Names or SANs—in one certificate. For total flexibility, a Multi-Domain SSL Certificate allows the use of the Subject Alternative Name (SAN) field so you can secure up to 100 different domain names, sub-domains, or public IP addresses using a single SSL Certificate and requiring just one IP address.
** The value must match exactly with the hostname or domain name you access. Otherwise you will still receive browser certificate errors after the certificate has been imported and trusted. Eg: If you were previously using http://101.10.10.1:9000/ to access the site and the common name of your new certificate is "mydomain", then the shortcut should be updated to http://mydomain:9000/ ; if you created a certificate for mydomain:9000. Second, Use the hostname or CNAME by which you will address the server. This is very important. If your web server’s real hostname is mysubdomain.mydomain.com but people will be using www.mydomain.com to address the box, then use the latter name to answer the “Common Name” (CNAME) question.
** Check if you are able to connect using the openssl s_time -connect remote.host:443 (use specific ssl commands to troubleshoot, I am citing openssl) or the openssl s_time -connect remote.host:443 -www /test.html -new
** If you don’t have an SSL-enabled web server available for your use, you can emulate one using the s_server option.
# on one host, set up the server (using default port 4433)
openssl s_server -cert mycerti.pem -www
# on second host (or even the same one), run s_time
openssl s_time -connect mydomain:9001 -www / -new -ssl3
or
# on second host (or even the same one), run s_time
openssl s_time -connect mydomain:9001 -www / -new -ssl3
** Check if cert is in use?
$ openssl s_client -connect [ip_or_dns_name]:[port]
$ man s_client
Solution I am proposing is having assumption:
site is hosted on IIS
you can access application by machine name across network without any issue.
you need not to access webapp on internet(that will need cetificate from certified authority).
Try:
Create self signed certificate by IIS like :
i. Open IIS, select Server certificates like:
ii. Create self signed certificate like:
iii. configure website to use that certificate like:
select website, click bindings.
click edit bindings for https
iv. Edit site binding to use certificate you have created like :
Now you can access you application with machine name.
Same process you can repeat for domain certificates for internet but that requires certificate registered/provided by some certified authority.
Please note that now use can access application with Machine Name on both local & on network. Since certificate are issued for single host name/co-domain so use machine name instead of localhost on local machine too.

MongoDB C# SSL Client Certificate

I am trying to establish a secure connection to MongoDB with the C# driver using certificate validation, but I am getting this error:
Unable to connect to server localhost:27017: Unable to read data from the transport connection: An established connection was aborted by the software in your host machine..
Heres the error from MongoDB:
[initandlisten] connection accepted from 127.0.0.1:26163 #2 (1 connection now open)
[conn2] ERROR: no SSL certificate provided by peer; connection rejected
[conn2] SocketException handling request, closing client connection: 9001 socket exception [CONNECT_ERROR]
When I connect to MongoDB through the mongo shell with the certificate it works.
var connectionString = "mongodb://localhost";
var clientSettings = MongoClientSettings.FromUrl(new MongoUrl(connectionString));
clientSettings.SslSettings = new SslSettings();
clientSettings.UseSsl = true;
clientSettings.SslSettings.ClientCertificates = new List<X509Certificate>()
{
new X509Certificate("cert.pem")
};
clientSettings.SslSettings.EnabledSslProtocols = SslProtocols.Default;
clientSettings.SslSettings.ClientCertificateSelectionCallback =
(sender, host, certificates, certificate, issuers) => clientSettings.SslSettings.ClientCertificates.ToList()[0];
clientSettings.SslSettings.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
var client = new MongoClient(clientSettings);
Does anyone know how to get this working?
Realize this is out of date but for the benefit of others...
If you're not handling cert revocation lists, you need to turn that setting off since it is enabled by default.
clientSettings.SslSettings.CheckCertificateRevocation = false;
Next, the X509Certificate2 you provide to the driver must include the private key. .NET doesn't seem to pick up private keys in pem files, so you need to provide certificate in .pfx format and include the passphrase.
To create a pfx file in openssl:
openssl pkcs12 -export -in mycert.cer -inkey mycert.key -out mycert.pfx
OpenSSL will prompt you for the export passphrase, use that when creating your X509Certificate2 object:
X509Certificate2 cert = new X509Certificate2("mycert.pfx","mypassphrase");
//struggled a lot to figure out this
using MongoDB.Bson;
using MongoDB.Driver;
namespace Mongo_AWS
{
internal class Program
{
private static void Main(string[] args)
{
//Mention cert file in connection string itself or put at your executable location
string connectionString = #"mongodb://user:pwd#localhost:9999/?ssl=true&ssl_ca_certs=C:\Users\sivaram\Downloads\my.pem";
MongoClientSettings settings = MongoClientSettings.FromUrl(new MongoUrl(connectionString));
//Disable certificate verification, if it is not issued for you
settings.VerifySslCertificate = false;
MongoClient client = new MongoClient(settings);
IMongoDatabase database = client.GetDatabase("test");
IMongoCollection<BsonDocument> collection = database.GetCollection<BsonDocument>("numbers");
System.Collections.Generic.List<BsonDocument> temp = collection.Find(new BsonDocument()).ToList();
BsonDocument docToInsert = new BsonDocument { { "sivaram-Pi", 3.14159 } };
collection.InsertOne(docToInsert);
}
}
}
,ssl_ca_certs = #"/path/my.pem", added this in connection string.
settings.VerifySslCertificate = false;
Use the above line if you are testing it from local/you have root certificate but not issued to your machine, may be issued to your production host.
Put the root certificate in the absolute path and refer that path directly in connection string. Mongo driver will take care of reading private key and all. No need to put it in the certificate store or somewhere.

which port(s) are used by DirectoryEntry?

My goal is to get the list of web site names from remote server. But I'm getting the exception:
The RPC server is unavailable.
Here is the code:
public List<string> GetWebSites(string serverIP)
{
List<string> names = new List<string>();
DirectoryEntry Services = new DirectoryEntry(string.Format("IIS://{0}/W3SVC", serverIP));
Services.Username = "user name";
Services.Password = "password";
IEnumerator ie = Services.Children.GetEnumerator();
DirectoryEntry Server = null;
while (ie.MoveNext())
{
Server = (DirectoryEntry)ie.Current;
if (Server.SchemaClassName == "IIsWebServer")
{
names.Add(Server.Properties["ServerComment"][0].ToString());
}
}
return names;
}
this works fine, when firewall is turned off on the machine.
What I need to know is, which port(s) are used by DirectoryEntry?
or is there any other way to get web site names, without turning off firewall?
I believe LDAP protocol uses TCP no? Should be port 389 for non-ssl and 636 for SSL

Categories

Resources