I am finding difficulty while setting up Riak Kv Cluster setup using java client.
Can anybody tell how we do that??
Achually i tried with below code to use riak security in cluster but i am getting error of SSLEngine Problem, can anybody tell how we resolve this issues.
Below is java Code for Refference
InputStream inputStream = null;
KeyStore ks = null;
try {
// inputStream = new FileInputStream("/ssl_dir/cacertfile.pem");
inputStream = new FileInputStream("/home/shahzad/Desktop/amit/rootCA.pem");
// Generate an X509Certificate from the InputStream
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
X509Certificate caCert = (X509Certificate) certFactory.generateCertificate(inputStream);
inputStream.close();
// Generate a KeyStore object
ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, "password".toCharArray());
ks.setCertificateEntry("cacert", caCert);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (RiakConfig.class) {
List<RiakNode> riakNodeList = new ArrayList<RiakNode>();
for (final String riakServer : riakServerArray) {
RiakNode node = new RiakNode.Builder()
.withMinConnections(10)
.withMinConnections(50)
.withRemoteAddress(riakServer.split(":")[0])
.withRemotePort(
Integer.parseInt(riakServer.split(":")[1]))
.withAuth("shahzad", "shahzad", ks)
.build();
riakNodeList.add(node);
}
// This cluster object takes our one node as an argument
cluster = new RiakCluster.Builder(riakNodeList).build();
// The cluster must be started to work, otherwise you will see
// errors
cluster.start();
}
Tell one thing..... how we access security enable Riak KV remotely.
Please check, if you enable security at Riak KV cluster and added client source
riak-admin security add-source all <<127.0.0.1/32>> trust
The IP address belongs to the client machine from where the connection will originate
Related
I am trying to implement the certificate authentication in .net core API(Server/target) and this API will be invoked in to another API(Client) .Here is the piece of code of client api which makes request to server/target api.But I'm facing an error on the server/target api .I'm running these two services from local and both certificates have already installed
Client side controller logic
[HttpGet]
public async Task<List<WeatherForecast>> Get()
{
List<WeatherForecast> weatherForecastList = new List<WeatherForecast>();
X509Certificate2 clientCert = Authentication.GetClientCertificate();
if (clientCert == null)
{
HttpActionContext actionContext = null;
actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden)
{
ReasonPhrase = "Client Certificate Required"
};
}
HttpClientHandler requestHandler = new HttpClientHandler();
requestHandler.ClientCertificates.Add(clientCert);
requestHandler.ServerCertificateCustomValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
HttpClient client = new HttpClient(requestHandler)
{
BaseAddress = new Uri("https://localhost:11111/ServerAPI")
};
client.DefaultRequestHeaders
.Accept
.Add(new MediaTypeWithQualityHeaderValue("application/xml"));//ACCEPT head
using (var httpClient = new HttpClient())
{
//httpClient.DefaultRequestHeaders.Accept.Clear();
var request = new HttpRequestMessage()
{
RequestUri = new Uri("https://localhost:44386/ServerAPI"),
Method = HttpMethod.Get,
};
request.Headers.Add("X-ARR-ClientCert", clientCert.GetRawCertDataString());
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));//ACCEPT head
//using (var response = await httpClient.GetAsync("https://localhost:11111/ServerAPI"))
using (var response = await httpClient.SendAsync(request))
{
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string apiResposne = await response.Content.ReadAsStringAsync();
weatherForecastList = JsonConvert.DeserializeObject<List<WeatherForecast>>(apiResposne);
}
}
}
return weatherForecastList;
}
authentication class
public static X509Certificate2 GetClientCertificate()
{
X509Store userCaStore = new X509Store(StoreName.TrustedPeople, StoreLocation.CurrentUser);
try
{
string str_API_Cert_Thumbprint = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
userCaStore.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certificatesInStore = userCaStore.Certificates;
X509Certificate2Collection findResult = certificatesInStore.Find(X509FindType.FindByThumbprint, str_API_Cert_Thumbprint, false);
X509Certificate2 clientCertificate = null;
if (findResult.Count == 1)
{
clientCertificate = findResult[0];
if(System.DateTime.Today >= System.Convert.ToDateTime(clientCertificate.GetExpirationDateString()))
{
throw new Exception("Certificate has already been expired.");
}
else if (System.Convert.ToDateTime(clientCertificate.GetExpirationDateString()).AddDays(-30) <= System.DateTime.Today)
{
throw new Exception("Certificate is about to expire in 30 days.");
}
}
else
{
throw new Exception("Unable to locate the correct client certificate.");
}
return clientCertificate;
}
catch (Exception ex)
{
throw;
}
finally
{
userCaStore.Close();
}
}
Server/target api code
[HttpGet]
public IEnumerable<WeatherForecast> Getcertdata()
{
IHeaderDictionary headers = base.Request.Headers;
X509Certificate2 clientCertificate = null;
string certHeaderString = headers["X-ARR-ClientCert"];
if (!string.IsNullOrEmpty(certHeaderString))
{
//byte[] bytes = Encoding.ASCII.GetBytes(certHeaderString);
//byte[] bytes = Convert.FromBase64String(certHeaderString);
//clientCertificate = new X509Certificate2(bytes);
clientCertificate = new X509Certificate2(WebUtility.UrlDecode(certHeaderString));
var serverCertificate = new X509Certificate2(Path.Combine("abc.pfx"), "pwd");
if (clientCertificate.Thumbprint == serverCertificate.Thumbprint)
{
//Valida Cert
}
}
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
}).ToArray();
//return new List<WeatherForecast>();
}
You have much more problems here, the code is significantly flawed and insecure in various ways. Let's explain each issue:
HttpClient in using clause in client side controller logic
Although you expect to wrap anything that implements IDisposable in using statement. However, it is not really the case with HttpClient. Connections are not closed immediately. And with every request to client controller action, a new connection is established to remote endpoint, while previous connections sit in TIME_WAIT state. Under certain constant load, your HttpClient will exhaust TCP port pool (which is limited) and any new attempt to create a new connection will throw an exception. Here are more details on this problem: You're using HttpClient wrong and it is destabilizing your software
Microsoft recommendation is to re-use existing connections. One way to do this is to Use IHttpClientFactory to implement resilient HTTP requests. Microsoft article talks a bit about this problem:
Though this class implements IDisposable, declaring and instantiating
it within a using statement is not preferred because when the
HttpClient object gets disposed of, the underlying socket is not
immediately released, which can lead to a socket exhaustion problem.
BTW, you have created a client variable, but do not use it in any way.
Ignore certificate validation problems
The line:
requestHandler.ServerCertificateCustomValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
make you vulnerable to MITM attack.
you are doing client certificate authentication wrong
The line:
request.Headers.Add("X-ARR-ClientCert", clientCert.GetRawCertDataString());
It is not the proper way how to do client cert authentication. What you literally doing is passing certificate's public part to server. That's all. You do not prove private key possession which is required to authenticate you. The proper way to do so is:
requestHandler.ClientCertificates.Add(clientCert);
This will force client and server to perform proper client authentication and check if you possess the private key for certificate you pass (it is done in TLS handshake automatically). If you have ASP.NET on server side, then you read it this way (in controller action):
X509Certificate2 clientCert = Request.HttpContext.Connection.ClientCertificate
if (clientCert == null) {
return Unauthorized();
}
// perform client cert validation according server-side rules.
Non-standard cert store
In authentication class you open StoreName.TrustedPeople store, while normally it should be StoreName.My. TrustedPeople isn't designed to store certs with private key. It isn't a functional problem, but it is bad practice.
unnecessary try/catch clause in authentication class
If you purposely throw exceptions in method, do not use try/catch. In your case you simply rethrow exception, thus you are doing a double work. And this:
throw new Exception("Certificate is about to expire in 30 days.");
is behind me. Throwing exception on technically valid certificate? Really?
server side code
As said, all this:
IHeaderDictionary headers = base.Request.Headers;
X509Certificate2 clientCertificate = null;
string certHeaderString = headers["X-ARR-ClientCert"];
if (!string.IsNullOrEmpty(certHeaderString))
{
//byte[] bytes = Encoding.ASCII.GetBytes(certHeaderString);
//byte[] bytes = Convert.FromBase64String(certHeaderString);
//clientCertificate = new X509Certificate2(bytes);
clientCertificate = new X509Certificate2(WebUtility.UrlDecode(certHeaderString));
var serverCertificate = new X509Certificate2(Path.Combine("abc.pfx"), "pwd");
if (clientCertificate.Thumbprint == serverCertificate.Thumbprint)
{
//Valida Cert
}
}
must be replaced with:
X509Certificate2 clientCert = Request.HttpContext.Connection.ClientCertificate
if (clientCert == null) {
return Unauthorized();
}
// perform client cert validation according server-side rules.
BTW:
var serverCertificate = new X509Certificate2(Path.Combine("abc.pfx"), "pwd");
if (clientCertificate.Thumbprint == serverCertificate.Thumbprint)
{
//Valida Cert
}
This is another disaster in your code. You are loading the server certificate from PFX just to compare their thumbprints? So, you suppose that client will have a copy of server certificate? Client and server certificates must not be the same. Next thing is you are generating a lot of copies of server certificate's private key files. More private key files you generate, the slower the process is and you just generate a lot of garbage. More details on this you can find in my blog post: Handling X509KeyStorageFlags in applications
I need to fetch the certificate, and would like to fetch the client, and there is no server, I could do this form:
public static X509Certificate2 EscolherCertificado(string serial)
{
var store = new X509Store("MY", StoreLocation.CurrentUser);
var Key = new RSACryptoServiceProvider();
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection collection = store.Certificates;
X509Certificate2Collection fcollection = collection.Find(X509FindType.FindBySerialNumber, serial, false);
if (fcollection.Count == 1)
{
return fcollection[0];
}
else { cod = "00000"; msgm = "not found"; return null; }
}
But when I publish on the server it does not work. Is there any way I can do this?
I can not get the client certificate, it returns error, because on the server there are no registered certificates.
EDIT
I have already been told that it is possible, I just do not know how to do it, the ways I tried does not work.
EDIT
Following this link, I did comply, but it does not work, it does not always find. What can I do to correct this problem?
public static X509Certificate2 EscolherCertificado(string serial)
{
X509Store userCaStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
try
{
userCaStore.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certificatesInStore = userCaStore.Certificates;
X509Certificate2Collection findResult = certificatesInStore.Find(X509FindType.FindBySerialNumber, serial, true);
X509Certificate2 clientCertificate = null;
if (findResult.Count == 1)
{
clientCertificate = findResult[0];
}
else
{
throw new Exception("Unable to locate the correct client certificate.");
}
cod = "0000"; msgm = clientCertificate.ToString(); return clientCertificate;
}
catch
{
throw;
}
finally
{
userCaStore.Close();
}
As far as I know, you cannot reach the client Certificates Store.
To do that you have to code a propietary plugin for each browser platform and give the right access permissions to the client.
That's a very painful task.
I wish you good luck with it.
In my case we ended up developing an EXE which has full access to the client hardware and features of the platform.
Here's the code:
private void ElegirCert()
{
System.Security.Cryptography.X509Certificates.X509Store store = new System.Security.Cryptography.X509Certificates.X509Store("MY", System.Security.Cryptography.X509Certificates.StoreLocation.CurrentUser);
store.Open(System.Security.Cryptography.X509Certificates.OpenFlags.ReadOnly);
System.Security.Cryptography.X509Certificates.X509Certificate2Collection collection = (System.Security.Cryptography.X509Certificates.X509Certificate2Collection)store.Certificates;
System.Security.Cryptography.X509Certificates.X509Certificate2Collection fcollection = (System.Security.Cryptography.X509Certificates.X509Certificate2Collection)collection;//.Find(System.Security.Cryptography.X509Certificates.X509FindType.FindByTimeValid, DateTime.Now, false);
try
{
Cert = System.Security.Cryptography.X509Certificates.X509Certificate2UI.SelectFromCollection(fcollection, "Elegir", "Seleccione el certificado que desea utilizar", System.Security.Cryptography.X509Certificates.X509SelectionFlag.SingleSelection)[0];
}
catch (Exception e)
{
}
store.Close();
}
I still think that it is not possible to get the list of client certificates using the sole browser capabilities.
There is a way and it involves creating an extension which communicates with an Executable Native file that does the "hard work". That means, getting the full list of certificates and exposing it to the user.
I think that after that, the user chooses one, then the EXE asks for the cert store password (if it has one), then the exe digitally signs the hash and whatever...
Good day, dear collegues!
I'm trying to send email using SMTP-server, created by my collegue. I'm using .net core 2.0 this Identity.
When I run my application at debug-mode using my own computer -- it works perfectly.
When I run the same app on hosting it throws this exception:
SmtpCommandException: 149.xxx.xxx.xxx is my address
MailKit.Net.Smtp.SmtpClient.OnSenderNotAccepted(MimeMessage message, MailboxAddress mailbox, SmtpResponse response)
the hosting and the smtp-server have the same IP-address and work at the same computer.
I'm sure, that exception of form "149.xxx.xxx.xxx is my address" means, that smtp-server thinks, I'm spamer, trying to use its IP to be "whitelisted" -- and this server blocks me.
I've found this:
HELO is faked interface address
Type: forgery
Some spammers put the server's interface address they connect to in their HELO, maybe asuming it is whitelisted or something.
drop condition = ${if eq{[$interface_address]}{$sender_helo_name}}
message = $interface_address is my address
But the same hosting has many other web-applications, they don't have a problem with connection to the local server.
public async Task SendEmailAsync(string email, string subject, string message)
{
var emailMessage = new MimeMessage();
emailMessage.From.Add(new MailboxAddress("No reply", "XX#XXXX.XXX"));
emailMessage.To.Add(new MailboxAddress("", email));
emailMessage.Subject = subject;
emailMessage.Body = new TextPart(MimeKit.Text.TextFormat.Html)
{
Text = message
};
using (var client = new SmtpClient())
{
await client.ConnectAsync("localhost", 25, SecureSocketOptions.None);
await client.AuthenticateAsync("XX#XXXX.XXX", "Password");
await client.SendAsync(emailMessage);
await client.DisconnectAsync(true);
}
}
I tried to use its address instead of "localhost". But it throws the same exception.
What should I do? How to say a smtp-server that I'm not spamer, that I'm just physically situated on its IP-address, on the same computer?
Yes, now I've done it!
I needed to use direct connection to local mail server (without SMTP, this is very important).
How to implement direct connection? My web-server uses Linux Ubuntu system. So I needed to use the Shell (Ubuntu terminal).
Firstly I've tested it manually: when I type "sendmail" (command for direct usage of local mail server) it requires email of recipient.
And I needed to type in terminal:
$ sendmail xxx#mail.com
subject:My subject //this is new line
to:xxx#mail.com // this is new line
from:kkk#mydomain.com // this is new line
Here I can write many lines of my letter's body.
. // this is the point in new line (the only symbol) to show this is end of the letter. Next keyboard "enter" means to send finally.
To use these commands, I needed to create new process (the same as to give command "sendmail").
So, instead of this all:
var emailMessage = new MimeMessage();
emailMessage.From.Add(new MailboxAddress("No reply", "XX#XXXX.XXX"));
emailMessage.To.Add(new MailboxAddress("", email));
emailMessage.Subject = subject;
emailMessage.Body = new TextPart(MimeKit.Text.TextFormat.Html)
{
Text = message
};
using (var client = new SmtpClient())
{
await client.ConnectAsync("localhost", 25, SecureSocketOptions.None);
await client.AuthenticateAsync("XX#XXXX.XXX", "Password");
await client.SendAsync(emailMessage);
await client.DisconnectAsync(true);
}
I've just inserted
Process p = new Process();
ProcessStartInfo info = new ProcessStartInfo();
info.FileName = "sendmail";
info.Arguments = $"{email}";
info.RedirectStandardInput = true;
info.UseShellExecute = false;
info.CreateNoWindow = true;
p.StartInfo = info;
p.Start();
using (StreamWriter sw = p.StandardInput)
{
if (sw.BaseStream.CanWrite)
{
sw.WriteLine("from:kkk#mydomain.com");
sw.WriteLine($"to:{email}");
sw.WriteLine($"subject:{subject}");
sw.WriteLine(message);
sw.WriteLine(".");
}
}
p.WaitForExit();
I need to transfer file (xml) to AS2 server. I am not so good at this communication channel, but I need to do it programmatically. For example sending to SFTP I am using this code:
import com.jcraft.jsch.*;
.......
public void uploadViaSFTP (String fileToUpload, String sftp_host, String sftp_user, String sftp_psw)
{
int SFTPPORT = 22;
Session session = null;
Channel channel = null;
ChannelSftp channelSftp = null;
try{
JSch jsch = new JSch();
session = jsch.getSession(sftp_user,sftp_host,SFTPPORT);
session.setPassword(sftp_psw);
java.util.Properties config = new java.util.Properties();
//this line should be used only for testing, not for production
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
channel = session.openChannel("sftp");
channel.connect();
channelSftp = (ChannelSftp)channel;
channelSftp.cd("/");
File f = new File(fileToUpload);
channelSftp.put(new FileInputStream(f), f.getName());
}catch(Exception ex){
ex.printStackTrace();
}
}
But now I need to do same for AS2. What library I could use (openAS2)? Is there a simple method to transfer like it does for SFTP?
You should be able to use standard HTTPS components and S/MIME attachment, since AS2 is a security layer and usage specification on top of HTTP or HTTPS.
I'd start with (https://www.mkyong.com/java/java-https-client-httpsurlconnection-example/), the AS2 specification (http://www.ietf.org/rfc/rfc4130.txt) , and this example from github: (https://github.com/protocol7/smime-java-example)
I have written a java sftp application based on Jcraft.jsch running on solaris. Each time the application connects to remote host a duplicate entry is done in known_hosts file. Any help on how to stop this. The connection code is as below:
public boolean connect(Properties props) throws JSchException {
FileSystemOptions fso = new FileSystemOptions();
try {
SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(fso, "no");
session = SftpClientFactory.createConnection(host, port, login.toCharArray(), password.toCharArray(), fso);
Channel channel = session.openChannel("sftp");
channel.connect();
command = (ChannelSftp) channel;
} catch (FileSystemException e) { ...
Thanks