server: better handling of crypt error
authorNiki Roo <niki@nikiroo.be>
Mon, 22 Apr 2019 19:11:34 +0000 (21:11 +0200)
committerNiki Roo <niki@nikiroo.be>
Mon, 22 Apr 2019 19:11:34 +0000 (21:11 +0200)
src/be/nikiroo/utils/CryptUtils.java
src/be/nikiroo/utils/serial/server/ConnectAction.java

index ea6892babd0a8c355c8182c364655e7493ea3ac0..d5413d7c392f6856405b3b25e0fcab989ff4de68 100644 (file)
@@ -1,6 +1,7 @@
 package be.nikiroo.utils;
 
 import java.io.IOException;
+import java.io.UnsupportedEncodingException;
 import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
 
@@ -10,6 +11,7 @@ import javax.crypto.IllegalBlockSizeException;
 import javax.crypto.NoSuchPaddingException;
 import javax.crypto.SecretKey;
 import javax.crypto.spec.SecretKeySpec;
+import javax.net.ssl.SSLException;
 
 /**
  * Small utility class to do AES encryption/decryption.
@@ -104,17 +106,17 @@ public class CryptUtils {
         * 
         * @return the encrypted data
         * 
-        * @throws IOException
+        * @throws SSLException
         *             in case of I/O error (i.e., the data is not what you assumed
         *             it was)
         */
-       public byte[] encrypt(byte[] data) throws IOException {
+       public byte[] encrypt(byte[] data) throws SSLException {
                try {
                        return ecipher.doFinal(data);
                } catch (IllegalBlockSizeException e) {
-                       throw new IOException(e);
+                       throw new SSLException(e);
                } catch (BadPaddingException e) {
-                       throw new IOException(e);
+                       throw new SSLException(e);
                }
        }
 
@@ -126,12 +128,18 @@ public class CryptUtils {
         * 
         * @return the encrypted data
         * 
-        * @throws IOException
+        * @throws SSLException
         *             in case of I/O error (i.e., the data is not what you assumed
         *             it was)
         */
-       public byte[] encrypt(String data) throws IOException {
-               return encrypt(data.getBytes("UTF8"));
+       public byte[] encrypt(String data) throws SSLException {
+               try {
+                       return encrypt(data.getBytes("UTF8"));
+               } catch (UnsupportedEncodingException e) {
+                       // UTF-8 is required in all confirm JVMs
+                       e.printStackTrace();
+                       return null;
+               }
        }
 
        /**
@@ -146,12 +154,18 @@ public class CryptUtils {
         * 
         * @return the encrypted data, encoded in Base64
         * 
-        * @throws IOException
+        * @throws SSLException
         *             in case of I/O error (i.e., the data is not what you assumed
         *             it was)
         */
-       public String encrypt64(String data, boolean zip) throws IOException {
-               return encrypt64(data.getBytes("UTF8"), zip);
+       public String encrypt64(String data, boolean zip) throws SSLException {
+               try {
+                       return encrypt64(data.getBytes("UTF8"), zip);
+               } catch (UnsupportedEncodingException e) {
+                       // UTF-8 is required in all confirm JVMs
+                       e.printStackTrace();
+                       return null;
+               }
        }
 
        /**
@@ -166,12 +180,18 @@ public class CryptUtils {
         * 
         * @return the encrypted data, encoded in Base64
         * 
-        * @throws IOException
+        * @throws SSLException
         *             in case of I/O error (i.e., the data is not what you assumed
         *             it was)
         */
-       public String encrypt64(byte[] data, boolean zip) throws IOException {
-               return StringUtils.base64(encrypt(data), zip);
+       public String encrypt64(byte[] data, boolean zip) throws SSLException {
+               try {
+                       return StringUtils.base64(encrypt(data), zip);
+               } catch (IOException e) {
+                       // not exactly true, but we consider here that this error is a crypt
+                       // error, not a normal I/O error
+                       throw new SSLException(e);
+               }
        }
 
        /**
@@ -182,16 +202,16 @@ public class CryptUtils {
         * 
         * @return the original, decoded data
         * 
-        * @throws IOException
+        * @throws SSLException
         *             in case of I/O error
         */
-       public byte[] decrypt(byte[] data) throws IOException {
+       public byte[] decrypt(byte[] data) throws SSLException {
                try {
                        return dcipher.doFinal(data);
                } catch (IllegalBlockSizeException e) {
-                       throw new IOException(e);
+                       throw new SSLException(e);
                } catch (BadPaddingException e) {
-                       throw new IOException(e);
+                       throw new SSLException(e);
                }
        }
 
@@ -207,11 +227,17 @@ public class CryptUtils {
         * 
         * @return the original, decoded data
         * 
-        * @throws IOException
+        * @throws SSLException
         *             in case of I/O error
         */
-       public byte[] decrypt64(String data, boolean zip) throws IOException {
-               return decrypt(StringUtils.unbase64(data, zip));
+       public byte[] decrypt64(String data, boolean zip) throws SSLException {
+               try {
+                       return decrypt(StringUtils.unbase64(data, zip));
+               } catch (IOException e) {
+                       // not exactly true, but we consider here that this error is a crypt
+                       // error, not a normal I/O error
+                       throw new SSLException(e);
+               }
        }
 
        /**
@@ -227,11 +253,21 @@ public class CryptUtils {
         * 
         * @return the original, decoded data
         * 
-        * @throws IOException
+        * @throws SSLException
         *             in case of I/O error
         */
-       public String decrypt64s(String data, boolean zip) throws IOException {
-               return new String(decrypt(StringUtils.unbase64(data, zip)), "UTF-8");
+       public String decrypt64s(String data, boolean zip) throws SSLException {
+               try {
+                       return new String(decrypt(StringUtils.unbase64(data, zip)), "UTF-8");
+               } catch (UnsupportedEncodingException e) {
+                       // UTF-8 is required in all confirm JVMs
+                       e.printStackTrace();
+                       return null;
+               } catch (IOException e) {
+                       // not exactly true, but we consider here that this error is a crypt
+                       // error, not a normal I/O error
+                       throw new SSLException(e);
+               }
        }
 
        /**
index 7d724248384d77a5ba459f4215a1aeebf80e7a13..be987083c5e54e3db1228f563b4ba1bf322a8918 100644 (file)
@@ -6,6 +6,8 @@ import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
 import java.net.Socket;
 
+import javax.net.ssl.SSLException;
+
 import be.nikiroo.utils.CryptUtils;
 import be.nikiroo.utils.Version;
 import be.nikiroo.utils.serial.Exporter;
@@ -66,7 +68,8 @@ abstract class ConnectAction {
         * Handler called when an unexpected error occurs in the code.
         * 
         * @param e
-        *            the exception that occurred
+        *            the exception that occurred, SSLException usually denotes a
+        *            crypt error
         */
        abstract protected void onError(Exception e);
 
@@ -139,7 +142,14 @@ abstract class ConnectAction {
                                out = new OutputStreamWriter(s.getOutputStream(), "UTF-8");
                                try {
                                        if (server) {
-                                               String line = readLine(in);
+                                               String line;
+                                               try {
+                                                       line = readLine(in);
+                                               } catch (SSLException e) {
+                                                       out.write("Unauthorized\n");
+                                                       throw e;
+                                               }
+
                                                if (line != null && line.startsWith("VERSION ")) {
                                                        // "VERSION client-version" (VERSION 1.0.0)
                                                        Version clientVersion = new Version(
@@ -263,6 +273,8 @@ abstract class ConnectAction {
         * 
         * @throws IOException
         *             in case of I/O error
+        * @throws SSLException
+        *             in case of crypt error
         */
        protected String sendString(String line) throws IOException {
                synchronized (lock) {
@@ -291,6 +303,8 @@ abstract class ConnectAction {
         * 
         * @throws IOException
         *             in case of I/O error
+        * @throws SSLException
+        *             in case of crypt error
         */
        protected String recString() throws IOException {
                synchronized (lock) {
@@ -307,6 +321,19 @@ abstract class ConnectAction {
                }
        }
 
+       /**
+        * Read a possibly encrypted line.
+        * 
+        * @param in
+        *            the stream to read from
+        * @return the unencrypted line
+        * 
+        * 
+        * @throws IOException
+        *             in case of I/O error
+        * @throws SSLException
+        *             in case of crypt error
+        */
        private String readLine(BufferedReader in) throws IOException {
                String line = in.readLine();
                if (line != null) {
@@ -319,6 +346,18 @@ abstract class ConnectAction {
                return line;
        }
 
+       /**
+        * Write a line, possible encrypted.
+        * 
+        * @param out
+        *            the stream to write to
+        * @param line
+        *            the line to write
+        * @throws IOException
+        *             in case of I/O error
+        * @throws SSLException
+        *             in case of crypt error
+        */
        private void writeLine(OutputStreamWriter out, String line)
                        throws IOException {
                if (crypt == null) {