There is an ongoing discussion on the security and trust working group for NHIN Direct regarding the IP-to-domain mapping problem that is created with traditional SSL. If an HISP (as defined by NHIN Direct) wants to host thousands of NHIN Direct "Health Domains" for providers, then it will an "artificially inflated cost" to have to purchase an IP for each of those domains.
Because Apache and OpenSSL have recently released TLS with support for the SNI extension, it is possible to use SNI as a solution to this problem on the server side. However, if we decide that we will allow server implementations of the NHINDirect transport layer to support TLS+SNI, then we must require that all clients support SNI too. OpenSSL based clients should do this by default and one could always us stunnel to implement an TLS+SNI aware client to proxy if your given programming language SSL implementation does not support SNI. It appears that native Java applications using OpenJDK do not yet support SNI, but I cannot get a straight answer out of that project. I know that there are OpenSSL Java libraries available but I have no idea if that would be considered viable.
Can you give me a "state of the art" summary of where TLS+SNI support is for Java clients? I need a Java implementers perspective on this.
JavaSE 7 has SNI Support in JSSE.
http://docs.oracle.com/javase/7/docs/technotes/guides/security/enhancements-7.html
Note, there seems to be a problem with it, as you can read here:
SSL handshake alert: unrecognized_name error since upgrade to Java 1.7.0
it is also possible to patch with some lines the orig Sun JDK (bootclasspath) to get Server SNI working.
Class: sun.security.ssl.ServerHandshaker
Add Field
/** Use for SNI */
private ServerNameExtension serverNameExtension = null;
Patch Method clientHello (add these lines)
/* Use for SNI */
this.serverNameExtension = (ServerNameExtension)mesg.extensions.get(ExtensionType.EXT_SERVER_NAME);
Patch Method setupPrivateKeyAndChain (change)
if (this.conn != null) { alias = km.chooseServerAlias(algorithm , null, this.conn);
} else { alias = km.chooseEngineServerAlias(algorithm, null, this.engine); }
to
final Principal[] principals = (this.serverNameExtension == null) ? null : this.serverNameExtension.getHostnamePrincipals();
if (this.conn != null) { alias = km.chooseServerAlias(algorithm , principals, this.conn);
} else { alias = km.chooseEngineServerAlias(algorithm, principals, this.engine); }
Add to Class sun.security.ssl.ServerNameExtension
static final class ServerNamePrincipal implements Principal {
private final String name;
ServerNamePrincipal(final String name) { this.name = name; }
#Override public String getName() { return this.name; }
#Override public String toString() { return this.name; }
}
public Principal[] getHostnamePrincipals() {
final List<Principal> principals = new LinkedList<>();
for(final ServerName name : this.names) {
if(name.type == NAME_HOST_NAME) { principals.add(new ServerNamePrincipal(name.hostname)); }
}
return principals.toArray(new Principal[principals.size()]);
}
I'm working on the same project as ftrotter.
Note the requirement of support for thousands of domains. I don't think that SANs are going to cut the mustard for two reasons. First, the size of the certificate is going to get enormous, which will likely cause performance problems at a minimum. Second, these domains are going to come and go frequently, particularly in the early days of NHIN Direct. The operational burden of having to update the certificate every time a domain comes or goes, is going to be unacceptable, IMHO.
At ftrotter's request, I did some googling around on the subject of java, TLS and SNI, and other ways to implement what amounts to a named-based virtual hosting situation, with one certificate per virtual host. Here's what I've come up with:
JSSE (Java Secure Socket Extension) supports TLS, and has "partial support" for TLS+SNI. I have no idea what partial support means in this context. The commentary I'm seeing indicates that the support that exists is not adequate for doing named-based virtual hosts, which is basically what we need.
I've found one article that claims the JDK7 version of JSSE will support TLS+SNI (dated 11/20/2008), and I've found one that claims it won't (dated 2/27/2009). Neither is particularly authoritative.
Some of the folks working on OpenJDK 7 discussed the issues around adding SNI support to JSSE back in Feb-Mar 2009, including posting a source patch. (thread starts here:
http://www.mail-archive.com/security-dev#openjdk.java.net/msg00612.html). OpenJDK7 isn't going to be released any time before about September 2010. I have no idea when the Java 7 platform will be released.
There is nothing substantive on java.sun.com at all, so I really don't know what Sun's plans are at all.
There is apparently a different way to accomplish name-based virtual hosts which is apparently widely compatible, using a single certificate per hosting server which contains multiple common names and multiple subject alt names. See http://wiki.cacert.org/VhostTaskForce and Serve different certs for same Tomcat application via connectors?
This approach would create really large certificates (due to all those CNs and SANs) if you have lots of virtual hosts. One of the folks at NHIN Direct's recent face-to-face meeting was talking about wanting to support thousands of virtual hosts. My guess is that this will break a lot of implementations. In addition, having to update the certificate each time you add or remove a virtual host sounds like a ridiculous operational burden.
In summary, the current Java state of the art for name-based virtual hosting with separate certificates per virtual host appears to be "no can do". In addition, it's not clear when or if it will be added.
Does anyone agree or disagree? Does anyone know if the OpenJDK project has any intention of "backporting" SNI support for Java 6?
Related
I'd like to use WebSocket with Java. Problem is, my server is separated from the client by a proxy that cannot be configured. I've been searching for implementations of WebSocket with fallbacks such as long-polling. I've found socket.io but don't know how the fallback works.
Under which case does it replace WebSocket and how?
Are there other libraries like socket.io with fallbacks implementations? I would like to find one in Java, but I only found Jetty.
EDIT: does the fallback only depend on the browser's compatibility with WebSocket? What if the cause of failure is a proxy badly configured, is socket.io going to detect it as a compatibilty failure and thus switch to long-polling (or another technique)?
Answer: since v1, socket.io includes engine.io, which brings the following features:
Socket.io is one of several implementations for the websockets protocol and its main selling point (IMO) is its ease of use: you don't need to code keep-alive mechanisms or decide which transport is best, it does it for you.
So, to make it clear, socket.io doesn't replace the websocket protocol, it's a package that implements it for you.
You mentioned long-polling. That is one of the transports used by socket.io. Long Polling is HTTP based and it's basically request --> wait --> response and the wait isn't very long, as it can be dropped by load balancers on EOF or stale connections. Nevertheless, it's still useful when the websockets protocol (TCP based) isn't available and socket.io automatically re-establishes the connection for you. Notice that websockets is a relatively new protocol, ratified in 2011, so older browsers don't support it. Well, socket.io detects that and then resorts to long polling, so you don't have to "worry" about it.
A websocket connection starts with HTTP, listening on the same port. For example, http://localhost:8080 (just a silly example). Then, when it's possible, socket.io switches to ws://localhost:8080 for you.
I never had problems with network topology challenges when using socket.io, as when the HTTP port is available and using long polling / websockets is possible, it just worked for me.
One of the libraries with fallback implementation, as you mentioned, is netty-socket.io. Notice how it configures the two transports:
public class Configuration {
private ExceptionListener exceptionListener = new DefaultExceptionListener();
private String context = "/socket.io";
private List<Transport> transports = Arrays.asList(Transport.WEBSOCKET, Transport.POLLING);
private int bossThreads = 0; // 0 = current_processors_amount * 2
private int workerThreads = 0; // 0 = current_processors_amount * 2
The complete code can be found here.
Node JS has also libraries for websockets, and I mention it here just to clarify that long polling and websockets aren't the only two available transports (might be the only ones in Java):
io.set('transports', [ // enable all transports (optional if you want flashsocket)
'websocket'
, 'flashsocket'
, 'htmlfile'
, 'xhr-polling'
, 'jsonp-polling'
]);
In a nutshell, socket.io attempts to make things as easy as possible for you, including not having to worry about what transports to use, as it's done under the hood for you, yet still configurable if you want.
I hope this brief explanation helps you!
Below are the bindings of implementation of java.rmi.registry.Registry
CustomRegistry: registryCount = 2
reg1.com:11, # of bindings = 2
OPTIONS
UPDATES
reg2.com:11, # of bindings = 1
TEST
When I use
(MyRegistry)registry.lookup("OPTIONS");
I receive exception: java.rmi.NotBoundException: OPTIONS
After reading explanations of this exception on this site then it appears the binding "OPTIONS" is not discoverable.
As the RMI servers are on a different machine is there a mechanism I can use to discover the bindings available on servers reg1.com % reg2.com
After reading explanations of this exception on this site then it appears the binding "OPTIONS" is not discoverable.
No it doesn't. It means it isn't bound.
As the RMI servers are on a different machine
Irrelevant.
is there a mechanism I can use to discover the bindings available on servers reg1.com % reg2.com
Registry.list(). Any string returned by Registry.list() can be plugged directly into Registry.lookup() to return the binding, unless it was unbound in between, which isn't likely.
Similarly any string returned by Naming.list() can be plugged into Naming.lookup().
But you can't mix them up, e.g. passing a string returned by Registry.list() to Naming.lookup(), because Naming deals in RMI URLs where Registry just deals in names.
I would like to forward emails from my Lotus Notes inbox to my gmail account.
Lotus Notes rules and agents are disabled on our server, so I developed external application for that.
I am using document.send method and mail successfully arrives to my gmail box.
The only problem is that often the email also duplicated in my Lotus Notes inbox.
I just found that the reason of that is "CC" and "BCC" fields, which I don't clean up,
however, I am looking for the way to forward email as it is - which means keep original CC and BCC and TO fields - exactly on the same way as it is done by forwarding agent.
I am using "IBM Notes 9" on Windows 7 64 bit.
I've prepared a code sample that demonstrates what I am doing.
package com.example;
import lotus.domino.*;
public class TestMailForwarder {
public static void main(String[] args) throws NotesException {
NotesThread.sinitThread();
try {
Session notesSession = NotesFactory.createSession(
(String) null, (String) null, Consts.NOTES_PASSWORD);
DbDirectory dir = notesSession.getDbDirectory(Consts.NOTES_SERVER);
Database mailDb = dir.openDatabaseByReplicaID(Consts.MAILDB_REPLICA_ID);
forwardAllEmails(mailDb);
} finally {
NotesThread.stermThread();
}
}
private static void forwardAllEmails(Database mailDb) throws NotesException {
View inbox = mailDb.getView("$Inbox");
//noinspection LoopStatementThatDoesntLoop
for (Document document = inbox.getFirstDocument();
null != document;
document = inbox.getNextDocument(document)) {
document.send(Consts.GMAIL_ADDRESS);
break;
}
}
}
Instead of trying to send the messages to your GMail, why not upload them using Gmail's IMAP interface. You would require to get the message as MIME content - which probably they are already for external incoming eMails and then push them to GMail.
I don't have a ready code sample, just one for the opposite pulling GMail into Notes, but you should be able to use that as a starting point.
A code sample for the MIME conversion is in an IBM Technote.
Hope that helps
You can't do a transparent forward with code running at the client level. Pure SMTP systems do it by preserving the RFC-822 header content while altering the RFC-821 RCPT TO data. Domino does not give client-level code independent control over these. It just uses the SendTo, CopyTo, and BlindCopyTo items. (There are some tricks that mail management and archiving vendors play in order to do things like this, but they require special changes to the Domino server's router configuration, and software on the other end as well.
Another way of accomplishing this (in response to the question you asked in your comment) would be to have your Java code make a direct connection to the gmail SMTP servers. I'm not sure how easy it is. A comment on this question states that the Java Mail API allows you to control the RCPT TO separately from the RFC822 headers, but I've not looked into the specifics other than taking note that there's an SMTPTransport class -- which is where I'd look for anything related to RFC-821 protocol. The bigger issue is that you will have to take control of converting messages into MIME format. With Notes mail, you may have a mix of Notes rich text and MIME. Theres a convertToMIME method in Notes 8.5.1 and above, but this will only convert the message body. You'll have to deal with any header content separately. (I'm not really up to speed on Notes 9, but AFAIK even though there is functionality in the client to create a .EML file when you drag a message to the desktop, there's no API there to do that for you.)
Finally, I've found a ready solution: AWESYNC.MAIL.
It is a commercial software but it does exactly what I need.
I'm using Java BouncyCastle so-called "lightweight" API to establish a TLS connection over a TCP socket.
I want to verify server-provided certificate chain being signed by one of trusted CAs. Sounds like a reasonably common task that every sane TLS client implementation out there does by default, so I expect this should be simple.
For a sake of simplifying the question, I don't ask about verifying anything other than the sign/trust chain, like matching hostname or checking expiration date. Such checks seem trivial to implement.
If I understand the documentation correctly, there's a TlsAuthentication interface, that users are supposed to implement. The sole provided implementation is LegacyTlsAuthentication, which adapts upon now-deprecated CertificateVerifyer interface, which has only AlwaysValidVerifyer implementation (that's just dummy "return true;" under the hood).
So, this is what I have for now:
DefaultTlsClient tlsClient = new DefaultTlsClient() {
#Override
public TlsAuthentication getAuthentication() throws IOException {
TlsAuthentication auth = new TlsAuthentication() {
#Override
public void notifyServerCertificate(Certificate serverCertificate) {
// Here I should validate certificate chain, but this far
// I only managed to print subjects for debugging purposes.
for (org.bouncycastle.asn1.x509.Certificate c : serverCertificate.getCerts()) {
System.out.println("Certificate: " + c.getSubject().toString());
}
}
#Override
public TlsCredentials getClientCredentials(CertificateRequest cr) throws IOException {
return null;
}
};
return auth;
}
};
socket = new Socket(hostname, port);
tlsHandler = new TlsProtocolHandler(socket.getInputStream(), socket.getOutputStream());
tlsHandler.connect(tlsClient);
However, I fail to understand or find any existing example that would check one org.bouncycastle.asn1.x509.Certificate for being correctly signed by another one. Could someone provide some pointers to me, please?
I'm using BounceCastle's proprietary API due to need to use ciphersuites that default Java installations do not allow due to being subject to US cryptographic policy jurisdiction restrictions. For example, AES256 encryption requires installing unlimited strength policy files, and I'd really like to avoid additional end-user installation steps, if possible.
The isSignatureValid method of the X509CertificateHolder class should work for you. This method takes in 1 parameter, a ContentVerifierProvider. You can create an X509CertificateHolder by passing a Certificate into the constructor.
The following code is taken from BC's version 2 API page and should give you a good idea in how to implement this in your solution.
ContentVerifierProvider contentVerifierProvider =
new BcRSAContentVerifierProviderBuilder(
new DefaultDigestAlgorithmIdentifierFinder()).build(lwPubKey);
if (!certHolder.isSignatureValid(contentVerifierProvider))
{
System.err.println("signature invalid");
}
"lwPubKey" is the public key of the signer. So depending on how long your certificate chain is, you would repeatedly call this method starting with the end entity certificate and going up the line to the self-signed root certificate.
Wow what a bunch of deprecated classes. I feel for ya.
Where you need to get to is
http://www.cs.berkeley.edu/~jonah/bc/org/bouncycastle/asn1/x509/KeyUsage.html#keyCertSign
The keyCertSign will be set for a CA issues cert.
You code above serverCertificate.getCerts() will return an array of X509CertificateStructure objects (your chain) for each of these you can call toASN1Object() to get the interface DerEncodable / KeyUsage
I hope this helps.
Is there a relatively simple way in Java to check if a domain is available or not?
I need a reliable method, so only checking if the connection can be made is not enough.
Domain availability depends on having a whois client. Here is a link to an implementation of a whois client in Java:
Java Whois Client
You'll need to parse the results - and depending on what whois server you use, you may (will) have varying formats that are returned. The best thing to do is to pay for a commercial whois/registration service such as OpenSRS. They have an extensive API which you can use as a registered reseller. Here are the API docs:
http://opensrs.com/resources/documentation/opensrs_xmlapi.pdf
HTH,
-aj
There's a good Whois Java client here:
https://github.com/ethauvin/Whois
You can run it from the command line or interface with it directly:
// don't include the www
Whois.main(new String[] {"skytouch.com"});
Another solution is to use Apache Commons lib. Simplified example:
import org.apache.commons.net.whois.WhoisClient;
public String getWhois(String domainName){
WhoisClient whois = new WhoisClient();
whois.setConnectTimeout(10000);
whois.setDefaultTimeout(10000);
whois.connect("whois.verisign-grs.com", 43);
String domainWhois = whois.query(domainName);
whois.disconnect();
return domainWhois;
}
Check if response equals "no match". Whois servers, timeout length and no availability response differ according to extension so you should have prepared additional collections for them.
Whois servers list can be found:
http://www.mit.edu/afs/athena/contrib/potluck/Net-Services/whois-servers.list
https://raw.githubusercontent.com/whois-server-list/whois-server-list/master/whois-server-list.xml
http://www.nirsoft.net/whois_servers_list.html
If you try to make your queries concurrent, you will definitely get whois response "You have reached configured rate limit." or explicit exception in a code so you should repeat queries after some sleep.
Performing a DNS lookup on the domain is the easiest solution. All available domains will have no DNS record, and most registrars assign a default DNS entry upon registration.
WHOIS lookups will be your most reliable solution, particularly behind an ISP that spoofs their own server (with a "domain not found" page filled with ads) for any missing domain name.