summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Hudson <nick.hudson@isode.com>2012-03-08 10:16:55 (GMT)
committerKevin Smith <git@kismith.co.uk>2012-03-08 21:51:02 (GMT)
commitc5392b36c368ebdca2e8ab356eb0d1fb0d36a5cb (patch)
tree38c40c5661bce2b5655d91e6e7dadcc3b536fac5 /src/com/isode/stroke/tls/PKCS12Certificate.java
parent0470264fd4f9e7e73d1b655dc680e5ca7c10513c (diff)
downloadstroke-c5392b36c368ebdca2e8ab356eb0d1fb0d36a5cb.zip
stroke-c5392b36c368ebdca2e8ab356eb0d1fb0d36a5cb.tar.bz2
Implement "CertificateWithKey" and add support for setting client certificates
This change provides the functionality to allow clients to specify a PKCS#12 file containing client certificate/key for use when starting TLS sessions. The PKCS12Certificate class now subclasses "CertificateWithKey" (matching the Swiften implementation). Swiften also has "CAPICertificate", which is another subclass of CertificateWithKey. This has not been provided in this patch. From a client's point of view, all that's necessary to specify a certificate to be used for TLS is to do something like CertificateWithKey myCert = new PKCS12Certificate( "/home/fred/myp12file.p12", "secret".toCharArray()); coreClient.setCertificate(myCert); before calling "CoreClient.connect". Matching the Swiften functionality, constructing a new PKCS12Certificate does not actually perform validation of the P12 file/passphrase; that takes place when the p12 file is used. There is limited scope for returning to the caller errors describing possible problems, but JSSEContext uses the "emitError" method which does maintain error information, which is available in a debugger, or from the JSSEContext.toString() method. Test-information: Set up an M-Link server with TLS verified that - when I specify a client certificate with suitable SAN, the client sends it and the server reports authentication using the certificate - when I specify a client certificate without a suitable SAN, the client sends it but the server rejects it
Diffstat (limited to 'src/com/isode/stroke/tls/PKCS12Certificate.java')
-rw-r--r--src/com/isode/stroke/tls/PKCS12Certificate.java79
1 files changed, 73 insertions, 6 deletions
diff --git a/src/com/isode/stroke/tls/PKCS12Certificate.java b/src/com/isode/stroke/tls/PKCS12Certificate.java
index 0a45f94..06b6b91 100644
--- a/src/com/isode/stroke/tls/PKCS12Certificate.java
+++ b/src/com/isode/stroke/tls/PKCS12Certificate.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 Isode Limited, London, England.
+ * Copyright (c) 2011-2012 Isode Limited, London, England.
* All rights reserved.
*/
/*
@@ -9,20 +9,52 @@
package com.isode.stroke.tls;
import com.isode.stroke.base.ByteArray;
+import com.isode.stroke.base.NotNull;
-public class PKCS12Certificate {
+public class PKCS12Certificate extends CertificateWithKey {
public PKCS12Certificate() {
}
- public PKCS12Certificate(String filename, String password) {
- password_ = password;
+ /**
+ * Construct a new object.
+ * @param filename the name of the P12 file, must not be null.
+ * @param password the password for the P12 file. Must not be null,
+ * but may be empty if no password is to be used.
+ */
+ public PKCS12Certificate(String filename, char[] password) {
+
+ NotNull.exceptIfNull(filename,"filename");
+ NotNull.exceptIfNull(password,"password");
+ filename_ = filename;
+ password_ = new char[password.length];
+ System.arraycopy(password,0,password_,0,password.length);
+ data_ = new ByteArray();
data_.readFromFile(filename);
}
public boolean isNull() {
return data_.isEmpty();
}
+
+ public boolean isPrivateKeyExportable() {
+ /////Hopefully a PKCS12 is never missing a private key
+ return true;
+ }
+
+ /**
+ * This returns the name of the P12 file.
+ * @return the P12 filename, never null.
+ */
+ public String getCertStoreName() {
+ return filename_;
+ }
+
+ public String getCertName() {
+ /* TODO */
+ return null;
+ }
+
public ByteArray getData() {
return data_;
@@ -32,9 +64,44 @@ public class PKCS12Certificate {
data_ = data;
}
- public String getPassword() {
+ /**
+ * Returns a reference to the password in this object. If {@link #reset()}
+ * has been called, then the method will return an empty array.
+ * @return the password for this object.
+ */
+ public char[] getPassword() {
return password_;
}
+ @Override
+ public String toString() {
+ return "PKCS12Certificate based on file " + filename_;
+ }
+
+ /**
+ * This method may be used once the PKCS12Certificate is no longer
+ * required, and will attempt to clear the memory containing the
+ * password in this object. After calling this method, you should
+ * not expect this object to be usable for subsequent authentication.
+ *
+ * <p>Note that this operation does <em>NOT</em> guarantee that all traces
+ * of the password will have been removed from memory.
+ */
+ public void reset() {
+ if (password_ != null) {
+ for (int i=0; i<password_.length; i++) {
+ password_[i] = 'x';
+ }
+ }
+ password_ = new char[] {};
+
+ }
+
+ @Override
+ protected void finalize() {
+ reset();
+ }
+
private ByteArray data_;
- private String password_;
+ private char[] password_;
+ private String filename_;
}