Repository: nifi
Updated Branches:
  refs/heads/master df1066d2e -> c7f770422


NIFI-888 EncryptContent for PGP Leaks File Handles.

Closes InputStreams created to read the public keys for PGP encryption and 
several other
streams involved in PGP encryptiong. This prevents NiFi from leaking file 
handles on
every validate call or encryption attempt in the EncryptContent processor.


Project: http://git-wip-us.apache.org/repos/asf/nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/b30fbe1f
Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/b30fbe1f
Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/b30fbe1f

Branch: refs/heads/master
Commit: b30fbe1f3bb2996e048112482cae51c9deedfd20
Parents: df1066d
Author: Alan Jackoway <[email protected]>
Authored: Fri Aug 21 16:45:30 2015 -0400
Committer: Aldrin Piri <[email protected]>
Committed: Sun Aug 23 23:07:26 2015 -0400

----------------------------------------------------------------------
 .../standard/util/OpenPGPKeyBasedEncryptor.java | 251 +++++++++++--------
 1 file changed, 143 insertions(+), 108 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi/blob/b30fbe1f/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/util/OpenPGPKeyBasedEncryptor.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/util/OpenPGPKeyBasedEncryptor.java
 
b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/util/OpenPGPKeyBasedEncryptor.java
index 60e3bf8..2e7834e 100644
--- 
a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/util/OpenPGPKeyBasedEncryptor.java
+++ 
b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/util/OpenPGPKeyBasedEncryptor.java
@@ -85,49 +85,61 @@ public class OpenPGPKeyBasedEncryptor implements Encryptor {
     /*
      * Validate secret keyring passphrase
      */
-    public static boolean validateKeyring(String provider, String 
secretKeyringFile, char[] passphrase) throws IOException,
+    public static boolean validateKeyring(String provider,
+            String secretKeyringFile, char[] passphrase) throws IOException,
             PGPException, NoSuchProviderException {
-        PGPSecretKeyRingCollection pgpsec = new 
PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(Files.newInputStream(Paths
-                .get(secretKeyringFile))));
-        Iterator ringit = pgpsec.getKeyRings();
-        while (ringit.hasNext()) {
-            PGPSecretKeyRing secretkeyring = (PGPSecretKeyRing) ringit.next();
-            PGPSecretKey secretkey = secretkeyring.getSecretKey();
-            secretkey.extractPrivateKey(passphrase, provider);
-            return true;
+        try (InputStream fin = Files.newInputStream(Paths
+                .get(secretKeyringFile))) {
+            try (InputStream pin = PGPUtil.getDecoderStream(fin)) {
+                PGPSecretKeyRingCollection pgpsec = new 
PGPSecretKeyRingCollection(
+                        pin);
+                Iterator ringit = pgpsec.getKeyRings();
+                while (ringit.hasNext()) {
+                    PGPSecretKeyRing secretkeyring = (PGPSecretKeyRing) ringit
+                            .next();
+                    PGPSecretKey secretkey = secretkeyring.getSecretKey();
+                    secretkey.extractPrivateKey(passphrase, provider);
+                    return true;
+                }
+                return false;
+            }
         }
-        return false;
     }
 
     /*
      * Get the public key for a specific user id from a keyring.
      */
     @SuppressWarnings("rawtypes")
-    public static PGPPublicKey getPublicKey(String userId, String 
publicKeyring) throws IOException, PGPException {
+    public static PGPPublicKey getPublicKey(String userId, String 
publicKeyring)
+            throws IOException, PGPException {
         PGPPublicKey pubkey = null;
-        PGPPublicKeyRingCollection pgppub = new
-                
PGPPublicKeyRingCollection(PGPUtil.getDecoderStream(Files.newInputStream(Paths.get(publicKeyring))));
-
-        Iterator ringit = pgppub.getKeyRings();
-        while (ringit.hasNext()) {
-            PGPPublicKeyRing kring = (PGPPublicKeyRing) ringit.next();
-
-            Iterator keyit = kring.getPublicKeys();
-            while (keyit.hasNext()) {
-                pubkey = (PGPPublicKey) keyit.next();
-                boolean userIdMatch = false;
-
-                Iterator userit = pubkey.getUserIDs();
-                while (userit.hasNext()) {
-                    String id = userit.next().toString();
-                    if (id.contains(userId)) {
-                        userIdMatch = true;
-                        break;
+        try (InputStream fin = Files.newInputStream(Paths.get(publicKeyring))) 
{
+            try (InputStream pin = PGPUtil.getDecoderStream(fin)) {
+                PGPPublicKeyRingCollection pgppub = new 
PGPPublicKeyRingCollection(
+                        pin);
+
+                Iterator ringit = pgppub.getKeyRings();
+                while (ringit.hasNext()) {
+                    PGPPublicKeyRing kring = (PGPPublicKeyRing) ringit.next();
+
+                    Iterator keyit = kring.getPublicKeys();
+                    while (keyit.hasNext()) {
+                        pubkey = (PGPPublicKey) keyit.next();
+                        boolean userIdMatch = false;
+
+                        Iterator userit = pubkey.getUserIDs();
+                        while (userit.hasNext()) {
+                            String id = userit.next().toString();
+                            if (id.contains(userId)) {
+                                userIdMatch = true;
+                                break;
+                            }
+                        }
+                        if (pubkey.isEncryptionKey() && userIdMatch) {
+                            return pubkey;
+                        }
                     }
                 }
-                if (pubkey.isEncryptionKey() && userIdMatch) {
-                    return pubkey;
-                }
             }
         }
         return null;
@@ -139,75 +151,88 @@ public class OpenPGPKeyBasedEncryptor implements 
Encryptor {
         private String secretKeyring;
         private char[] passphrase;
 
-        OpenPGPDecryptCallback(final String provider, final String keyring, 
final char[] passphrase) {
+        OpenPGPDecryptCallback(final String provider, final String keyring,
+                final char[] passphrase) {
             this.provider = provider;
             this.secretKeyring = keyring;
             this.passphrase = passphrase;
         }
 
         @Override
-        public void process(InputStream in, OutputStream out) throws 
IOException {
-            InputStream pgpin = PGPUtil.getDecoderStream(in);
-            PGPObjectFactory pgpFactory = new PGPObjectFactory(pgpin);
+        public void process(InputStream in, OutputStream out)
+                throws IOException {
+            try (InputStream pgpin = PGPUtil.getDecoderStream(in)) {
+                PGPObjectFactory pgpFactory = new PGPObjectFactory(pgpin);
 
-            Object obj = pgpFactory.nextObject();
-            if (!(obj instanceof PGPEncryptedDataList)) {
-                obj = pgpFactory.nextObject();
+                Object obj = pgpFactory.nextObject();
                 if (!(obj instanceof PGPEncryptedDataList)) {
-                    throw new ProcessException("Invalid OpenPGP data");
-                }
-            }
-            PGPEncryptedDataList encList = (PGPEncryptedDataList) obj;
-
-            PGPSecretKeyRingCollection pgpSecretKeyring;
-            try {
-                // open secret keyring file
-                pgpSecretKeyring = new 
PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(Files
-                        .newInputStream(Paths.get(secretKeyring))));
-            } catch (Exception e) {
-                throw new ProcessException("Invalid secret keyring - " + 
e.getMessage());
-            }
-
-            try {
-                PGPPrivateKey privateKey = null;
-                PGPPublicKeyEncryptedData encData = null;
-
-                // find the secret key in the encrypted data
-                Iterator it = encList.getEncryptedDataObjects();
-                while (privateKey == null && it.hasNext()) {
-                    obj = it.next();
-                    if (!(obj instanceof PGPPublicKeyEncryptedData)) {
+                    obj = pgpFactory.nextObject();
+                    if (!(obj instanceof PGPEncryptedDataList)) {
                         throw new ProcessException("Invalid OpenPGP data");
                     }
-                    encData = (PGPPublicKeyEncryptedData) obj;
-                    PGPSecretKey secretkey = 
pgpSecretKeyring.getSecretKey(encData.getKeyID());
-                    if (secretkey != null) {
-                        privateKey = secretkey.extractPrivateKey(passphrase, 
provider);
-                    }
                 }
-                if (privateKey == null) {
-                    throw new ProcessException("Secret keyring does not 
contain the key required to decrypt");
+                PGPEncryptedDataList encList = (PGPEncryptedDataList) obj;
+
+                PGPSecretKeyRingCollection pgpSecretKeyring;
+                try {
+                    // open secret keyring file
+                    pgpSecretKeyring = new PGPSecretKeyRingCollection(
+                            PGPUtil.getDecoderStream(Files.newInputStream(Paths
+                                    .get(secretKeyring))));
+                } catch (Exception e) {
+                    throw new ProcessException("Invalid secret keyring - "
+                            + e.getMessage());
                 }
 
-                InputStream clearData = encData.getDataStream(privateKey, 
provider);
-                PGPObjectFactory clearFactory = new 
PGPObjectFactory(clearData);
-
-                obj = clearFactory.nextObject();
-                if (obj instanceof PGPCompressedData) {
-                    PGPCompressedData compData = (PGPCompressedData) obj;
-                    clearFactory = new 
PGPObjectFactory(compData.getDataStream());
-                    obj = clearFactory.nextObject();
-                }
-                PGPLiteralData literal = (PGPLiteralData) obj;
+                try {
+                    PGPPrivateKey privateKey = null;
+                    PGPPublicKeyEncryptedData encData = null;
+
+                    // find the secret key in the encrypted data
+                    Iterator it = encList.getEncryptedDataObjects();
+                    while (privateKey == null && it.hasNext()) {
+                        obj = it.next();
+                        if (!(obj instanceof PGPPublicKeyEncryptedData)) {
+                            throw new ProcessException("Invalid OpenPGP data");
+                        }
+                        encData = (PGPPublicKeyEncryptedData) obj;
+                        PGPSecretKey secretkey = pgpSecretKeyring
+                                .getSecretKey(encData.getKeyID());
+                        if (secretkey != null) {
+                            privateKey = secretkey.extractPrivateKey(
+                                    passphrase, provider);
+                        }
+                    }
+                    if (privateKey == null) {
+                        throw new ProcessException(
+                                "Secret keyring does not contain the key 
required to decrypt");
+                    }
 
-                InputStream lis = literal.getInputStream();
-                final byte[] buffer = new byte[4096];
-                int len;
-                while ((len = lis.read(buffer)) >= 0) {
-                    out.write(buffer, 0, len);
+                    try (InputStream clearData = encData.getDataStream(
+                            privateKey, provider)) {
+                        PGPObjectFactory clearFactory = new PGPObjectFactory(
+                                clearData);
+
+                        obj = clearFactory.nextObject();
+                        if (obj instanceof PGPCompressedData) {
+                            PGPCompressedData compData = (PGPCompressedData) 
obj;
+                            clearFactory = new PGPObjectFactory(
+                                    compData.getDataStream());
+                            obj = clearFactory.nextObject();
+                        }
+                        PGPLiteralData literal = (PGPLiteralData) obj;
+
+                        try (InputStream lis = literal.getInputStream()) {
+                            final byte[] buffer = new byte[4096];
+                            int len;
+                            while ((len = lis.read(buffer)) >= 0) {
+                                out.write(buffer, 0, len);
+                            }
+                        }
+                    }
+                } catch (Exception e) {
+                    throw new ProcessException(e.getMessage());
                 }
-            } catch (Exception e) {
-                throw new ProcessException(e.getMessage());
             }
         }
 
@@ -231,43 +256,53 @@ public class OpenPGPKeyBasedEncryptor implements 
Encryptor {
         }
 
         @Override
-        public void process(InputStream in, OutputStream out) throws 
IOException {
+        public void process(InputStream in, OutputStream out)
+                throws IOException {
             PGPPublicKey publicKey;
             try {
                 publicKey = getPublicKey(userId, publicKeyring);
             } catch (Exception e) {
-                throw new ProcessException("Invalid public keyring - " + 
e.getMessage());
+                throw new ProcessException("Invalid public keyring - "
+                        + e.getMessage());
             }
 
             try {
-                SecureRandom secureRandom = 
SecureRandom.getInstance(SECURE_RANDOM_ALGORITHM);
+                SecureRandom secureRandom = SecureRandom
+                        .getInstance(SECURE_RANDOM_ALGORITHM);
 
                 OutputStream output = out;
                 if (EncryptContent.isPGPArmoredAlgorithm(algorithm)) {
                     output = new ArmoredOutputStream(out);
                 }
 
-                PGPEncryptedDataGenerator encGenerator = new 
PGPEncryptedDataGenerator(PGPEncryptedData.CAST5, false,
-                        secureRandom, provider);
+                PGPEncryptedDataGenerator encGenerator = new 
PGPEncryptedDataGenerator(
+                        PGPEncryptedData.CAST5, false, secureRandom, provider);
                 encGenerator.addMethod(publicKey);
-                OutputStream encOut = encGenerator.open(output, new 
byte[65536]);
-
-                PGPCompressedDataGenerator compData = new 
PGPCompressedDataGenerator(PGPCompressedData.ZIP, Deflater.BEST_SPEED);
-                OutputStream compOut = compData.open(encOut, new byte[65536]);
-
-                PGPLiteralDataGenerator literal = new 
PGPLiteralDataGenerator();
-                OutputStream literalOut = literal.open(compOut, 
PGPLiteralData.BINARY, filename, new Date(), new byte[65536]);
-
-                final byte[] buffer = new byte[4096];
-                int len;
-                while ((len = in.read(buffer)) >= 0) {
-                    literalOut.write(buffer, 0, len);
+                try (OutputStream encOut = encGenerator.open(output,
+                        new byte[65536])) {
+
+                    PGPCompressedDataGenerator compData = new 
PGPCompressedDataGenerator(
+                            PGPCompressedData.ZIP, Deflater.BEST_SPEED);
+                    try (OutputStream compOut = compData.open(encOut,
+                            new byte[65536])) {
+
+                        PGPLiteralDataGenerator literal = new 
PGPLiteralDataGenerator();
+                        try (OutputStream literalOut = literal.open(compOut,
+                                PGPLiteralData.BINARY, filename, new Date(),
+                                new byte[65536])) {
+
+                            final byte[] buffer = new byte[4096];
+                            int len;
+                            while ((len = in.read(buffer)) >= 0) {
+                                literalOut.write(buffer, 0, len);
+                            }
+
+                        }
+                    }
+                }
+                if (EncryptContent.isPGPArmoredAlgorithm(algorithm)) {
+                    output.close();
                 }
-
-                literalOut.close();
-                compOut.close();
-                encOut.close();
-                output.close();
             } catch (Exception e) {
                 throw new ProcessException(e.getMessage());
             }

Reply via email to