Reputation: 53
I'm trying to create a Java software that connects to a Netgear WAG102 (Access Point) which has to get the connection logs for my wifi network.
my software already works with other Netgear Access Points (WG302v2, for istance), but I can find no way to get it to work with the WAG102. I keep on receiving a
javax.net.ssl.SSLProtocolException: Extensions not allowed in v2 certificate
while trying to open a secure SSL connection to the AP.
additional info: the certificate sent from the AP expired 1 year ago, so I implemented the infamous "TrustAllCerts" trick, but that alone didn't seem to help.
Google chrome says that the certificate is version v4, but my java software keeps on saying it's version v2, giving then that exception when it checks for the certificate extensions (version v2 doesn't support extensions, as far as I know).
My question is: is there any way to make it work despite of this issue?
here is my code:
private HttpsURLConnection createConnection(URL url) throws IOException{
HttpsURLConnection con=(HttpsURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setDoOutput(true);
con.setRequestProperty("Authorization", "Basic " + "**********");
con.setHostnameVerifier(new HostnameVerifier(){public boolean verify(String hostname, SSLSession session){return true;}});
TrustManager[] trustAllCerts=null;
SSLContext sslContext=null;
SSLSocketFactory sslSocketFactory;
try{
trustAllCerts = new TrustManager[]{ new X509TrustManager(){
public X509Certificate[] getAcceptedIssuers(){return null;}
public void checkClientTrusted(X509Certificate[] chain, String authType){}
public void checkServerTrusted(X509Certificate[] chain, String authType){}
}};
sslContext = SSLContext.getInstance( "SSL" );
sslContext.init( null, trustAllCerts, new java.security.SecureRandom() );
sslSocketFactory = sslContext.getSocketFactory();
con.setSSLSocketFactory( sslSocketFactory );
System.out.println("Response Code : " + con.getResponseCode());
System.out.println("Cipher Suite : " + con.getCipherSuite());
Certificate[] certs = con.getServerCertificates();
for(Certificate cert : certs){
System.out.println("Cert ext : "+cert);
System.out.println("Cert Type : " + cert.getType());
System.out.println("Cert Hash Code : " + cert.hashCode());
System.out.println("Cert Public Key Algorithm : " + cert.getPublicKey().getAlgorithm());
System.out.println("Cert Public Key Format : " + cert.getPublicKey().getFormat());
System.out.println("\n");
}
} catch (Exception e){e.printStackTrace();}
//printHTTPSCert(con);
return con;
}
I'm getting the exception when calling con.getResponseCode()
, basically because it's when the connection is getting opened I think.
This program works correctly with www.google.com and all the other sites with a good certificate.
Upvotes: 2
Views: 4775
Reputation: 122719
There seem to be two issues here:
Firstly, there it shouldn't be a V4 certificate. It's possible to put this number in the version field, with custom made tools, but there's no specification that matches it. The latest X.509 specification only goes up to V3:
Version ::= INTEGER { v1(0), v2(1), v3(2) }
Secondly, the Java code that reads the certificate uses a !=
condition:
(version.compare(CertificateVersion.V3) != 0)
If it's not V3, it assumes that it's V2 (which makes sense if you consider there shouldn't be a V4). I presume other implementations might let this incorrect certificate through using a >=
condition instead.
The easiest would be to install a new, correct certificate on the router if possible. (According to your screenshot, it's also using an MD5 signature, which isn't recommended nowadays.)
EDIT: It also appears that this certificate was issued with a www.netgear.com
Subject Alternative Name (i.e. it's valid for that host name), which is non-sense on a router. You should really install your own certificate if you're deploying this, even if it's self-signed.
Anyway, there might be a workaround. It seems that the BouncyCastle implementation CertificateFactory
(used by the JSSE) is more flexible in terms of versions. If you use the BC provider in a position before the Sun providers, this should work. You can get the BC provider jar and use this (before making connections), for example:
Security.insertProviderAt(new BouncyCastleProvider(), 1);
Upvotes: 3