/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.guacamole.auth.cas.conf;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.IOException;
import java.lang.IllegalArgumentException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import org.apache.guacamole.properties.GuacamoleProperty;
import org.apache.guacamole.GuacamoleServerException;
import org.apache.guacamole.environment.Environment;
import org.apache.guacamole.environment.LocalEnvironment;

/**
 * A GuacamoleProperty whose value is derived from a private key file.
 */
public abstract class PrivateKeyGuacamoleProperty implements GuacamoleProperty<PrivateKey>  {

    @Override
    public PrivateKey parseValue(String value) throws GuacamoleServerException {

        if (value == null || value.isEmpty())
            return null;

        try {

            // Open and read the file specified in the configuration.
            File keyFile = new File(value);
            FileInputStream keyStreamIn = new FileInputStream(keyFile);
            ByteArrayOutputStream keyStreamOut = new ByteArrayOutputStream();
            byte[] keyBuffer = new byte[1024];

            for (int readBytes; (readBytes = keyStreamIn.read(keyBuffer)) != -1;)
                keyStreamOut.write(keyBuffer, 0, readBytes);

            final byte[] keyBytes = keyStreamOut.toByteArray();

            // Set up decryption infrastructure
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            KeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            return keyFactory.generatePrivate(keySpec);

        }
        catch (FileNotFoundException e) {
            throw new GuacamoleServerException("Could not find the specified key file.", e);
        }
        catch (IOException e) {
            throw new GuacamoleServerException("Could not read in the specified key file.", e);
        }
        catch (NoSuchAlgorithmException e) {
            throw new GuacamoleServerException("RSA algorithm is not available.", e);
        }
        catch (InvalidKeySpecException e) {
            throw new GuacamoleServerException("Key is not in expected PKCS8 encoding.", e);
        }

    }

}

@@ -1941,15 +1941,82 @@
     
-try %7B%0A%0A
+FileInputStream keyStreamIn = null;%0A%0A        try %7B%0A            try %7B%0A%0A    
     
@@ -2089,24 +2089,28 @@
             
+    
 File keyFile
@@ -2137,39 +2137,27 @@
             
-FileInputStream
+   
  keyStreamIn
@@ -2201,16 +2201,20 @@
         
+ 
+   
 ByteArra
@@ -2283,16 +2283,20 @@
         
+    
 byte%5B%5D k
@@ -2335,16 +2335,20 @@
         
+ 
+   
 for (int
@@ -2409,16 +2409,20 @@
 != -1;)%0A
+    
         
@@ -2487,16 +2487,20 @@
         
+    
 final by
@@ -2540,24 +2540,28 @@
 teArray();%0A%0A
+    
             
@@ -2608,16 +2608,20 @@
         
+    
 KeyFacto
@@ -2679,16 +2679,20 @@
         
+   
+ 
 KeySpec 
@@ -2744,24 +2744,28 @@
             
+    
 return keyFa
@@ -2797,34 +2797,42 @@
 Spec);%0A%0A        
+   
+ 
 %7D%0A
+    
         catch (F
@@ -2861,32 +2861,36 @@
 ) %7B%0A            
+  
+  
 throw new Guacam
@@ -2954,34 +2954,42 @@
 .%22, e);%0A        
-%7D%0A
+    %7D%0A    
         catch (I
@@ -2987,18 +2987,31 @@
  catch (
-IO
+NoSuchAlgorithm
 Exceptio
@@ -3009,32 +3009,36 @@
 mException e) %7B%0A
+    
             thro
@@ -3073,46 +3073,36 @@
 on(%22
-Could not read in the specified key fi
+RSA algorithm is not availab
 le.%22
@@ -3107,34 +3107,42 @@
 .%22, e);%0A        
-%7D%0A
+    %7D%0A    
         catch (N
@@ -3136,39 +3136,38 @@
      catch (
-NoSuchAlgorithm
+InvalidKeySpec
 Exception e)
@@ -3161,32 +3161,36 @@
 cException e) %7B%0A
+    
             thro
@@ -3225,46 +3225,53 @@
 on(%22
-RSA algorithm is not available
+Key is not in expected PKCS8 encoding
 .%22, e);%0A
     
@@ -3258,32 +3258,36 @@
 encoding.%22, e);%0A
+    
         %7D%0A      
@@ -3288,37 +3288,153 @@
         
-catch (InvalidKeySpec
+    finally %7B%0A                if (keyStreamIn != null)%0A                    keyStreamIn.close();%0A            %7D%0A        %7D%0A        catch (IO
 Exceptio
@@ -3492,45 +3492,48 @@
 on(%22
-Key is not in expected PKCS8 encoding
+Could not read in the specified key file
 .%22, 
@@ -3546,17 +3546,16 @@
       %7D%0A
-%0A
     %7D%0A%0A%7D

Merge changes addressing InputStream leak when reading CAS ClearPass private key.