From 8883fd1c0efa08fe0a73a11a1c8986fa3ea72753 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Fri, 13 Sep 2019 09:02:58 +0200 Subject: refactor utils into a separate module --- eaaf_core/pom.xml | 20 +- .../idp/process/support/SecureRandomHolder.java | 61 ---- .../gv/egiz/eaaf/core/impl/utils/ArrayUtils.java | 44 --- .../egiz/eaaf/core/impl/utils/DataURLBuilder.java | 113 ------- .../at/gv/egiz/eaaf/core/impl/utils/FileUtils.java | 175 ---------- .../at/gv/egiz/eaaf/core/impl/utils/HTTPUtils.java | 178 ---------- .../eaaf/core/impl/utils/HttpClientFactory.java | 154 --------- .../eaaf/core/impl/utils/IHttpClientFactory.java | 21 -- .../egiz/eaaf/core/impl/utils/KeyStoreUtils.java | 199 ----------- .../egiz/eaaf/core/impl/utils/KeyValueUtils.java | 375 --------------------- .../eaaf/core/impl/utils/NodeIteratorAdapter.java | 113 ------- .../egiz/eaaf/core/impl/utils/NodeListAdapter.java | 70 ---- .../at/gv/egiz/eaaf/core/impl/utils/Random.java | 176 ---------- .../SecurePendingRequestIdGenerationStrategy.java | 214 ------------ .../gv/egiz/eaaf/core/impl/utils/ServletUtils.java | 43 --- .../SimplePendingRequestIdGenerationStrategy.java | 38 --- .../gv/egiz/eaaf/core/impl/utils/StreamUtils.java | 201 ----------- .../eaaf/core/impl/utils/TransactionIDUtils.java | 101 ------ .../at/gv/egiz/eaaf/core/impl/utils/X509Utils.java | 62 ---- eaaf_core_utils/pom.xml | 150 +++++++++ .../idp/process/support/SecureRandomHolder.java | 61 ++++ .../gv/egiz/eaaf/core/impl/utils/ArrayUtils.java | 44 +++ .../egiz/eaaf/core/impl/utils/DataURLBuilder.java | 113 +++++++ .../at/gv/egiz/eaaf/core/impl/utils/FileUtils.java | 175 ++++++++++ .../at/gv/egiz/eaaf/core/impl/utils/HTTPUtils.java | 178 ++++++++++ .../eaaf/core/impl/utils/HttpClientFactory.java | 152 +++++++++ .../eaaf/core/impl/utils/IHttpClientFactory.java | 21 ++ .../egiz/eaaf/core/impl/utils/KeyStoreUtils.java | 199 +++++++++++ .../egiz/eaaf/core/impl/utils/KeyValueUtils.java | 375 +++++++++++++++++++++ .../eaaf/core/impl/utils/NodeIteratorAdapter.java | 113 +++++++ .../egiz/eaaf/core/impl/utils/NodeListAdapter.java | 70 ++++ .../at/gv/egiz/eaaf/core/impl/utils/Random.java | 176 ++++++++++ .../SecurePendingRequestIdGenerationStrategy.java | 214 ++++++++++++ .../gv/egiz/eaaf/core/impl/utils/ServletUtils.java | 43 +++ .../SimplePendingRequestIdGenerationStrategy.java | 38 +++ .../gv/egiz/eaaf/core/impl/utils/StreamUtils.java | 201 +++++++++++ .../eaaf/core/impl/utils/TransactionIDUtils.java | 101 ++++++ .../at/gv/egiz/eaaf/core/impl/utils/X509Utils.java | 62 ++++ pom.xml | 17 +- 39 files changed, 2501 insertions(+), 2360 deletions(-) delete mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/support/SecureRandomHolder.java delete mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/ArrayUtils.java delete mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/DataURLBuilder.java delete mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/FileUtils.java delete mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HTTPUtils.java delete mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HttpClientFactory.java delete mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/IHttpClientFactory.java delete mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/KeyStoreUtils.java delete mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/KeyValueUtils.java delete mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/NodeIteratorAdapter.java delete mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/NodeListAdapter.java delete mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/Random.java delete mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SecurePendingRequestIdGenerationStrategy.java delete mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/ServletUtils.java delete mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SimplePendingRequestIdGenerationStrategy.java delete mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/StreamUtils.java delete mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/TransactionIDUtils.java delete mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/X509Utils.java create mode 100644 eaaf_core_utils/pom.xml create mode 100644 eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/support/SecureRandomHolder.java create mode 100644 eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/ArrayUtils.java create mode 100644 eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/DataURLBuilder.java create mode 100644 eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/FileUtils.java create mode 100644 eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HTTPUtils.java create mode 100644 eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HttpClientFactory.java create mode 100644 eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/IHttpClientFactory.java create mode 100644 eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/KeyStoreUtils.java create mode 100644 eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/KeyValueUtils.java create mode 100644 eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/NodeIteratorAdapter.java create mode 100644 eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/NodeListAdapter.java create mode 100644 eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/Random.java create mode 100644 eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SecurePendingRequestIdGenerationStrategy.java create mode 100644 eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/ServletUtils.java create mode 100644 eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SimplePendingRequestIdGenerationStrategy.java create mode 100644 eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/StreamUtils.java create mode 100644 eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/TransactionIDUtils.java create mode 100644 eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/X509Utils.java diff --git a/eaaf_core/pom.xml b/eaaf_core/pom.xml index b0dc1953..43f75444 100644 --- a/eaaf_core/pom.xml +++ b/eaaf_core/pom.xml @@ -17,6 +17,10 @@ at.gv.egiz.eaaf eaaf_core_api + + at.gv.egiz.eaaf + eaaf_core_utils + at.gv.egiz.components @@ -82,21 +86,7 @@ xalan xalan - - - org.apache.httpcomponents - httpclient - - - org.apache.httpcomponents - httpcore - - - - joda-time - joda-time - - + junit junit diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/support/SecureRandomHolder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/support/SecureRandomHolder.java deleted file mode 100644 index a297367f..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/support/SecureRandomHolder.java +++ /dev/null @@ -1,61 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.idp.process.support; - -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; - -/** - * Holder for a secure random instance following the initialization on demand holder design pattern. The secure random - * instance is a singleton that is initialized on first usage. - * - * @author tknall - * - */ -public class SecureRandomHolder { - - private SecureRandomHolder() { - } - - private static final SecureRandom SRND_INSTANCE; - static { - try { - SRND_INSTANCE = SecureRandom.getInstance("SHA1PRNG"); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException("Unable to instantiate SHA1PRNG.", e); - } - } - - /** - * Returns a secure random generator instance. - * @return The secure random instance. - */ - public static SecureRandom getInstance() { - return SecureRandomHolder.SRND_INSTANCE; - } - -} \ No newline at end of file diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/ArrayUtils.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/ArrayUtils.java deleted file mode 100644 index 8585bc05..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/ArrayUtils.java +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.utils; - -import java.util.List; - -public class ArrayUtils { - - /** - * Check if a String 's' is part of a List 'l' in qualsIgnoreCase mode - * - * @param s Search String - * @param l List of String elements - * @return true if 's' is in 'l', otherwise false - */ - public static boolean containsCaseInsensitive(String s, List l){ - if (l == null || s == null) - return false; - - return l.stream().anyMatch(x -> x.equalsIgnoreCase(s)); - - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/DataURLBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/DataURLBuilder.java deleted file mode 100644 index a81fafbc..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/DataURLBuilder.java +++ /dev/null @@ -1,113 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - ******************************************************************************/ -/* - * Copyright 2003 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - */ - - -package at.gv.egiz.eaaf.core.impl.utils; - -import org.apache.commons.lang3.StringUtils; - -import at.gv.egiz.eaaf.core.api.data.EAAFConstants; - -/** - * Builds a DataURL parameter meant for the security layer implementation - * to respond to. - * - * @author Paul Ivancsics - * @version $Id$ - */ -public class DataURLBuilder { - - /** - * Constructor for DataURLBuilder. - */ - public DataURLBuilder() { - super(); - } - - /** - * Constructs a data URL for VerifyIdentityLink or VerifyAuthenticationBlock, - * including the MOASessionID as a parameter. - * - * @param authBaseURL base URL (context path) of the MOA ID Authentication component, - * including a trailing '/' - * @param authServletName request part of the data URL - * @param pendingReqId sessionID to be included in the dataURL - * @return String - */ - public String buildDataURL(String authBaseURL, String authServletName, String pendingReqId) { - String dataURL; - if (!authBaseURL.endsWith("/")) - authBaseURL += "/"; - - if (authServletName.startsWith("/")) - authServletName = authServletName.substring(1); - - dataURL = authBaseURL + authServletName; - - if (StringUtils.isNotEmpty(pendingReqId)) - dataURL = addParameter(dataURL, EAAFConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID, pendingReqId); - - return dataURL; - } - - /** - * Method addParameter. - * @param urlString represents the url - * @param paramname is the parameter to be added - * @param value is the value of that parameter - * @return String - */ - private String addParameter(String urlString, String paramname, String value) { - String url = urlString; - if (paramname != null) { - if (url.indexOf("?") < 0) - url += "?"; - else - url += "&"; - url += paramname + "=" + value; - } - return url; - } -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/FileUtils.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/FileUtils.java deleted file mode 100644 index fff83e53..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/FileUtils.java +++ /dev/null @@ -1,175 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ - - -package at.gv.egiz.eaaf.core.impl.utils; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URL; - -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class FileUtils { - private static final Logger log = LoggerFactory.getLogger(FileUtils.class); - - - /** - * Reads a file, given by URL, into a byte array. - * @param urlString file URL - * @return file content - * @throws IOException on any exception thrown - */ - public static byte[] readURL(String urlString) throws IOException { - final URL url = new URL(urlString); - final InputStream in = new BufferedInputStream(url.openStream()); - final byte[] content = StreamUtils.readStream(in); - in.close(); - return content; - } - - /** - * Reads a file from a resource. - * @param name resource name - * @return file content as a byte array - * @throws IOException on any exception thrown - */ - public static byte[] readResource(String name) throws IOException { - final ClassLoader cl = FileUtils.class.getClassLoader(); - final BufferedInputStream in = new BufferedInputStream(cl.getResourceAsStream(name)); - final byte[] content = StreamUtils.readStream(in); - in.close(); - return content; - } - /** - * Reads a file from a resource. - * @param name filename - * @param encoding character encoding - * @return file content - * @throws IOException on any exception thrown - */ - public static String readResource(String name, String encoding) throws IOException { - final byte[] content = readResource(name); - return new String(content, encoding); - } - - - /** - * Returns the absolute URL of a given url which is relative to the parameter root - * @param url - * @param root - * @return String - * @throws MalformedURLException - */ - public static String makeAbsoluteURL(String url, URI root) throws MalformedURLException { - if (root != null) - return makeAbsoluteURL(url, root.toURL().toString()); - else - return makeAbsoluteURL(url, StringUtils.EMPTY); - - } - - /** - * Returns the absolute URL of a given url which is relative to the parameter root - * @param url - * @param root - * @return String - */ - public static String makeAbsoluteURL(String url, String root) { - //if url is relative to rootConfigFileDirName make it absolute - - log.trace("Making AbsoluteURL URL: " + url + " Root-Path: " + root); - - if (StringUtils.isEmpty(root)) - root = null; - - File keyFile; - String newURL = url; - - if(null == url) return null; - - if (url.startsWith("http:") || url.startsWith("https:") || url.startsWith("file:") || url.startsWith("ftp:")) { - return url; - - } else { - // check if absolute - if not make it absolute - keyFile = new File(url); - if (!keyFile.isAbsolute()) { - keyFile = new File(root, url); - - if (keyFile.toString().startsWith("file:")) - newURL = keyFile.toString(); - - else - newURL = keyFile.toURI().toString(); - - } - return newURL; - } - } - - - private static void copy( InputStream fis, OutputStream fos ) - { - try - { - final byte[] buffer = new byte[ 0xFFFF ]; - for ( int len; (len = fis.read(buffer)) != -1; ) - fos.write( buffer, 0, len ); - } - catch( final IOException e ) { - System.err.println( e ); - } - finally { - if ( fis != null ) - try { fis.close(); } catch ( final IOException e ) { e.printStackTrace(); } - if ( fos != null ) - try { fos.close(); } catch ( final IOException e ) { e.printStackTrace(); } - } - } - - public static void copyFile(File src, File dest) - { - try - { - copy( new FileInputStream( src ), new FileOutputStream( dest ) ); - } - catch( final IOException e ) { - e.printStackTrace(); - } - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HTTPUtils.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HTTPUtils.java deleted file mode 100644 index cf1abaa7..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HTTPUtils.java +++ /dev/null @@ -1,178 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - ******************************************************************************/ -/* - * Copyright 2003 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - */ - - -package at.gv.egiz.eaaf.core.impl.utils; - -import javax.servlet.http.HttpServletRequest; - -import org.apache.commons.lang3.StringUtils; - - -/** - * - * @author Rudolf Schamberger - * - */ -public class HTTPUtils { - -// /** -// * Utility used to obtainin correct encoded HTTP content. -// * Reads a given Content adressed by HTTP-URL into String. -// * Content encoding is considered by using the Content-Type HTTP header charset value. -// * @param URL HTTP URL to read from. -// * @return String representation of content -// * @throws IOException on data-reading problems -// */ -// public static String readHttpURL(String URL) -// throws IOException { -// -// URL url = new URL(URL); -// HttpURLConnection conn = (HttpURLConnection)url.openConnection(); -// conn.setRequestMethod("GET"); -// String contentType = conn.getContentType(); -// RE regExp = null; -// try { -// regExp = new RE("(;.*charset=)(\"*)(.*[^\"])"); -// } catch (RESyntaxException e) { -// //RESyntaxException is not possible = expr. is costant -// } -// boolean charsetSupplied = regExp.match(contentType); -// String encoding = "ISO-8859-1"; //default HTTP encoding -// if (charsetSupplied) { -// encoding = regExp.getParen(3); -// } -// InputStream instream = new BufferedInputStream(conn.getInputStream()); -// InputStreamReader isr = new InputStreamReader(instream, encoding); -// Reader in = new BufferedReader(isr); -// int ch; -// StringBuffer buffer = new StringBuffer(); -// while ((ch = in.read()) > -1) { -// buffer.append((char)ch); -// } -// in.close(); -// conn.disconnect(); -// return buffer.toString(); -// } - - /** - * Helper method to retrieve server URL including context path - * @param request HttpServletRequest - * @return Server URL including context path (e.g. http://localhost:8443/moa-id-auth - */ - public static String getBaseURL(HttpServletRequest request) { - StringBuffer buffer = new StringBuffer(getServerURL(request)); - - // add context path if available - String contextPath = request.getContextPath(); - if (!StringUtils.isEmpty(contextPath)) { - buffer.append(contextPath); - } - - return buffer.toString(); - } - - /** - * Helper method to retrieve server URL - * @param request HttpServletRequest - * @return Server URL (e.g. http://localhost:8443) - */ - public static String getServerURL(HttpServletRequest request) { - StringBuffer buffer = new StringBuffer(); - - // get protocol - String protocol = request.getScheme(); - buffer.append(protocol).append("://"); - - // server name - buffer.append(request.getServerName()); - - // add port if necessary - int port = request.getServerPort(); - if ((protocol.equals("http") && port != 80) || (protocol.equals("https") && port != 443)) { - buffer.append(':'); - buffer.append(port); - } - - return buffer.toString(); - } - - /** - * Extract the IDP PublicURLPrefix from authrequest - * - * @param req HttpServletRequest - * @return PublicURLPrefix which ends always without / - */ - public static String extractAuthURLFromRequest(HttpServletRequest req) { - String authURL = req.getScheme() + "://" + req.getServerName(); - if ((req.getScheme().equalsIgnoreCase("https") && req.getServerPort()!=443) || (req.getScheme().equalsIgnoreCase("http") && req.getServerPort()!=80)) { - authURL = authURL.concat(":" + req.getServerPort()); - } - authURL = authURL.concat(req.getContextPath()); - return authURL; - - } - - /** - * Extract the IDP requested URL from authrequest - * - * @param req HttpServletRequest - * @return RequestURL which ends always without / - */ - public static String extractAuthServletPathFromRequest(HttpServletRequest req) { - return extractAuthURLFromRequest(req).concat(req.getServletPath()); - - } - - public static String addURLParameter(String url, String paramname, - String paramvalue) { - String param = paramname + "=" + paramvalue; - if (url.indexOf("?") < 0) - return url + "?" + param; - else - return url + "&" + param; - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HttpClientFactory.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HttpClientFactory.java deleted file mode 100644 index ee12b9e4..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HttpClientFactory.java +++ /dev/null @@ -1,154 +0,0 @@ -package at.gv.egiz.eaaf.core.impl.utils; - -import java.security.NoSuchAlgorithmException; - -import javax.annotation.PostConstruct; -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.SSLContext; - -import org.apache.http.HttpRequest; -import org.apache.http.HttpResponse; -import org.apache.http.ProtocolException; -import org.apache.http.client.RedirectStrategy; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.conn.socket.LayeredConnectionSocketFactory; -import org.apache.http.conn.ssl.NoopHostnameVerifier; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.DefaultRedirectStrategy; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; -import org.apache.http.protocol.HttpContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import at.gv.egiz.eaaf.core.api.idp.IConfiguration; - -@Service -public class HttpClientFactory implements IHttpClientFactory { - private static final Logger log = LoggerFactory.getLogger(HttpClientFactory.class); - @Autowired(required=true) private IConfiguration basicConfig; - - public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_USE = "client.http.connection.pool.use"; - public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL = "client.http.connection.pool.maxtotal"; - public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE = "client.http.connection.pool.maxperroute"; - public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_SOCKET = "client.http.connection.timeout.socket"; - public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_CONNECTION = "client.http.connection.timeout.connection"; - public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_REQUEST = "client.http.connection.timeout.request"; - public static final String PROP_CONFIG_CLIENT_HTTP_SSL_HOSTNAMEVERIFIER_TRUSTALL = "client.http.ssl.hostnameverifier.trustall"; - - // default configuration values - public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_SOCKET = "15"; - public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_CONNECTION = "15"; - public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_REQUEST = "30"; - public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL = "500"; - public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE = "100"; - - private HttpClientBuilder httpClientBuilder = null; - - /* (non-Javadoc) - * @see at.gv.egiz.eaaf.core.impl.utils.IHttpClientFactory#getHttpClient() - */ - @Override - public CloseableHttpClient getHttpClient() { - return getHttpClient(true); - - } - - @Override - public CloseableHttpClient getHttpClient(boolean followRedirects) { - RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); - if (!followRedirects) - redirectStrategy = new RedirectStrategy() { - - @Override - public boolean isRedirected(HttpRequest request, HttpResponse response, HttpContext context) - throws ProtocolException { - return false; - } - - @Override - public HttpUriRequest getRedirect(HttpRequest request, HttpResponse response, HttpContext context) - throws ProtocolException { - return null; - } - }; - - return httpClientBuilder - .setRedirectStrategy(redirectStrategy) - .build(); - - } - - @PostConstruct - private void initalize() { - //initialize http client - log.trace("Initializing HTTP Client-builder ... "); - httpClientBuilder = HttpClients.custom(); - - //set default request configuration - final RequestConfig requestConfig = RequestConfig.custom() - .setConnectTimeout(Integer.valueOf(basicConfig.getBasicConfiguration( - PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_CONNECTION, - DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_CONNECTION)) * 1000) - .setConnectionRequestTimeout(Integer.valueOf(basicConfig.getBasicConfiguration( - PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_REQUEST, - DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_REQUEST)) * 1000) - .setSocketTimeout(Integer.valueOf(basicConfig.getBasicConfiguration( - PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_SOCKET, - DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_SOCKET)) * 1000) - .build(); - httpClientBuilder.setDefaultRequestConfig(requestConfig); - - //set pool connection if requested - if (basicConfig.getBasicConfigurationBoolean( - PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_USE, - true)) { - final PoolingHttpClientConnectionManager pool = new PoolingHttpClientConnectionManager(); - pool.setDefaultMaxPerRoute(Integer.valueOf(basicConfig.getBasicConfiguration( - PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE, - DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE))); - pool.setMaxTotal(Integer.valueOf(basicConfig.getBasicConfiguration( - PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL, - DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL))); - - - - httpClientBuilder.setConnectionManager(pool); - log.debug("Initalize http-client pool with, maxTotal: {} maxPerRoute: {}", pool.getMaxTotal(), pool.getDefaultMaxPerRoute()); - - } - - try { - log.trace("Initializing SSL Context ... "); - final SSLContext sslContext = SSLContext.getDefault(); - HostnameVerifier hostnameVerifier = null; - if (basicConfig.getBasicConfigurationBoolean( - PROP_CONFIG_CLIENT_HTTP_SSL_HOSTNAMEVERIFIER_TRUSTALL, - false)) { - hostnameVerifier = new NoopHostnameVerifier(); - log.warn("HTTP client-builder deactivates SSL Host-name verification!"); - } - - final LayeredConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext , hostnameVerifier); - httpClientBuilder.setSSLSocketFactory(sslSocketFactory ); - - } catch (final NoSuchAlgorithmException e) { - log.warn("HTTP client-builder can NOT initialze SSL-Context", e); - - } - - - log.info("HTTP client-builder successfuly initialized"); - - } - - - - - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/IHttpClientFactory.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/IHttpClientFactory.java deleted file mode 100644 index 1975fb52..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/IHttpClientFactory.java +++ /dev/null @@ -1,21 +0,0 @@ -package at.gv.egiz.eaaf.core.impl.utils; - -import org.apache.http.impl.client.CloseableHttpClient; - -public interface IHttpClientFactory { - - /** - * Return an instance of a Apache HTTP client that follows http redirects automatically - * - * @return - */ - CloseableHttpClient getHttpClient(); - - /** - * Return an instance of a Apache HTTP client - * @param followRedirects - * @return - */ - CloseableHttpClient getHttpClient(boolean followRedirects); - -} \ No newline at end of file diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/KeyStoreUtils.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/KeyStoreUtils.java deleted file mode 100644 index e3d74066..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/KeyStoreUtils.java +++ /dev/null @@ -1,199 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ - - -package at.gv.egiz.eaaf.core.impl.utils; - -import java.io.BufferedInputStream; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.security.GeneralSecurityException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.cert.Certificate; -import java.security.cert.CertificateFactory; - -/** - * Utility for creating and loading key stores. - * - * @author Paul Ivancsics - * @version $Id$ - */ -public class KeyStoreUtils { - - /** - * JAVA KeyStore - */ - private static final String KEYSTORE_TYPE_JKS = "JKS"; - - /** - * PKCS12 KeyStore - */ - private static final String KEYSTORE_TYPE_PKCS12 = "PKCS12"; - - - - /** - * Loads a key store from file. - * - * @param keystoreType key store type - * @param urlString URL of key store - * @param password password protecting the key store - * @return key store loaded - * @throws IOException thrown while reading the key store from file - * @throws GeneralSecurityException thrown while creating the key store - */ - public static KeyStore loadKeyStore( - String keystoreType, - String urlString, - String password) - throws IOException, GeneralSecurityException { - - URL keystoreURL = new URL(urlString); - InputStream in = keystoreURL.openStream(); - return loadKeyStore(keystoreType, in, password); - } - /** - * Loads a key store from an InputStream, and - * closes the InputStream. - * - * @param keystoreType key store type - * @param in input stream - * @param password password protecting the key store - * @return key store loaded - * @throws IOException thrown while reading the key store from the stream - * @throws GeneralSecurityException thrown while creating the key store - */ - public static KeyStore loadKeyStore( - String keystoreType, - InputStream in, - String password) - throws IOException, GeneralSecurityException { - - char[] chPassword = null; - if (password != null) - chPassword = password.toCharArray(); - KeyStore ks = KeyStore.getInstance(keystoreType); - ks.load(in, chPassword); - in.close(); - return ks; - } - /** - * Creates a key store from X509 certificate files, aliasing them with - * the index in the String[], starting with "0". - * - * @param keyStoreType key store type - * @param certFilenames certificate filenames - * @return key store created - * @throws IOException thrown while reading the certificates from file - * @throws GeneralSecurityException thrown while creating the key store - */ - public static KeyStore createKeyStore( - String keyStoreType, - String[] certFilenames) - throws IOException, GeneralSecurityException { - - KeyStore ks = KeyStore.getInstance(keyStoreType); - ks.load(null, null); - for (int i = 0; i < certFilenames.length; i++) { - Certificate cert = loadCertificate(certFilenames[i]); - ks.setCertificateEntry("" + i, cert); - } - return ks; - } - - /** - * Loads an X509 certificate from file. - * @param certFilename filename - * @return the certificate loaded - * @throws IOException thrown while reading the certificate from file - * @throws GeneralSecurityException thrown while creating the certificate - */ - private static Certificate loadCertificate(String certFilename) - throws IOException, GeneralSecurityException { - - FileInputStream in = new FileInputStream(certFilename); - CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); - Certificate cert = certFactory.generateCertificate(in); - in.close(); - return cert; - } - - - /** - * Loads a keyStore without knowing the keyStore type - * @param keyStorePath URL to the keyStore - * @param password Password protecting the keyStore - * @return keyStore loaded - * @throws KeyStoreException thrown if keyStore cannot be loaded - * @throws FileNotFoundException - * @throws IOException - */ - public static KeyStore loadKeyStore(String keyStorePath, String password) throws KeyStoreException, IOException{ - - //InputStream is = new FileInputStream(keyStorePath); - URL keystoreURL = new URL(keyStorePath); - InputStream in = keystoreURL.openStream(); - InputStream isBuffered = new BufferedInputStream(in); - return loadKeyStore(isBuffered, password); - - } - - /** - * Loads a keyStore without knowing the keyStore type - * @param in input stream - * @param password Password protecting the keyStore - * @return keyStore loaded - * @throws KeyStoreException thrown if keyStore cannot be loaded - * @throws FileNotFoundException - * @throws IOException - */ -public static KeyStore loadKeyStore(InputStream is, String password) throws KeyStoreException, IOException{ - is.mark(1024*1024); - KeyStore ks = null; - try { - try { - ks = loadKeyStore(KEYSTORE_TYPE_PKCS12, is, password); - } catch (IOException e2) { - is.reset(); - ks = loadKeyStore(KEYSTORE_TYPE_JKS, is, password); - } - } catch(Exception e) { - e.printStackTrace(); - - } - return ks; - - } - - - - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/KeyValueUtils.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/KeyValueUtils.java deleted file mode 100644 index e753f19f..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/KeyValueUtils.java +++ /dev/null @@ -1,375 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.utils; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; -import java.util.Set; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * @author tlenz - * - */ -public class KeyValueUtils { - private static final Logger log = LoggerFactory.getLogger(KeyValueUtils.class); - - public static final String KEY_DELIMITER = "."; - public static final String CSV_DELIMITER = ","; - public static final String KEYVVALUEDELIMITER = "="; - public static final String DEFAULT_VALUE = "default"; - - /** - * Convert Java properties into a Map - *

- * Important: The key/values from properties must be of type String! - * - * @param properties - * @return - */ - public static Map convertPropertiesToMap(Properties properties) { - return new HashMap((Map) properties); - - //INFO Java8 solution ;) -// return properties.entrySet().stream().collect( -// Collectors.toMap( -// e -> e.getKey().toString(), -// e -> e.getValue().toString() -// ) -// ); - - } - - /** - * Extract the first child of an input key after a the prefix - * - * @param key Full input key - * @param prefix Prefix - * @return Child key {String} if it exists or null - */ - public static String getFirstChildAfterPrefix(String key, String prefix) { - final String idAfterPrefix = removePrefixFromKey(key, prefix); - if (idAfterPrefix != null) { - final int index = idAfterPrefix.indexOf(KEY_DELIMITER); - if (index > 0) { - final String adding = idAfterPrefix.substring(0, index); - if (!(adding.isEmpty())) { - return adding; - - } - } else if (!(idAfterPrefix.isEmpty())) { - return idAfterPrefix; - - } - - } - return null; - } - - /** - * Extract the prefix from an input key - * - * @param key Full input key - * @param suffix Suffix of this key - * @return Prefix {String} of the key or null if input key does not ends with postfix string - */ - public static String getPrefixFromKey(String key, String suffix) { - if (key != null && suffix != null && key.endsWith(suffix)) { - final String idPreforeSuffix = key.substring(0, key.length()-suffix.length()); - if (idPreforeSuffix.endsWith(KEY_DELIMITER)) - return idPreforeSuffix.substring(0, idPreforeSuffix.length()-1); - else - return idPreforeSuffix; - } - return null; - - } - - /** - * Remove a prefix string from a key - * - * @param key Full input key - * @param prefix Prefix, which should be removed - * @return The suffix of the input key or null if the input does not starts with the prefix - */ - public static String removePrefixFromKey(String key, String prefix) { - if (prefix == null) - prefix = new String(); - - if (key!=null && key.startsWith(prefix)) { - String afterPrefix = key.substring(prefix.length()); - final int index = afterPrefix.indexOf(KEY_DELIMITER); - - if (index == 0) { - afterPrefix = afterPrefix.substring(1); - - } - return afterPrefix; - - } - return null; - } - - /** - * Remove a prefix string from all keys in {Map} of key/value pairs - * - * @param keys Input data of key/value pairs - * @param prefix Prefix which should be removed - * @return {Map} of key/value pairs without prefix in key, but never null - */ - public static Map removePrefixFromKeys(Map keys, String prefix) { - final Map result = new HashMap(); - final Iterator> interator = keys.entrySet().iterator(); - while(interator.hasNext()) { - final Entry el = interator.next(); - final String newKey = removePrefixFromKey(el.getKey(), prefix); - if (StringUtils.isNotEmpty(newKey)) { - result.put(newKey, el.getValue()); - } - } - - return result; - } - - /** - * Get a subset of key/value pairs which starts with a prefix string - * The Prefix is removed from the key - * - * @param keys Input data of key/value pairs - * @param prefix Prefix string - * @return {Map} of key/value pairs without prefix in key, but never null - */ - public static Map getSubSetWithPrefix(Map keys, String prefix) { - return removePrefixFromKeys(keys, prefix); - } - - - /** - * Add a prefix to key/value pairs to make the key absolute according to key namespace convention - * - * @param input Input key/value pairs which should be updated - * @param prefix Key prefix, which should be added if the key is not absolute - * @param absolutIdentifier Key identifier, which indicates an absolute key - * @return {Map} of key/value pairs in which all keys are absolute but never null - */ - public static Map makeKeysAbsolut(Map input, String prefix, String absolutIdentifier) { - final Map result = new HashMap(); - final Iterator> interator = input.entrySet().iterator(); - while(interator.hasNext()) { - final Entry el = interator.next(); - if (!el.getKey().startsWith(absolutIdentifier)) { - //key is not absolute -> add prefix - result.put(prefix - + KEY_DELIMITER - + el.getKey(), - el.getValue()); - - } else { - //key is absolute - result.put(el.getKey(), el.getValue()); - } - } - return result; - } - - /** - * Get the parent key string from an input key - * - * @param key input key - * @return parent key or the empty String if no parent exists - */ - public static String getParentKey(String key) { - if (StringUtils.isNotEmpty(key)) { - final int index = key.lastIndexOf(KEY_DELIMITER); - if (index > 0) { - return key.substring(0, index); - - } - } - - return new String(); - } - - /** - * Find the highest free list counter - * - * @param input Array of list keys - * @param listPrefix {String} prefix of the list - * @return {int} highest free list counter - */ - public static int findNextFreeListCounter(String[] input, - String listPrefix) { - final List counters = new ArrayList(); - if (input == null || input.length == 0) - return 0; - - else { - for (final String key : input) { - final String listIndex = getFirstChildAfterPrefix(key, listPrefix); - counters.add(Integer.parseInt(listIndex)); - - } - Collections.sort(counters); - return counters.get(counters.size()-1) + 1; - } - } - - /** - * Find the highest free list counter - * - * @param keySet {Set} of list keys - * @param listPrefix {String} prefix of the list - * @return {int} highest free list counter - */ - public static int findNextFreeListCounter(Set keySet, - String listPrefix) { - if (keySet.isEmpty()) - return 0; - - final String[] array = new String[keySet.size()]; - keySet.toArray(array); - return findNextFreeListCounter(array, listPrefix); - } - - - /** - * Normalize a CSV encoded list of value of an key/value pair - * - * This method removes all whitespace at the begin or the - * end of CSV values and remove newLine signs at the end of value. - * The ',' is used as list delimiter - * - * @param value CSV encoded input data - * @return normalized CSV encoded data or null if {value} is null or empty - */ - public static String normalizeCSVValueString(String value) { - String normalizedCodes = null; - if (StringUtils.isNotEmpty(value)) { - final String[] codes = value.split(CSV_DELIMITER); - for (final String el: codes) { - if (normalizedCodes == null) - normalizedCodes = StringUtils.chomp(el.trim()); - else - normalizedCodes += "," + StringUtils.chomp(el.trim()); - - } - } - return normalizedCodes; - } - - - /** - * Check a String if it is a comma separated list of values - * - * This method uses the ',' as list delimiter. - * - * @param value CSV encoded input data - * @return true if the input data contains a ',' and has more then 1 list element, otherwise false - */ - public static boolean isCSVValueString(String value) { - if (StringUtils.isNotEmpty(value)) { - final String[] codes = value.split(CSV_DELIMITER); - if (codes.length >= 2) { - if (StringUtils.isNotEmpty(codes[1].trim())) - return true; - - } - } - - return false; - } - - /** - * Convert a CSV list to a List of CSV values - *

- * This method removes all whitespace at the begin or the - * end of CSV values and remove newLine signs at the end of value. - * The ',' is used as list delimiter - * - * @param csv CSV encoded input data - * @return List of CSV normalized values, but never null - */ - @Nonnull - public static List getListOfCSVValues(@Nullable String csv) { - final List list = new ArrayList(); - if (StringUtils.isNotEmpty(csv)) { - final String[] values = csv.split(CSV_DELIMITER); - for (final String el: values) - list.add(el.trim()); - - } - - return list; - } - - /** - * Convert a List of String elements to a Map of Key/Value pairs - *
- * Every List element used as a key/value pair and the '=' sign represents the delimiter between key and value - * - * @param elements List of key/value elements - * @return Map of Key / Value pairs, but never null - */ - public static Map convertListToMap(List elements) { - final Map map = new HashMap(); - for (final String el : elements) { - if (el.contains(KEYVVALUEDELIMITER)) { - final String[] split = el.split(KEYVVALUEDELIMITER); - map.put(split[0], split[1]); - - } else - log.debug("Key/Value Mapper: '" + el + "' contains NO '='. Ignore it."); - - } - - return map; - } - - /** - * This method remove all newline delimiter (\n or \r\n) from input data - * - * @param value Input String - * @return Input String without newline characters - */ - public static String removeAllNewlineFromString(String value) { - return value.replaceAll("(\\t|\\r?\\n)+", ""); - - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/NodeIteratorAdapter.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/NodeIteratorAdapter.java deleted file mode 100644 index ec57b92a..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/NodeIteratorAdapter.java +++ /dev/null @@ -1,113 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ - - -package at.gv.egiz.eaaf.core.impl.utils; - -import java.util.ListIterator; - -import org.w3c.dom.DOMException; -import org.w3c.dom.Node; -import org.w3c.dom.traversal.NodeFilter; -import org.w3c.dom.traversal.NodeIterator; - -/** - * A NodeIterator implementation based on a - * ListIterator. - * - * @see java.util.ListIterator - * @see org.w3c.dom.traversal.NodeIterator - * - */ -public class NodeIteratorAdapter implements NodeIterator { - - /** The ListIterator to wrap. */ - private ListIterator nodeIterator; - - /** - * Create a new NodeIteratorAdapter. - * @param nodeIterator The ListIterator to iterate over. - */ - public NodeIteratorAdapter(ListIterator nodeIterator) { - this.nodeIterator = nodeIterator; - } - - /** - * @see org.w3c.dom.traversal.NodeIterator#getRoot() - */ - public Node getRoot() { - return null; - } - - /** - * @see org.w3c.dom.traversal.NodeIterator#getWhatToShow() - */ - public int getWhatToShow() { - return NodeFilter.SHOW_ALL; - } - - /** - * @see org.w3c.dom.traversal.NodeIterator#getFilter() - */ - public NodeFilter getFilter() { - return null; - } - - /** - * @see org.w3c.dom.traversal.NodeIterator#getExpandEntityReferences() - */ - public boolean getExpandEntityReferences() { - return false; - } - - /** - * @see org.w3c.dom.traversal.NodeIterator#nextNode() - */ - public Node nextNode() throws DOMException { - if (nodeIterator.hasNext()) { - return (Node) nodeIterator.next(); - } - return null; - } - - /** - * @see org.w3c.dom.traversal.NodeIterator#previousNode() - */ - public Node previousNode() throws DOMException { - if (nodeIterator.hasPrevious()) { - return (Node) nodeIterator.previous(); - } - return null; - } - - /** - * @see org.w3c.dom.traversal.NodeIterator#detach() - */ - public void detach() { - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/NodeListAdapter.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/NodeListAdapter.java deleted file mode 100644 index 69045aaa..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/NodeListAdapter.java +++ /dev/null @@ -1,70 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ - - -package at.gv.egiz.eaaf.core.impl.utils; - -import java.util.List; - -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -/** - * A NodeList implementation based on a List. - * - * @see java.util.List - * @see org.w3c.dom.NodeList - */ - -public class NodeListAdapter implements NodeList { - /** The List to wrap. */ - private List nodeList; - - /** - * Create a new NodeListAdapter. - * - * @param nodeList The List containing the nodes. - */ - public NodeListAdapter(List nodeList) { - this.nodeList = nodeList; - } - - /** - * @see org.w3c.dom.NodeList#item(int) - */ - public Node item(int index) { - return (Node) nodeList.get(index); - } - - /** - * @see org.w3c.dom.NodeList#getLength() - */ - public int getLength() { - return nodeList.size(); - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/Random.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/Random.java deleted file mode 100644 index e236b3a9..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/Random.java +++ /dev/null @@ -1,176 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ - -package at.gv.egiz.eaaf.core.impl.utils; - - -import java.nio.ByteBuffer; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; - -import org.apache.commons.codec.binary.Hex; -import org.apache.commons.lang3.ArrayUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import at.gv.egiz.eaaf.core.impl.idp.process.support.SecureRandomHolder; - - -/** - * Random number generator used to generate ID's - * @author Paul Ivancsics - * @version $Id$ - */ -public class Random { - private static final Logger log = LoggerFactory.getLogger(Random.class); - - private final static char[] allowedPreFix = - {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z', - 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}; - private static final DateFormat dateFormater = new SimpleDateFormat("yyyyddMM"); - - /** random number generator used */ - private static SecureRandom random; - //private static SeedGenerator seedgenerator; - - static { - try { - random = SecureRandom.getInstance("SHA256PRNG-FIPS186"); - - } catch (NoSuchAlgorithmException e) { - log.warn("Can NOT initialize SecureRandom with: 'SHA256PRNG-FIPS186'. Use 'StrongSecureRandom' as backup"); - random = SecureRandomHolder.getInstance(); - - } - - - //random = iaik.security.random.SHA256FIPS186Random.getDefault(); - } - - /** - * Generate a unique process reference-value [160bit], which always starts with a letter - *
- * This unique ID consists of single letter, a 64bit date String[yyyyddMM], - * and a 88bit random value. - * - * @return 160bit ID, which is hex encoded - */ - public static String nextProcessReferenceValue() { - //pre-process all three parts of a unique reference value - String now = dateFormater.format(new Date()); //8 bytes = 64bit - byte[] randValue = nextByteRandom(11); - char preFix = allowedPreFix[Math.abs(random.nextInt() % allowedPreFix.length)]; - - //generate ID - String returnValue = preFix + new String(Hex.encodeHex(ArrayUtils.addAll(now.getBytes(), randValue))); // 20 bytes = 160 bits - if (returnValue.length() > 40) - return returnValue.substring(0, 40); - else - return returnValue; - - } - - - - /** - * Creates a new random number [256bit], and encode it as hex value. - * - * @return random hex encoded value [256bit] - */ - public static String nextHexRandom32() { - return new String(Hex.encodeHex(nextByteRandom(32))); // 32 bytes = 256 bits - - } - - /** - * Creates a new random number [128bit], and encode it as hex value. - * - * @return random hex encoded value [128bit] - */ - public static String nextHexRandom16() { - return new String(Hex.encodeHex(nextByteRandom(16))); // 16 bytes = 128 bits - - } - - /** - * Creates a new random number [64bit], to be used as an ID. - * - * @return random long as a String [64bit] - */ - public static String nextLongRandom() { - return "".concat(String.valueOf(Math.abs(generateLongRandom(32)))); // 32 bytes = 256 bits - - } - - /** - * Creates a new random number, to be used as an ID. - * - * @return random long as a String [64bit] - */ - @Deprecated - public static String nextRandom() { - long l = ByteBuffer.wrap(nextByteRandom(32)).getLong(); // 32 bytes = 256 bits - return "" + Math.abs(l); - - } - -/** - * Creates a new random byte[] - * - * @param size Size of random number in byte - * @return - */ -public static byte[] nextBytes(int size) { - return nextByteRandom(size); - -} - - public static void seedRandom() { - //TODO: implement reflection on IAIK Seed generator -// seedgenerator = iaik.security.random.AutoSeedGenerator.getDefault(); -// if (seedgenerator.seedAvailable()) -// random.setSeed(seedgenerator.getSeed()); - - random.setSeed(System.nanoTime()); - } - - private static long generateLongRandom(int size) { - return ByteBuffer.wrap(nextByteRandom(size)).getLong(); - } - - /** - * Generate a new random number - * - * @param size Size of random number in byte - * @return - */ - private static synchronized byte[] nextByteRandom(int size) { - byte[] b = new byte[size]; - random.nextBytes(b); - return b; - - } -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SecurePendingRequestIdGenerationStrategy.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SecurePendingRequestIdGenerationStrategy.java deleted file mode 100644 index f0ef9b38..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SecurePendingRequestIdGenerationStrategy.java +++ /dev/null @@ -1,214 +0,0 @@ -package at.gv.egiz.eaaf.core.impl.utils; - -import java.io.UnsupportedEncodingException; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.KeySpec; -import java.util.Arrays; -import java.util.Base64; - -import javax.annotation.PostConstruct; -import javax.crypto.Mac; -import javax.crypto.SecretKey; -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.PBEKeySpec; - -import org.apache.commons.lang3.StringUtils; -import org.joda.time.DateTime; -import org.joda.time.DurationFieldType; -import org.joda.time.format.DateTimeFormat; -import org.joda.time.format.DateTimeFormatter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.lang.NonNull; -import org.springframework.lang.Nullable; - -import at.gv.egiz.eaaf.core.api.idp.IConfiguration; -import at.gv.egiz.eaaf.core.api.utils.IPendingRequestIdGenerationStrategy; -import at.gv.egiz.eaaf.core.exceptions.EAAFConfigurationException; -import at.gv.egiz.eaaf.core.exceptions.EAAFException; -import at.gv.egiz.eaaf.core.exceptions.EAAFIllegalStateException; -import at.gv.egiz.eaaf.core.exceptions.PendingReqIdValidationException; - -/** - * PendingRequestId generation strategy based on signed tokens that facilitates extended token validation - * - * @author tlenz - * - */ -public class SecurePendingRequestIdGenerationStrategy implements IPendingRequestIdGenerationStrategy { - private static final Logger log = LoggerFactory.getLogger(SecurePendingRequestIdGenerationStrategy.class); - - @Autowired(required=true) IConfiguration baseConfig; - - public static final String CONFIG_PROP_PENDINGREQUESTID_DIGIST_SECRET = "core.pendingrequestid.digist.secret"; - public static final String CONFIG_PROP_PENDINGREQUESTID_DIGIST_ALGORITHM = "core.pendingrequestid.digist.algorithm"; - public static final String CONFIG_PROP_PENDINGREQUESTID_MAX_LIFETIME = "core.pendingrequestid.maxlifetime"; - - public static final String DEFAULT_PENDINGREQUESTID_DIGIST_ALGORITHM = "HmacSHA256"; - public static final String DEFAULT_PENDINGREQUESTID_MAX_LIFETIME = "300"; - - private static final int ENCODED_TOKEN_PARTS = 3; - private static final String TOKEN_SEPARATOR = "|"; - private static final DateTimeFormatter TOKEN_TEXTUAL_DATE_FORMAT = - DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss SSS"); - - private int maxPendingRequestIdLifeTime = 300; - private final int maxPendingReqIdSize = 1024; - private String digistAlgorithm = null; - private SecretKey key = null; - private final byte[] salt = "notRequiredInThisScenario".getBytes(); - - @Override - public String generateExternalPendingRequestId() throws EAAFException { - try { - final String toSign = buildInternalToken(Random.nextLongRandom(), DateTime.now()); - final StringBuilder externalPendingRequestId= new StringBuilder(); - externalPendingRequestId.append(toSign); - externalPendingRequestId.append(TOKEN_SEPARATOR); - externalPendingRequestId.append(Base64.getEncoder().encodeToString(calculateHMAC(toSign))); - return Base64.getUrlEncoder().encodeToString(externalPendingRequestId.toString().getBytes("UTF-8")); - - } catch (final UnsupportedEncodingException e) { - throw new EAAFException("internal.99", new Object[] {e.getMessage()}, e); - - } - - } - - @Override - public String getPendingRequestIdWithOutChecks(String externalPendingReqId) throws PendingReqIdValidationException { - final String[] tokenElements = extractTokens(externalPendingReqId); - return tokenElements[1]; - - } - - @Override - public String validateAndGetPendingRequestId(String externalPendingReqId) throws PendingReqIdValidationException { - try { - final String[] tokenElements = extractTokens(externalPendingReqId); - final String internalPendingReqId = tokenElements[1]; - final DateTime timeStamp = TOKEN_TEXTUAL_DATE_FORMAT.parseDateTime(tokenElements[0]); - - log.trace("Checking HMAC from externalPendingReqId ... "); - final byte[] tokenDigest = Base64.getDecoder().decode(tokenElements[2]); - final byte[] refDigist = calculateHMAC(buildInternalToken(internalPendingReqId, timeStamp)); - if (!Arrays.equals(tokenDigest, refDigist)) { - log.warn("Digest of Token does NOT match"); - log.debug("Token: {} | Ref: {}", tokenDigest, refDigist); - throw new PendingReqIdValidationException(null, "Digest of pendingRequestId does NOT match"); - - } - log.debug("PendingRequestId HMAC digest check successful"); - - log.trace("Checking valid period ... "); - final DateTime now = DateTime.now(); - if (timeStamp.withFieldAdded( - DurationFieldType.seconds(), maxPendingRequestIdLifeTime).isBefore(now)) { - log.warn("Token exceeds the valid period"); - log.debug("Token: {} | Now: {}", timeStamp, now ); - throw new PendingReqIdValidationException(internalPendingReqId, "PendingRequestId exceeds the valid period"); - - } - log.debug("Token valid-period check successful"); - - return internalPendingReqId; - - - } catch (final IllegalArgumentException | EAAFIllegalStateException e) { - log.warn("Token is NOT a valid String. Msg: {}", e.getMessage()); - log.debug("TokenValue: {}", externalPendingReqId); - throw new PendingReqIdValidationException(null, "PendingReqId is NOT a valid String", e); - - } - } - - @NonNull - private String[] extractTokens(@Nullable String externalPendingReqId) throws PendingReqIdValidationException { - if (StringUtils.isEmpty(externalPendingReqId)) { - log.info("PendingReqId is 'null' or empty"); - throw new PendingReqIdValidationException(null, "PendingReqId is 'null' or empty"); - - } - - log.trace("RAW external pendingReqId: {}", externalPendingReqId); - final byte[] externalPendingReqIdBytes = Base64.getUrlDecoder().decode(externalPendingReqId); - - if (externalPendingReqIdBytes.length > maxPendingReqIdSize) { - log.warn("pendingReqId size exceeds {}", maxPendingReqIdSize); - throw new PendingReqIdValidationException(null, "pendingReqId exceeds max.size: " + maxPendingReqIdSize); - - } - - final String stringToken = new String(externalPendingReqIdBytes); - if (StringUtils.countMatches(stringToken, TOKEN_SEPARATOR) == ENCODED_TOKEN_PARTS - 1) { - final String[] tokenElements = StringUtils.split(stringToken, - TOKEN_SEPARATOR, ENCODED_TOKEN_PARTS); - return tokenElements; - - } else { - log.warn("PendingRequestId has an unvalid format"); - log.debug("PendingRequestId: {}", stringToken); - throw new PendingReqIdValidationException(null, "PendingReqId has an unvalid format"); - - } - - } - - - @PostConstruct - private void initialize() throws EAAFConfigurationException { - log.debug("Initializing " + this.getClass().getName() + " ... "); - - final String pendingReqIdDigistSecret = baseConfig.getBasicConfiguration(CONFIG_PROP_PENDINGREQUESTID_DIGIST_SECRET); - if (StringUtils.isEmpty(pendingReqIdDigistSecret)) - throw new EAAFConfigurationException("config.08", new Object[] {CONFIG_PROP_PENDINGREQUESTID_DIGIST_SECRET}); - - digistAlgorithm = baseConfig.getBasicConfiguration(CONFIG_PROP_PENDINGREQUESTID_DIGIST_ALGORITHM, DEFAULT_PENDINGREQUESTID_DIGIST_ALGORITHM); - - maxPendingRequestIdLifeTime = Integer.valueOf( - baseConfig.getBasicConfiguration(CONFIG_PROP_PENDINGREQUESTID_MAX_LIFETIME, DEFAULT_PENDINGREQUESTID_MAX_LIFETIME)); - - try { - final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WITHHMACSHA256"); - final KeySpec spec = new PBEKeySpec(pendingReqIdDigistSecret.toCharArray(), salt, 10000, 128); - key = keyFactory.generateSecret(spec); - - - } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { - log.error("Can NOT initialize TokenService with configuration object", e); - throw new EAAFConfigurationException("config.09", - new Object[] { CONFIG_PROP_PENDINGREQUESTID_DIGIST_SECRET, - "Can NOT generate HMAC key"}, - e); - - } - - log.info(this.getClass().getName() + " initialized with digistAlg: {} and maxLifeTime: {}", digistAlgorithm, maxPendingRequestIdLifeTime); - - } - - private String buildInternalToken(String internalPendingReqId, DateTime now) { - return new StringBuilder() - .append(TOKEN_TEXTUAL_DATE_FORMAT.print(now)) - .append(TOKEN_SEPARATOR) - .append(internalPendingReqId).toString(); - } - - private byte[] calculateHMAC(String toSign) throws EAAFIllegalStateException { - try { - final Mac mac = Mac.getInstance(digistAlgorithm); - mac.init(key); - return mac.doFinal(toSign.getBytes("UTF-8")); - - } catch (UnsupportedEncodingException | NoSuchAlgorithmException | InvalidKeyException e) { - log.error("Can NOT generate secure pendingRequestId", e); - throw new EAAFIllegalStateException(new Object[] {"Can NOT caluclate digist for secure pendingRequestId"}, e); - - } - - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/ServletUtils.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/ServletUtils.java deleted file mode 100644 index 38e873e2..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/ServletUtils.java +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ - -package at.gv.egiz.eaaf.core.impl.utils; - -import javax.servlet.http.HttpServletRequest; - -public class ServletUtils { - - - public static String getBaseUrl( HttpServletRequest request ) { - if ( ( request.getServerPort() == 80 ) || - ( request.getServerPort() == 443 ) ) - return request.getScheme() + "://" + - request.getServerName() + - request.getContextPath(); - else - return request.getScheme() + "://" + - request.getServerName() + ":" + request.getServerPort() + - request.getContextPath(); - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SimplePendingRequestIdGenerationStrategy.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SimplePendingRequestIdGenerationStrategy.java deleted file mode 100644 index 6b8fe9b7..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SimplePendingRequestIdGenerationStrategy.java +++ /dev/null @@ -1,38 +0,0 @@ -package at.gv.egiz.eaaf.core.impl.utils; - -import org.apache.commons.lang3.StringUtils; - -import at.gv.egiz.eaaf.core.api.utils.IPendingRequestIdGenerationStrategy; -import at.gv.egiz.eaaf.core.exceptions.PendingReqIdValidationException; - -/** - * Simple pendingRequestId generation strategy that facilitates no extended validation - * - * @author tlenz - * - */ -public class SimplePendingRequestIdGenerationStrategy implements IPendingRequestIdGenerationStrategy { - - @Override - public String generateExternalPendingRequestId() { - return Random.nextLongRandom(); - - } - - @Override - public String validateAndGetPendingRequestId(String pendingReqId) throws PendingReqIdValidationException { - return getPendingRequestIdWithOutChecks(pendingReqId); - - } - - @Override - public String getPendingRequestIdWithOutChecks(String externalPendingReqId) throws PendingReqIdValidationException { - if (StringUtils.isEmpty(externalPendingReqId)) - throw new PendingReqIdValidationException(externalPendingReqId, "PendingRequestId is empty or null"); - - - - return externalPendingReqId; - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/StreamUtils.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/StreamUtils.java deleted file mode 100644 index 530da777..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/StreamUtils.java +++ /dev/null @@ -1,201 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ - - -package at.gv.egiz.eaaf.core.impl.utils; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintStream; - -/** - * Utility methods for streams. - * - * @author Patrick Peck - * @version $Id$ - */ -public class StreamUtils { - - /** - * Compare the contents of two InputStreams. - * - * @param is1 The 1st InputStream to compare. - * @param is2 The 2nd InputStream to compare. - * @return boolean true, if both streams contain the exactly the - * same content, false otherwise. - * @throws IOException An error occurred reading one of the streams. - */ - public static boolean compareStreams(InputStream is1, InputStream is2) - throws IOException { - - byte[] buf1 = new byte[256]; - byte[] buf2 = new byte[256]; - int length1; - int length2; - - try { - while (true) { - length1 = is1.read(buf1); - length2 = is2.read(buf2); - - if (length1 != length2) { - return false; - } - if (length1 <= 0) { - return true; - } - if (!compareBytes(buf1, buf2, length1)) { - return false; - } - } - } catch (IOException e) { - throw e; - } finally { - // close both streams - try { - is1.close(); - is2.close(); - } catch (IOException e) { - // ignore this - } - } - } - - /** - * Compare two byte arrays, up to a given maximum length. - * - * @param b1 1st byte array to compare. - * @param b2 2nd byte array to compare. - * @param length The maximum number of bytes to compare. - * @return true, if the byte arrays are equal, false - * otherwise. - */ - private static boolean compareBytes(byte[] b1, byte[] b2, int length) { - if (b1.length != b2.length) { - return false; - } - - for (int i = 0; i < b1.length && i < length; i++) { - if (b1[i] != b2[i]) { - return false; - } - } - - return true; - } - - /** - * Reads a byte array from a stream. - * @param in The InputStream to read. - * @return The bytes contained in the given InputStream. - * @throws IOException on any exception thrown - */ - public static byte[] readStream(InputStream in) throws IOException { - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - copyStream(in, out, null); - - /* - ByteArrayOutputStream out = new ByteArrayOutputStream(); - int b; - while ((b = in.read()) >= 0) - out.write(b); - - */ - in.close(); - return out.toByteArray(); - } - - /** - * Reads a String from a stream, using given encoding. - * @param in The InputStream to read. - * @param encoding The character encoding to use for converting the bytes - * of the InputStream into a String. - * @return The content of the given InputStream converted into - * a String. - * @throws IOException on any exception thrown - */ - public static String readStream(InputStream in, String encoding) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - copyStream(in, out, null); - - /* - ByteArrayOutputStream out = new ByteArrayOutputStream(); - int b; - while ((b = in.read()) >= 0) - out.write(b); - */ - in.close(); - return out.toString(encoding); - } - - /** - * Reads all data (until EOF is reached) from the given source to the - * destination stream. If the destination stream is null, all data is dropped. - * It uses the given buffer to read data and forward it. If the buffer is - * null, this method allocates a buffer. - * - * @param source The stream providing the data. - * @param destination The stream that takes the data. If this is null, all - * data from source will be read and discarded. - * @param buffer The buffer to use for forwarding. If it is null, the method - * allocates a buffer. - * @exception IOException If reading from the source or writing to the - * destination fails. - */ - private static void copyStream(InputStream source, OutputStream destination, byte[] buffer) throws IOException { - if (source == null) { - throw new NullPointerException("Argument \"source\" must not be null."); - } - if (buffer == null) { - buffer = new byte[8192]; - } - - if (destination != null) { - int bytesRead; - while ((bytesRead = source.read(buffer)) >= 0) { - destination.write(buffer, 0, bytesRead); - } - } else { - while (source.read(buffer) >= 0); - } - } - - /** - * Gets the stack trace of the Throwable passed in as a string. - * @param t The Throwable. - * @return a String representing the stack trace of the Throwable. - */ - public static String getStackTraceAsString(Throwable t) - { - ByteArrayOutputStream stackTraceBIS = new ByteArrayOutputStream(); - t.printStackTrace(new PrintStream(stackTraceBIS)); - return new String(stackTraceBIS.toByteArray()); - } -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/TransactionIDUtils.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/TransactionIDUtils.java deleted file mode 100644 index 2e016848..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/TransactionIDUtils.java +++ /dev/null @@ -1,101 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.utils; - - -import at.gv.egiz.eaaf.core.api.IRequest; - -/** - * @author tlenz - * - */ -public class TransactionIDUtils { - - //MDC variables for logging - public static final String MDC_TRANSACTION_ID = "transactionId"; - public static final String MDC_SESSION_ID = "sessionId"; - public static final String MDC_SERVICEPROVIDER_ID = "oaId"; - - /** - * Set all MDC variables from pending request to this threat context
- * These includes SessionID, TransactionID, and unique service-provider identifier - * - * @param pendingRequest - */ - public static void setAllLoggingVariables(IRequest pendingRequest) { - setTransactionId(pendingRequest.getUniqueTransactionIdentifier()); - setSessionId(pendingRequest.getUniqueSessionIdentifier()); - setServiceProviderId(pendingRequest.getServiceProviderConfiguration().getUniqueIdentifier()); - - } - - /** - * Remove all MDC variables from this threat context - * - */ - public static void removeAllLoggingVariables() { - removeSessionId(); - removeTransactionId(); - removeServiceProviderId(); - - } - - - public static void setServiceProviderId(String oaUniqueId) { - org.slf4j.MDC.put(MDC_SERVICEPROVIDER_ID, oaUniqueId); - - } - - public static void removeServiceProviderId() { - org.slf4j.MDC.remove(MDC_SERVICEPROVIDER_ID); - - } - - public static void setTransactionId(String pendingRequestID) { - org.slf4j.MDC.put(MDC_TRANSACTION_ID, - "TID-" + pendingRequestID); - - } - - public static void removeTransactionId() { - org.slf4j.MDC.remove(MDC_TRANSACTION_ID); - - } - - public static void setSessionId(String uniqueSessionId) { - org.slf4j.MDC.put(MDC_SESSION_ID, - "SID-" + uniqueSessionId); - - } - - public static void removeSessionId() { - org.slf4j.MDC.remove(MDC_SESSION_ID); - - } - - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/X509Utils.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/X509Utils.java deleted file mode 100644 index b3fb42c4..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/X509Utils.java +++ /dev/null @@ -1,62 +0,0 @@ -package at.gv.egiz.eaaf.core.impl.utils; - -import java.security.cert.X509Certificate; -import java.util.List; - -import javax.security.auth.x500.X500Principal; - -public class X509Utils { - - /** - * Sorts the Certificate Chain by IssuerDN and SubjectDN. The [0]-Element should be the Hostname, - * the last Element should be the Root Certificate. - * - * @param certs - * The first element must be the correct one. - * @return sorted Certificate Chain - */ - public static List sortCertificates( - List certs) - { - int length = certs.size(); - if (certs.size() <= 1) - { - return certs; - } - - for (X509Certificate cert : certs) - { - if (cert == null) - { - throw new NullPointerException(); - } - } - - for (int i = 0; i < length; i++) - { - boolean found = false; - X500Principal issuer = certs.get(i).getIssuerX500Principal(); - for (int j = i + 1; j < length; j++) - { - X500Principal subject = certs.get(j).getSubjectX500Principal(); - if (issuer.equals(subject)) - { - // sorting necessary? - if (i + 1 != j) - { - X509Certificate tmp = certs.get(i + 1); - certs.set(i + 1, certs.get(j)); - certs.set(j, tmp); - } - found = true; - } - } - if (!found) - { - break; - } - } - - return certs; - } -} diff --git a/eaaf_core_utils/pom.xml b/eaaf_core_utils/pom.xml new file mode 100644 index 00000000..6168f601 --- /dev/null +++ b/eaaf_core_utils/pom.xml @@ -0,0 +1,150 @@ + + + 4.0.0 + + at.gv.egiz + eaaf + 1.0.12-SNAPSHOT + + at.gv.egiz.eaaf + eaaf_core_utils + Utils for EAAF core components + Core component Utils for identity managment implementations + + + + European Union Public License, version 1.2 (EUPL-1.2) + https://opensource.org/licenses/EUPL-1.2 + repo + + + + + + Thomas Lenz + thomas.lenz@egiz.gv.at + eGovernment Innovation Center (EGIZ) + https://www.egiz.gv.at + + + + + UTF-8 + + + + + at.gv.egiz.eaaf + eaaf_core_api + + + + org.springframework + spring-webmvc + + + + org.slf4j + slf4j-api + + + org.apache.commons + commons-lang3 + + + org.apache.httpcomponents + httpclient + + + org.apache.httpcomponents + httpcore + + + com.google.code.findbugs + jsr305 + + + joda-time + joda-time + + + javax.servlet + javax.servlet-api + provided + + + + junit + junit + test + + + org.springframework + spring-test + test + + + + + + eaaf_core_utils + + + + src/main/resources + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.7.0 + + 1.8 + 1.8 + + + + + compile + testCompile + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.0 + + + + test-jar + + + + + + + + maven-surefire-plugin + ${surefire.version} + + 1 + + + + org.apache.maven.surefire + surefire-junit47 + ${surefire.version} + + + + + + + + + diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/support/SecureRandomHolder.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/support/SecureRandomHolder.java new file mode 100644 index 00000000..a297367f --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/support/SecureRandomHolder.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright 2017 Graz University of Technology + * EAAF-Core Components has been developed in a cooperation between EGIZ, + * A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + *******************************************************************************/ +/******************************************************************************* + *******************************************************************************/ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eaaf.core.impl.idp.process.support; + +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; + +/** + * Holder for a secure random instance following the initialization on demand holder design pattern. The secure random + * instance is a singleton that is initialized on first usage. + * + * @author tknall + * + */ +public class SecureRandomHolder { + + private SecureRandomHolder() { + } + + private static final SecureRandom SRND_INSTANCE; + static { + try { + SRND_INSTANCE = SecureRandom.getInstance("SHA1PRNG"); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("Unable to instantiate SHA1PRNG.", e); + } + } + + /** + * Returns a secure random generator instance. + * @return The secure random instance. + */ + public static SecureRandom getInstance() { + return SecureRandomHolder.SRND_INSTANCE; + } + +} \ No newline at end of file diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/ArrayUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/ArrayUtils.java new file mode 100644 index 00000000..8585bc05 --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/ArrayUtils.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright 2017 Graz University of Technology + * EAAF-Core Components has been developed in a cooperation between EGIZ, + * A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + *******************************************************************************/ +package at.gv.egiz.eaaf.core.impl.utils; + +import java.util.List; + +public class ArrayUtils { + + /** + * Check if a String 's' is part of a List 'l' in qualsIgnoreCase mode + * + * @param s Search String + * @param l List of String elements + * @return true if 's' is in 'l', otherwise false + */ + public static boolean containsCaseInsensitive(String s, List l){ + if (l == null || s == null) + return false; + + return l.stream().anyMatch(x -> x.equalsIgnoreCase(s)); + + } + +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/DataURLBuilder.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/DataURLBuilder.java new file mode 100644 index 00000000..a81fafbc --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/DataURLBuilder.java @@ -0,0 +1,113 @@ +/******************************************************************************* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + ******************************************************************************/ +/* + * Copyright 2003 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +package at.gv.egiz.eaaf.core.impl.utils; + +import org.apache.commons.lang3.StringUtils; + +import at.gv.egiz.eaaf.core.api.data.EAAFConstants; + +/** + * Builds a DataURL parameter meant for the security layer implementation + * to respond to. + * + * @author Paul Ivancsics + * @version $Id$ + */ +public class DataURLBuilder { + + /** + * Constructor for DataURLBuilder. + */ + public DataURLBuilder() { + super(); + } + + /** + * Constructs a data URL for VerifyIdentityLink or VerifyAuthenticationBlock, + * including the MOASessionID as a parameter. + * + * @param authBaseURL base URL (context path) of the MOA ID Authentication component, + * including a trailing '/' + * @param authServletName request part of the data URL + * @param pendingReqId sessionID to be included in the dataURL + * @return String + */ + public String buildDataURL(String authBaseURL, String authServletName, String pendingReqId) { + String dataURL; + if (!authBaseURL.endsWith("/")) + authBaseURL += "/"; + + if (authServletName.startsWith("/")) + authServletName = authServletName.substring(1); + + dataURL = authBaseURL + authServletName; + + if (StringUtils.isNotEmpty(pendingReqId)) + dataURL = addParameter(dataURL, EAAFConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID, pendingReqId); + + return dataURL; + } + + /** + * Method addParameter. + * @param urlString represents the url + * @param paramname is the parameter to be added + * @param value is the value of that parameter + * @return String + */ + private String addParameter(String urlString, String paramname, String value) { + String url = urlString; + if (paramname != null) { + if (url.indexOf("?") < 0) + url += "?"; + else + url += "&"; + url += paramname + "=" + value; + } + return url; + } +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/FileUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/FileUtils.java new file mode 100644 index 00000000..fff83e53 --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/FileUtils.java @@ -0,0 +1,175 @@ +/******************************************************************************* + * Copyright 2017 Graz University of Technology + * EAAF-Core Components has been developed in a cooperation between EGIZ, + * A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + *******************************************************************************/ +/******************************************************************************* + *******************************************************************************/ +/******************************************************************************* + *******************************************************************************/ + + +package at.gv.egiz.eaaf.core.impl.utils; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class FileUtils { + private static final Logger log = LoggerFactory.getLogger(FileUtils.class); + + + /** + * Reads a file, given by URL, into a byte array. + * @param urlString file URL + * @return file content + * @throws IOException on any exception thrown + */ + public static byte[] readURL(String urlString) throws IOException { + final URL url = new URL(urlString); + final InputStream in = new BufferedInputStream(url.openStream()); + final byte[] content = StreamUtils.readStream(in); + in.close(); + return content; + } + + /** + * Reads a file from a resource. + * @param name resource name + * @return file content as a byte array + * @throws IOException on any exception thrown + */ + public static byte[] readResource(String name) throws IOException { + final ClassLoader cl = FileUtils.class.getClassLoader(); + final BufferedInputStream in = new BufferedInputStream(cl.getResourceAsStream(name)); + final byte[] content = StreamUtils.readStream(in); + in.close(); + return content; + } + /** + * Reads a file from a resource. + * @param name filename + * @param encoding character encoding + * @return file content + * @throws IOException on any exception thrown + */ + public static String readResource(String name, String encoding) throws IOException { + final byte[] content = readResource(name); + return new String(content, encoding); + } + + + /** + * Returns the absolute URL of a given url which is relative to the parameter root + * @param url + * @param root + * @return String + * @throws MalformedURLException + */ + public static String makeAbsoluteURL(String url, URI root) throws MalformedURLException { + if (root != null) + return makeAbsoluteURL(url, root.toURL().toString()); + else + return makeAbsoluteURL(url, StringUtils.EMPTY); + + } + + /** + * Returns the absolute URL of a given url which is relative to the parameter root + * @param url + * @param root + * @return String + */ + public static String makeAbsoluteURL(String url, String root) { + //if url is relative to rootConfigFileDirName make it absolute + + log.trace("Making AbsoluteURL URL: " + url + " Root-Path: " + root); + + if (StringUtils.isEmpty(root)) + root = null; + + File keyFile; + String newURL = url; + + if(null == url) return null; + + if (url.startsWith("http:") || url.startsWith("https:") || url.startsWith("file:") || url.startsWith("ftp:")) { + return url; + + } else { + // check if absolute - if not make it absolute + keyFile = new File(url); + if (!keyFile.isAbsolute()) { + keyFile = new File(root, url); + + if (keyFile.toString().startsWith("file:")) + newURL = keyFile.toString(); + + else + newURL = keyFile.toURI().toString(); + + } + return newURL; + } + } + + + private static void copy( InputStream fis, OutputStream fos ) + { + try + { + final byte[] buffer = new byte[ 0xFFFF ]; + for ( int len; (len = fis.read(buffer)) != -1; ) + fos.write( buffer, 0, len ); + } + catch( final IOException e ) { + System.err.println( e ); + } + finally { + if ( fis != null ) + try { fis.close(); } catch ( final IOException e ) { e.printStackTrace(); } + if ( fos != null ) + try { fos.close(); } catch ( final IOException e ) { e.printStackTrace(); } + } + } + + public static void copyFile(File src, File dest) + { + try + { + copy( new FileInputStream( src ), new FileOutputStream( dest ) ); + } + catch( final IOException e ) { + e.printStackTrace(); + } + } + +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HTTPUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HTTPUtils.java new file mode 100644 index 00000000..cf1abaa7 --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HTTPUtils.java @@ -0,0 +1,178 @@ +/******************************************************************************* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + ******************************************************************************/ +/* + * Copyright 2003 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +package at.gv.egiz.eaaf.core.impl.utils; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang3.StringUtils; + + +/** + * + * @author Rudolf Schamberger + * + */ +public class HTTPUtils { + +// /** +// * Utility used to obtainin correct encoded HTTP content. +// * Reads a given Content adressed by HTTP-URL into String. +// * Content encoding is considered by using the Content-Type HTTP header charset value. +// * @param URL HTTP URL to read from. +// * @return String representation of content +// * @throws IOException on data-reading problems +// */ +// public static String readHttpURL(String URL) +// throws IOException { +// +// URL url = new URL(URL); +// HttpURLConnection conn = (HttpURLConnection)url.openConnection(); +// conn.setRequestMethod("GET"); +// String contentType = conn.getContentType(); +// RE regExp = null; +// try { +// regExp = new RE("(;.*charset=)(\"*)(.*[^\"])"); +// } catch (RESyntaxException e) { +// //RESyntaxException is not possible = expr. is costant +// } +// boolean charsetSupplied = regExp.match(contentType); +// String encoding = "ISO-8859-1"; //default HTTP encoding +// if (charsetSupplied) { +// encoding = regExp.getParen(3); +// } +// InputStream instream = new BufferedInputStream(conn.getInputStream()); +// InputStreamReader isr = new InputStreamReader(instream, encoding); +// Reader in = new BufferedReader(isr); +// int ch; +// StringBuffer buffer = new StringBuffer(); +// while ((ch = in.read()) > -1) { +// buffer.append((char)ch); +// } +// in.close(); +// conn.disconnect(); +// return buffer.toString(); +// } + + /** + * Helper method to retrieve server URL including context path + * @param request HttpServletRequest + * @return Server URL including context path (e.g. http://localhost:8443/moa-id-auth + */ + public static String getBaseURL(HttpServletRequest request) { + StringBuffer buffer = new StringBuffer(getServerURL(request)); + + // add context path if available + String contextPath = request.getContextPath(); + if (!StringUtils.isEmpty(contextPath)) { + buffer.append(contextPath); + } + + return buffer.toString(); + } + + /** + * Helper method to retrieve server URL + * @param request HttpServletRequest + * @return Server URL (e.g. http://localhost:8443) + */ + public static String getServerURL(HttpServletRequest request) { + StringBuffer buffer = new StringBuffer(); + + // get protocol + String protocol = request.getScheme(); + buffer.append(protocol).append("://"); + + // server name + buffer.append(request.getServerName()); + + // add port if necessary + int port = request.getServerPort(); + if ((protocol.equals("http") && port != 80) || (protocol.equals("https") && port != 443)) { + buffer.append(':'); + buffer.append(port); + } + + return buffer.toString(); + } + + /** + * Extract the IDP PublicURLPrefix from authrequest + * + * @param req HttpServletRequest + * @return PublicURLPrefix which ends always without / + */ + public static String extractAuthURLFromRequest(HttpServletRequest req) { + String authURL = req.getScheme() + "://" + req.getServerName(); + if ((req.getScheme().equalsIgnoreCase("https") && req.getServerPort()!=443) || (req.getScheme().equalsIgnoreCase("http") && req.getServerPort()!=80)) { + authURL = authURL.concat(":" + req.getServerPort()); + } + authURL = authURL.concat(req.getContextPath()); + return authURL; + + } + + /** + * Extract the IDP requested URL from authrequest + * + * @param req HttpServletRequest + * @return RequestURL which ends always without / + */ + public static String extractAuthServletPathFromRequest(HttpServletRequest req) { + return extractAuthURLFromRequest(req).concat(req.getServletPath()); + + } + + public static String addURLParameter(String url, String paramname, + String paramvalue) { + String param = paramname + "=" + paramvalue; + if (url.indexOf("?") < 0) + return url + "?" + param; + else + return url + "&" + param; + } + +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HttpClientFactory.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HttpClientFactory.java new file mode 100644 index 00000000..a141d92d --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HttpClientFactory.java @@ -0,0 +1,152 @@ +package at.gv.egiz.eaaf.core.impl.utils; + +import java.security.NoSuchAlgorithmException; + +import javax.annotation.PostConstruct; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; + +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; +import org.apache.http.ProtocolException; +import org.apache.http.client.RedirectStrategy; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.conn.socket.LayeredConnectionSocketFactory; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.DefaultRedirectStrategy; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.protocol.HttpContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; + +public class HttpClientFactory implements IHttpClientFactory { + private static final Logger log = LoggerFactory.getLogger(HttpClientFactory.class); + @Autowired(required=true) private IConfiguration basicConfig; + + public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_USE = "client.http.connection.pool.use"; + public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL = "client.http.connection.pool.maxtotal"; + public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE = "client.http.connection.pool.maxperroute"; + public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_SOCKET = "client.http.connection.timeout.socket"; + public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_CONNECTION = "client.http.connection.timeout.connection"; + public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_REQUEST = "client.http.connection.timeout.request"; + public static final String PROP_CONFIG_CLIENT_HTTP_SSL_HOSTNAMEVERIFIER_TRUSTALL = "client.http.ssl.hostnameverifier.trustall"; + + // default configuration values + public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_SOCKET = "15"; + public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_CONNECTION = "15"; + public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_REQUEST = "30"; + public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL = "500"; + public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE = "100"; + + private HttpClientBuilder httpClientBuilder = null; + + /* (non-Javadoc) + * @see at.gv.egiz.eaaf.core.impl.utils.IHttpClientFactory#getHttpClient() + */ + @Override + public CloseableHttpClient getHttpClient() { + return getHttpClient(true); + + } + + @Override + public CloseableHttpClient getHttpClient(boolean followRedirects) { + RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); + if (!followRedirects) + redirectStrategy = new RedirectStrategy() { + + @Override + public boolean isRedirected(HttpRequest request, HttpResponse response, HttpContext context) + throws ProtocolException { + return false; + } + + @Override + public HttpUriRequest getRedirect(HttpRequest request, HttpResponse response, HttpContext context) + throws ProtocolException { + return null; + } + }; + + return httpClientBuilder + .setRedirectStrategy(redirectStrategy) + .build(); + + } + + @PostConstruct + private void initalize() { + //initialize http client + log.trace("Initializing HTTP Client-builder ... "); + httpClientBuilder = HttpClients.custom(); + + //set default request configuration + final RequestConfig requestConfig = RequestConfig.custom() + .setConnectTimeout(Integer.valueOf(basicConfig.getBasicConfiguration( + PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_CONNECTION, + DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_CONNECTION)) * 1000) + .setConnectionRequestTimeout(Integer.valueOf(basicConfig.getBasicConfiguration( + PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_REQUEST, + DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_REQUEST)) * 1000) + .setSocketTimeout(Integer.valueOf(basicConfig.getBasicConfiguration( + PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_SOCKET, + DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_SOCKET)) * 1000) + .build(); + httpClientBuilder.setDefaultRequestConfig(requestConfig); + + //set pool connection if requested + if (basicConfig.getBasicConfigurationBoolean( + PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_USE, + true)) { + final PoolingHttpClientConnectionManager pool = new PoolingHttpClientConnectionManager(); + pool.setDefaultMaxPerRoute(Integer.valueOf(basicConfig.getBasicConfiguration( + PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE, + DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE))); + pool.setMaxTotal(Integer.valueOf(basicConfig.getBasicConfiguration( + PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL, + DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL))); + + + + httpClientBuilder.setConnectionManager(pool); + log.debug("Initalize http-client pool with, maxTotal: {} maxPerRoute: {}", pool.getMaxTotal(), pool.getDefaultMaxPerRoute()); + + } + + try { + log.trace("Initializing SSL Context ... "); + final SSLContext sslContext = SSLContext.getDefault(); + HostnameVerifier hostnameVerifier = null; + if (basicConfig.getBasicConfigurationBoolean( + PROP_CONFIG_CLIENT_HTTP_SSL_HOSTNAMEVERIFIER_TRUSTALL, + false)) { + hostnameVerifier = new NoopHostnameVerifier(); + log.warn("HTTP client-builder deactivates SSL Host-name verification!"); + } + + final LayeredConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext , hostnameVerifier); + httpClientBuilder.setSSLSocketFactory(sslSocketFactory ); + + } catch (final NoSuchAlgorithmException e) { + log.warn("HTTP client-builder can NOT initialze SSL-Context", e); + + } + + + log.info("HTTP client-builder successfuly initialized"); + + } + + + + + +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/IHttpClientFactory.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/IHttpClientFactory.java new file mode 100644 index 00000000..1975fb52 --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/IHttpClientFactory.java @@ -0,0 +1,21 @@ +package at.gv.egiz.eaaf.core.impl.utils; + +import org.apache.http.impl.client.CloseableHttpClient; + +public interface IHttpClientFactory { + + /** + * Return an instance of a Apache HTTP client that follows http redirects automatically + * + * @return + */ + CloseableHttpClient getHttpClient(); + + /** + * Return an instance of a Apache HTTP client + * @param followRedirects + * @return + */ + CloseableHttpClient getHttpClient(boolean followRedirects); + +} \ No newline at end of file diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/KeyStoreUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/KeyStoreUtils.java new file mode 100644 index 00000000..e3d74066 --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/KeyStoreUtils.java @@ -0,0 +1,199 @@ +/******************************************************************************* + * Copyright 2017 Graz University of Technology + * EAAF-Core Components has been developed in a cooperation between EGIZ, + * A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + *******************************************************************************/ +/******************************************************************************* + *******************************************************************************/ +/******************************************************************************* + *******************************************************************************/ + + +package at.gv.egiz.eaaf.core.impl.utils; + +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; + +/** + * Utility for creating and loading key stores. + * + * @author Paul Ivancsics + * @version $Id$ + */ +public class KeyStoreUtils { + + /** + * JAVA KeyStore + */ + private static final String KEYSTORE_TYPE_JKS = "JKS"; + + /** + * PKCS12 KeyStore + */ + private static final String KEYSTORE_TYPE_PKCS12 = "PKCS12"; + + + + /** + * Loads a key store from file. + * + * @param keystoreType key store type + * @param urlString URL of key store + * @param password password protecting the key store + * @return key store loaded + * @throws IOException thrown while reading the key store from file + * @throws GeneralSecurityException thrown while creating the key store + */ + public static KeyStore loadKeyStore( + String keystoreType, + String urlString, + String password) + throws IOException, GeneralSecurityException { + + URL keystoreURL = new URL(urlString); + InputStream in = keystoreURL.openStream(); + return loadKeyStore(keystoreType, in, password); + } + /** + * Loads a key store from an InputStream, and + * closes the InputStream. + * + * @param keystoreType key store type + * @param in input stream + * @param password password protecting the key store + * @return key store loaded + * @throws IOException thrown while reading the key store from the stream + * @throws GeneralSecurityException thrown while creating the key store + */ + public static KeyStore loadKeyStore( + String keystoreType, + InputStream in, + String password) + throws IOException, GeneralSecurityException { + + char[] chPassword = null; + if (password != null) + chPassword = password.toCharArray(); + KeyStore ks = KeyStore.getInstance(keystoreType); + ks.load(in, chPassword); + in.close(); + return ks; + } + /** + * Creates a key store from X509 certificate files, aliasing them with + * the index in the String[], starting with "0". + * + * @param keyStoreType key store type + * @param certFilenames certificate filenames + * @return key store created + * @throws IOException thrown while reading the certificates from file + * @throws GeneralSecurityException thrown while creating the key store + */ + public static KeyStore createKeyStore( + String keyStoreType, + String[] certFilenames) + throws IOException, GeneralSecurityException { + + KeyStore ks = KeyStore.getInstance(keyStoreType); + ks.load(null, null); + for (int i = 0; i < certFilenames.length; i++) { + Certificate cert = loadCertificate(certFilenames[i]); + ks.setCertificateEntry("" + i, cert); + } + return ks; + } + + /** + * Loads an X509 certificate from file. + * @param certFilename filename + * @return the certificate loaded + * @throws IOException thrown while reading the certificate from file + * @throws GeneralSecurityException thrown while creating the certificate + */ + private static Certificate loadCertificate(String certFilename) + throws IOException, GeneralSecurityException { + + FileInputStream in = new FileInputStream(certFilename); + CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); + Certificate cert = certFactory.generateCertificate(in); + in.close(); + return cert; + } + + + /** + * Loads a keyStore without knowing the keyStore type + * @param keyStorePath URL to the keyStore + * @param password Password protecting the keyStore + * @return keyStore loaded + * @throws KeyStoreException thrown if keyStore cannot be loaded + * @throws FileNotFoundException + * @throws IOException + */ + public static KeyStore loadKeyStore(String keyStorePath, String password) throws KeyStoreException, IOException{ + + //InputStream is = new FileInputStream(keyStorePath); + URL keystoreURL = new URL(keyStorePath); + InputStream in = keystoreURL.openStream(); + InputStream isBuffered = new BufferedInputStream(in); + return loadKeyStore(isBuffered, password); + + } + + /** + * Loads a keyStore without knowing the keyStore type + * @param in input stream + * @param password Password protecting the keyStore + * @return keyStore loaded + * @throws KeyStoreException thrown if keyStore cannot be loaded + * @throws FileNotFoundException + * @throws IOException + */ +public static KeyStore loadKeyStore(InputStream is, String password) throws KeyStoreException, IOException{ + is.mark(1024*1024); + KeyStore ks = null; + try { + try { + ks = loadKeyStore(KEYSTORE_TYPE_PKCS12, is, password); + } catch (IOException e2) { + is.reset(); + ks = loadKeyStore(KEYSTORE_TYPE_JKS, is, password); + } + } catch(Exception e) { + e.printStackTrace(); + + } + return ks; + + } + + + + +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/KeyValueUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/KeyValueUtils.java new file mode 100644 index 00000000..e753f19f --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/KeyValueUtils.java @@ -0,0 +1,375 @@ +/******************************************************************************* + * Copyright 2017 Graz University of Technology + * EAAF-Core Components has been developed in a cooperation between EGIZ, + * A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + *******************************************************************************/ +/******************************************************************************* + *******************************************************************************/ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eaaf.core.impl.utils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Properties; +import java.util.Set; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author tlenz + * + */ +public class KeyValueUtils { + private static final Logger log = LoggerFactory.getLogger(KeyValueUtils.class); + + public static final String KEY_DELIMITER = "."; + public static final String CSV_DELIMITER = ","; + public static final String KEYVVALUEDELIMITER = "="; + public static final String DEFAULT_VALUE = "default"; + + /** + * Convert Java properties into a Map + *

+ * Important: The key/values from properties must be of type String! + * + * @param properties + * @return + */ + public static Map convertPropertiesToMap(Properties properties) { + return new HashMap((Map) properties); + + //INFO Java8 solution ;) +// return properties.entrySet().stream().collect( +// Collectors.toMap( +// e -> e.getKey().toString(), +// e -> e.getValue().toString() +// ) +// ); + + } + + /** + * Extract the first child of an input key after a the prefix + * + * @param key Full input key + * @param prefix Prefix + * @return Child key {String} if it exists or null + */ + public static String getFirstChildAfterPrefix(String key, String prefix) { + final String idAfterPrefix = removePrefixFromKey(key, prefix); + if (idAfterPrefix != null) { + final int index = idAfterPrefix.indexOf(KEY_DELIMITER); + if (index > 0) { + final String adding = idAfterPrefix.substring(0, index); + if (!(adding.isEmpty())) { + return adding; + + } + } else if (!(idAfterPrefix.isEmpty())) { + return idAfterPrefix; + + } + + } + return null; + } + + /** + * Extract the prefix from an input key + * + * @param key Full input key + * @param suffix Suffix of this key + * @return Prefix {String} of the key or null if input key does not ends with postfix string + */ + public static String getPrefixFromKey(String key, String suffix) { + if (key != null && suffix != null && key.endsWith(suffix)) { + final String idPreforeSuffix = key.substring(0, key.length()-suffix.length()); + if (idPreforeSuffix.endsWith(KEY_DELIMITER)) + return idPreforeSuffix.substring(0, idPreforeSuffix.length()-1); + else + return idPreforeSuffix; + } + return null; + + } + + /** + * Remove a prefix string from a key + * + * @param key Full input key + * @param prefix Prefix, which should be removed + * @return The suffix of the input key or null if the input does not starts with the prefix + */ + public static String removePrefixFromKey(String key, String prefix) { + if (prefix == null) + prefix = new String(); + + if (key!=null && key.startsWith(prefix)) { + String afterPrefix = key.substring(prefix.length()); + final int index = afterPrefix.indexOf(KEY_DELIMITER); + + if (index == 0) { + afterPrefix = afterPrefix.substring(1); + + } + return afterPrefix; + + } + return null; + } + + /** + * Remove a prefix string from all keys in {Map} of key/value pairs + * + * @param keys Input data of key/value pairs + * @param prefix Prefix which should be removed + * @return {Map} of key/value pairs without prefix in key, but never null + */ + public static Map removePrefixFromKeys(Map keys, String prefix) { + final Map result = new HashMap(); + final Iterator> interator = keys.entrySet().iterator(); + while(interator.hasNext()) { + final Entry el = interator.next(); + final String newKey = removePrefixFromKey(el.getKey(), prefix); + if (StringUtils.isNotEmpty(newKey)) { + result.put(newKey, el.getValue()); + } + } + + return result; + } + + /** + * Get a subset of key/value pairs which starts with a prefix string + * The Prefix is removed from the key + * + * @param keys Input data of key/value pairs + * @param prefix Prefix string + * @return {Map} of key/value pairs without prefix in key, but never null + */ + public static Map getSubSetWithPrefix(Map keys, String prefix) { + return removePrefixFromKeys(keys, prefix); + } + + + /** + * Add a prefix to key/value pairs to make the key absolute according to key namespace convention + * + * @param input Input key/value pairs which should be updated + * @param prefix Key prefix, which should be added if the key is not absolute + * @param absolutIdentifier Key identifier, which indicates an absolute key + * @return {Map} of key/value pairs in which all keys are absolute but never null + */ + public static Map makeKeysAbsolut(Map input, String prefix, String absolutIdentifier) { + final Map result = new HashMap(); + final Iterator> interator = input.entrySet().iterator(); + while(interator.hasNext()) { + final Entry el = interator.next(); + if (!el.getKey().startsWith(absolutIdentifier)) { + //key is not absolute -> add prefix + result.put(prefix + + KEY_DELIMITER + + el.getKey(), + el.getValue()); + + } else { + //key is absolute + result.put(el.getKey(), el.getValue()); + } + } + return result; + } + + /** + * Get the parent key string from an input key + * + * @param key input key + * @return parent key or the empty String if no parent exists + */ + public static String getParentKey(String key) { + if (StringUtils.isNotEmpty(key)) { + final int index = key.lastIndexOf(KEY_DELIMITER); + if (index > 0) { + return key.substring(0, index); + + } + } + + return new String(); + } + + /** + * Find the highest free list counter + * + * @param input Array of list keys + * @param listPrefix {String} prefix of the list + * @return {int} highest free list counter + */ + public static int findNextFreeListCounter(String[] input, + String listPrefix) { + final List counters = new ArrayList(); + if (input == null || input.length == 0) + return 0; + + else { + for (final String key : input) { + final String listIndex = getFirstChildAfterPrefix(key, listPrefix); + counters.add(Integer.parseInt(listIndex)); + + } + Collections.sort(counters); + return counters.get(counters.size()-1) + 1; + } + } + + /** + * Find the highest free list counter + * + * @param keySet {Set} of list keys + * @param listPrefix {String} prefix of the list + * @return {int} highest free list counter + */ + public static int findNextFreeListCounter(Set keySet, + String listPrefix) { + if (keySet.isEmpty()) + return 0; + + final String[] array = new String[keySet.size()]; + keySet.toArray(array); + return findNextFreeListCounter(array, listPrefix); + } + + + /** + * Normalize a CSV encoded list of value of an key/value pair + * + * This method removes all whitespace at the begin or the + * end of CSV values and remove newLine signs at the end of value. + * The ',' is used as list delimiter + * + * @param value CSV encoded input data + * @return normalized CSV encoded data or null if {value} is null or empty + */ + public static String normalizeCSVValueString(String value) { + String normalizedCodes = null; + if (StringUtils.isNotEmpty(value)) { + final String[] codes = value.split(CSV_DELIMITER); + for (final String el: codes) { + if (normalizedCodes == null) + normalizedCodes = StringUtils.chomp(el.trim()); + else + normalizedCodes += "," + StringUtils.chomp(el.trim()); + + } + } + return normalizedCodes; + } + + + /** + * Check a String if it is a comma separated list of values + * + * This method uses the ',' as list delimiter. + * + * @param value CSV encoded input data + * @return true if the input data contains a ',' and has more then 1 list element, otherwise false + */ + public static boolean isCSVValueString(String value) { + if (StringUtils.isNotEmpty(value)) { + final String[] codes = value.split(CSV_DELIMITER); + if (codes.length >= 2) { + if (StringUtils.isNotEmpty(codes[1].trim())) + return true; + + } + } + + return false; + } + + /** + * Convert a CSV list to a List of CSV values + *

+ * This method removes all whitespace at the begin or the + * end of CSV values and remove newLine signs at the end of value. + * The ',' is used as list delimiter + * + * @param csv CSV encoded input data + * @return List of CSV normalized values, but never null + */ + @Nonnull + public static List getListOfCSVValues(@Nullable String csv) { + final List list = new ArrayList(); + if (StringUtils.isNotEmpty(csv)) { + final String[] values = csv.split(CSV_DELIMITER); + for (final String el: values) + list.add(el.trim()); + + } + + return list; + } + + /** + * Convert a List of String elements to a Map of Key/Value pairs + *
+ * Every List element used as a key/value pair and the '=' sign represents the delimiter between key and value + * + * @param elements List of key/value elements + * @return Map of Key / Value pairs, but never null + */ + public static Map convertListToMap(List elements) { + final Map map = new HashMap(); + for (final String el : elements) { + if (el.contains(KEYVVALUEDELIMITER)) { + final String[] split = el.split(KEYVVALUEDELIMITER); + map.put(split[0], split[1]); + + } else + log.debug("Key/Value Mapper: '" + el + "' contains NO '='. Ignore it."); + + } + + return map; + } + + /** + * This method remove all newline delimiter (\n or \r\n) from input data + * + * @param value Input String + * @return Input String without newline characters + */ + public static String removeAllNewlineFromString(String value) { + return value.replaceAll("(\\t|\\r?\\n)+", ""); + + } + +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/NodeIteratorAdapter.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/NodeIteratorAdapter.java new file mode 100644 index 00000000..ec57b92a --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/NodeIteratorAdapter.java @@ -0,0 +1,113 @@ +/******************************************************************************* + * Copyright 2017 Graz University of Technology + * EAAF-Core Components has been developed in a cooperation between EGIZ, + * A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + *******************************************************************************/ +/******************************************************************************* + *******************************************************************************/ +/******************************************************************************* + *******************************************************************************/ + + +package at.gv.egiz.eaaf.core.impl.utils; + +import java.util.ListIterator; + +import org.w3c.dom.DOMException; +import org.w3c.dom.Node; +import org.w3c.dom.traversal.NodeFilter; +import org.w3c.dom.traversal.NodeIterator; + +/** + * A NodeIterator implementation based on a + * ListIterator. + * + * @see java.util.ListIterator + * @see org.w3c.dom.traversal.NodeIterator + * + */ +public class NodeIteratorAdapter implements NodeIterator { + + /** The ListIterator to wrap. */ + private ListIterator nodeIterator; + + /** + * Create a new NodeIteratorAdapter. + * @param nodeIterator The ListIterator to iterate over. + */ + public NodeIteratorAdapter(ListIterator nodeIterator) { + this.nodeIterator = nodeIterator; + } + + /** + * @see org.w3c.dom.traversal.NodeIterator#getRoot() + */ + public Node getRoot() { + return null; + } + + /** + * @see org.w3c.dom.traversal.NodeIterator#getWhatToShow() + */ + public int getWhatToShow() { + return NodeFilter.SHOW_ALL; + } + + /** + * @see org.w3c.dom.traversal.NodeIterator#getFilter() + */ + public NodeFilter getFilter() { + return null; + } + + /** + * @see org.w3c.dom.traversal.NodeIterator#getExpandEntityReferences() + */ + public boolean getExpandEntityReferences() { + return false; + } + + /** + * @see org.w3c.dom.traversal.NodeIterator#nextNode() + */ + public Node nextNode() throws DOMException { + if (nodeIterator.hasNext()) { + return (Node) nodeIterator.next(); + } + return null; + } + + /** + * @see org.w3c.dom.traversal.NodeIterator#previousNode() + */ + public Node previousNode() throws DOMException { + if (nodeIterator.hasPrevious()) { + return (Node) nodeIterator.previous(); + } + return null; + } + + /** + * @see org.w3c.dom.traversal.NodeIterator#detach() + */ + public void detach() { + } + +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/NodeListAdapter.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/NodeListAdapter.java new file mode 100644 index 00000000..69045aaa --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/NodeListAdapter.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright 2017 Graz University of Technology + * EAAF-Core Components has been developed in a cooperation between EGIZ, + * A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + *******************************************************************************/ +/******************************************************************************* + *******************************************************************************/ +/******************************************************************************* + *******************************************************************************/ + + +package at.gv.egiz.eaaf.core.impl.utils; + +import java.util.List; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * A NodeList implementation based on a List. + * + * @see java.util.List + * @see org.w3c.dom.NodeList + */ + +public class NodeListAdapter implements NodeList { + /** The List to wrap. */ + private List nodeList; + + /** + * Create a new NodeListAdapter. + * + * @param nodeList The List containing the nodes. + */ + public NodeListAdapter(List nodeList) { + this.nodeList = nodeList; + } + + /** + * @see org.w3c.dom.NodeList#item(int) + */ + public Node item(int index) { + return (Node) nodeList.get(index); + } + + /** + * @see org.w3c.dom.NodeList#getLength() + */ + public int getLength() { + return nodeList.size(); + } + +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/Random.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/Random.java new file mode 100644 index 00000000..e236b3a9 --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/Random.java @@ -0,0 +1,176 @@ +/******************************************************************************* + * Copyright 2017 Graz University of Technology + * EAAF-Core Components has been developed in a cooperation between EGIZ, + * A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + *******************************************************************************/ + +package at.gv.egiz.eaaf.core.impl.utils; + + +import java.nio.ByteBuffer; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.lang3.ArrayUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.eaaf.core.impl.idp.process.support.SecureRandomHolder; + + +/** + * Random number generator used to generate ID's + * @author Paul Ivancsics + * @version $Id$ + */ +public class Random { + private static final Logger log = LoggerFactory.getLogger(Random.class); + + private final static char[] allowedPreFix = + {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z', + 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}; + private static final DateFormat dateFormater = new SimpleDateFormat("yyyyddMM"); + + /** random number generator used */ + private static SecureRandom random; + //private static SeedGenerator seedgenerator; + + static { + try { + random = SecureRandom.getInstance("SHA256PRNG-FIPS186"); + + } catch (NoSuchAlgorithmException e) { + log.warn("Can NOT initialize SecureRandom with: 'SHA256PRNG-FIPS186'. Use 'StrongSecureRandom' as backup"); + random = SecureRandomHolder.getInstance(); + + } + + + //random = iaik.security.random.SHA256FIPS186Random.getDefault(); + } + + /** + * Generate a unique process reference-value [160bit], which always starts with a letter + *
+ * This unique ID consists of single letter, a 64bit date String[yyyyddMM], + * and a 88bit random value. + * + * @return 160bit ID, which is hex encoded + */ + public static String nextProcessReferenceValue() { + //pre-process all three parts of a unique reference value + String now = dateFormater.format(new Date()); //8 bytes = 64bit + byte[] randValue = nextByteRandom(11); + char preFix = allowedPreFix[Math.abs(random.nextInt() % allowedPreFix.length)]; + + //generate ID + String returnValue = preFix + new String(Hex.encodeHex(ArrayUtils.addAll(now.getBytes(), randValue))); // 20 bytes = 160 bits + if (returnValue.length() > 40) + return returnValue.substring(0, 40); + else + return returnValue; + + } + + + + /** + * Creates a new random number [256bit], and encode it as hex value. + * + * @return random hex encoded value [256bit] + */ + public static String nextHexRandom32() { + return new String(Hex.encodeHex(nextByteRandom(32))); // 32 bytes = 256 bits + + } + + /** + * Creates a new random number [128bit], and encode it as hex value. + * + * @return random hex encoded value [128bit] + */ + public static String nextHexRandom16() { + return new String(Hex.encodeHex(nextByteRandom(16))); // 16 bytes = 128 bits + + } + + /** + * Creates a new random number [64bit], to be used as an ID. + * + * @return random long as a String [64bit] + */ + public static String nextLongRandom() { + return "".concat(String.valueOf(Math.abs(generateLongRandom(32)))); // 32 bytes = 256 bits + + } + + /** + * Creates a new random number, to be used as an ID. + * + * @return random long as a String [64bit] + */ + @Deprecated + public static String nextRandom() { + long l = ByteBuffer.wrap(nextByteRandom(32)).getLong(); // 32 bytes = 256 bits + return "" + Math.abs(l); + + } + +/** + * Creates a new random byte[] + * + * @param size Size of random number in byte + * @return + */ +public static byte[] nextBytes(int size) { + return nextByteRandom(size); + +} + + public static void seedRandom() { + //TODO: implement reflection on IAIK Seed generator +// seedgenerator = iaik.security.random.AutoSeedGenerator.getDefault(); +// if (seedgenerator.seedAvailable()) +// random.setSeed(seedgenerator.getSeed()); + + random.setSeed(System.nanoTime()); + } + + private static long generateLongRandom(int size) { + return ByteBuffer.wrap(nextByteRandom(size)).getLong(); + } + + /** + * Generate a new random number + * + * @param size Size of random number in byte + * @return + */ + private static synchronized byte[] nextByteRandom(int size) { + byte[] b = new byte[size]; + random.nextBytes(b); + return b; + + } +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SecurePendingRequestIdGenerationStrategy.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SecurePendingRequestIdGenerationStrategy.java new file mode 100644 index 00000000..f0ef9b38 --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SecurePendingRequestIdGenerationStrategy.java @@ -0,0 +1,214 @@ +package at.gv.egiz.eaaf.core.impl.utils; + +import java.io.UnsupportedEncodingException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; +import java.util.Arrays; +import java.util.Base64; + +import javax.annotation.PostConstruct; +import javax.crypto.Mac; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; + +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; +import org.joda.time.DurationFieldType; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; + +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.api.utils.IPendingRequestIdGenerationStrategy; +import at.gv.egiz.eaaf.core.exceptions.EAAFConfigurationException; +import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.exceptions.EAAFIllegalStateException; +import at.gv.egiz.eaaf.core.exceptions.PendingReqIdValidationException; + +/** + * PendingRequestId generation strategy based on signed tokens that facilitates extended token validation + * + * @author tlenz + * + */ +public class SecurePendingRequestIdGenerationStrategy implements IPendingRequestIdGenerationStrategy { + private static final Logger log = LoggerFactory.getLogger(SecurePendingRequestIdGenerationStrategy.class); + + @Autowired(required=true) IConfiguration baseConfig; + + public static final String CONFIG_PROP_PENDINGREQUESTID_DIGIST_SECRET = "core.pendingrequestid.digist.secret"; + public static final String CONFIG_PROP_PENDINGREQUESTID_DIGIST_ALGORITHM = "core.pendingrequestid.digist.algorithm"; + public static final String CONFIG_PROP_PENDINGREQUESTID_MAX_LIFETIME = "core.pendingrequestid.maxlifetime"; + + public static final String DEFAULT_PENDINGREQUESTID_DIGIST_ALGORITHM = "HmacSHA256"; + public static final String DEFAULT_PENDINGREQUESTID_MAX_LIFETIME = "300"; + + private static final int ENCODED_TOKEN_PARTS = 3; + private static final String TOKEN_SEPARATOR = "|"; + private static final DateTimeFormatter TOKEN_TEXTUAL_DATE_FORMAT = + DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss SSS"); + + private int maxPendingRequestIdLifeTime = 300; + private final int maxPendingReqIdSize = 1024; + private String digistAlgorithm = null; + private SecretKey key = null; + private final byte[] salt = "notRequiredInThisScenario".getBytes(); + + @Override + public String generateExternalPendingRequestId() throws EAAFException { + try { + final String toSign = buildInternalToken(Random.nextLongRandom(), DateTime.now()); + final StringBuilder externalPendingRequestId= new StringBuilder(); + externalPendingRequestId.append(toSign); + externalPendingRequestId.append(TOKEN_SEPARATOR); + externalPendingRequestId.append(Base64.getEncoder().encodeToString(calculateHMAC(toSign))); + return Base64.getUrlEncoder().encodeToString(externalPendingRequestId.toString().getBytes("UTF-8")); + + } catch (final UnsupportedEncodingException e) { + throw new EAAFException("internal.99", new Object[] {e.getMessage()}, e); + + } + + } + + @Override + public String getPendingRequestIdWithOutChecks(String externalPendingReqId) throws PendingReqIdValidationException { + final String[] tokenElements = extractTokens(externalPendingReqId); + return tokenElements[1]; + + } + + @Override + public String validateAndGetPendingRequestId(String externalPendingReqId) throws PendingReqIdValidationException { + try { + final String[] tokenElements = extractTokens(externalPendingReqId); + final String internalPendingReqId = tokenElements[1]; + final DateTime timeStamp = TOKEN_TEXTUAL_DATE_FORMAT.parseDateTime(tokenElements[0]); + + log.trace("Checking HMAC from externalPendingReqId ... "); + final byte[] tokenDigest = Base64.getDecoder().decode(tokenElements[2]); + final byte[] refDigist = calculateHMAC(buildInternalToken(internalPendingReqId, timeStamp)); + if (!Arrays.equals(tokenDigest, refDigist)) { + log.warn("Digest of Token does NOT match"); + log.debug("Token: {} | Ref: {}", tokenDigest, refDigist); + throw new PendingReqIdValidationException(null, "Digest of pendingRequestId does NOT match"); + + } + log.debug("PendingRequestId HMAC digest check successful"); + + log.trace("Checking valid period ... "); + final DateTime now = DateTime.now(); + if (timeStamp.withFieldAdded( + DurationFieldType.seconds(), maxPendingRequestIdLifeTime).isBefore(now)) { + log.warn("Token exceeds the valid period"); + log.debug("Token: {} | Now: {}", timeStamp, now ); + throw new PendingReqIdValidationException(internalPendingReqId, "PendingRequestId exceeds the valid period"); + + } + log.debug("Token valid-period check successful"); + + return internalPendingReqId; + + + } catch (final IllegalArgumentException | EAAFIllegalStateException e) { + log.warn("Token is NOT a valid String. Msg: {}", e.getMessage()); + log.debug("TokenValue: {}", externalPendingReqId); + throw new PendingReqIdValidationException(null, "PendingReqId is NOT a valid String", e); + + } + } + + @NonNull + private String[] extractTokens(@Nullable String externalPendingReqId) throws PendingReqIdValidationException { + if (StringUtils.isEmpty(externalPendingReqId)) { + log.info("PendingReqId is 'null' or empty"); + throw new PendingReqIdValidationException(null, "PendingReqId is 'null' or empty"); + + } + + log.trace("RAW external pendingReqId: {}", externalPendingReqId); + final byte[] externalPendingReqIdBytes = Base64.getUrlDecoder().decode(externalPendingReqId); + + if (externalPendingReqIdBytes.length > maxPendingReqIdSize) { + log.warn("pendingReqId size exceeds {}", maxPendingReqIdSize); + throw new PendingReqIdValidationException(null, "pendingReqId exceeds max.size: " + maxPendingReqIdSize); + + } + + final String stringToken = new String(externalPendingReqIdBytes); + if (StringUtils.countMatches(stringToken, TOKEN_SEPARATOR) == ENCODED_TOKEN_PARTS - 1) { + final String[] tokenElements = StringUtils.split(stringToken, + TOKEN_SEPARATOR, ENCODED_TOKEN_PARTS); + return tokenElements; + + } else { + log.warn("PendingRequestId has an unvalid format"); + log.debug("PendingRequestId: {}", stringToken); + throw new PendingReqIdValidationException(null, "PendingReqId has an unvalid format"); + + } + + } + + + @PostConstruct + private void initialize() throws EAAFConfigurationException { + log.debug("Initializing " + this.getClass().getName() + " ... "); + + final String pendingReqIdDigistSecret = baseConfig.getBasicConfiguration(CONFIG_PROP_PENDINGREQUESTID_DIGIST_SECRET); + if (StringUtils.isEmpty(pendingReqIdDigistSecret)) + throw new EAAFConfigurationException("config.08", new Object[] {CONFIG_PROP_PENDINGREQUESTID_DIGIST_SECRET}); + + digistAlgorithm = baseConfig.getBasicConfiguration(CONFIG_PROP_PENDINGREQUESTID_DIGIST_ALGORITHM, DEFAULT_PENDINGREQUESTID_DIGIST_ALGORITHM); + + maxPendingRequestIdLifeTime = Integer.valueOf( + baseConfig.getBasicConfiguration(CONFIG_PROP_PENDINGREQUESTID_MAX_LIFETIME, DEFAULT_PENDINGREQUESTID_MAX_LIFETIME)); + + try { + final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WITHHMACSHA256"); + final KeySpec spec = new PBEKeySpec(pendingReqIdDigistSecret.toCharArray(), salt, 10000, 128); + key = keyFactory.generateSecret(spec); + + + } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { + log.error("Can NOT initialize TokenService with configuration object", e); + throw new EAAFConfigurationException("config.09", + new Object[] { CONFIG_PROP_PENDINGREQUESTID_DIGIST_SECRET, + "Can NOT generate HMAC key"}, + e); + + } + + log.info(this.getClass().getName() + " initialized with digistAlg: {} and maxLifeTime: {}", digistAlgorithm, maxPendingRequestIdLifeTime); + + } + + private String buildInternalToken(String internalPendingReqId, DateTime now) { + return new StringBuilder() + .append(TOKEN_TEXTUAL_DATE_FORMAT.print(now)) + .append(TOKEN_SEPARATOR) + .append(internalPendingReqId).toString(); + } + + private byte[] calculateHMAC(String toSign) throws EAAFIllegalStateException { + try { + final Mac mac = Mac.getInstance(digistAlgorithm); + mac.init(key); + return mac.doFinal(toSign.getBytes("UTF-8")); + + } catch (UnsupportedEncodingException | NoSuchAlgorithmException | InvalidKeyException e) { + log.error("Can NOT generate secure pendingRequestId", e); + throw new EAAFIllegalStateException(new Object[] {"Can NOT caluclate digist for secure pendingRequestId"}, e); + + } + + } + +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/ServletUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/ServletUtils.java new file mode 100644 index 00000000..38e873e2 --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/ServletUtils.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright 2017 Graz University of Technology + * EAAF-Core Components has been developed in a cooperation between EGIZ, + * A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + *******************************************************************************/ + +package at.gv.egiz.eaaf.core.impl.utils; + +import javax.servlet.http.HttpServletRequest; + +public class ServletUtils { + + + public static String getBaseUrl( HttpServletRequest request ) { + if ( ( request.getServerPort() == 80 ) || + ( request.getServerPort() == 443 ) ) + return request.getScheme() + "://" + + request.getServerName() + + request.getContextPath(); + else + return request.getScheme() + "://" + + request.getServerName() + ":" + request.getServerPort() + + request.getContextPath(); + } + +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SimplePendingRequestIdGenerationStrategy.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SimplePendingRequestIdGenerationStrategy.java new file mode 100644 index 00000000..6b8fe9b7 --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SimplePendingRequestIdGenerationStrategy.java @@ -0,0 +1,38 @@ +package at.gv.egiz.eaaf.core.impl.utils; + +import org.apache.commons.lang3.StringUtils; + +import at.gv.egiz.eaaf.core.api.utils.IPendingRequestIdGenerationStrategy; +import at.gv.egiz.eaaf.core.exceptions.PendingReqIdValidationException; + +/** + * Simple pendingRequestId generation strategy that facilitates no extended validation + * + * @author tlenz + * + */ +public class SimplePendingRequestIdGenerationStrategy implements IPendingRequestIdGenerationStrategy { + + @Override + public String generateExternalPendingRequestId() { + return Random.nextLongRandom(); + + } + + @Override + public String validateAndGetPendingRequestId(String pendingReqId) throws PendingReqIdValidationException { + return getPendingRequestIdWithOutChecks(pendingReqId); + + } + + @Override + public String getPendingRequestIdWithOutChecks(String externalPendingReqId) throws PendingReqIdValidationException { + if (StringUtils.isEmpty(externalPendingReqId)) + throw new PendingReqIdValidationException(externalPendingReqId, "PendingRequestId is empty or null"); + + + + return externalPendingReqId; + } + +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/StreamUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/StreamUtils.java new file mode 100644 index 00000000..530da777 --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/StreamUtils.java @@ -0,0 +1,201 @@ +/******************************************************************************* + * Copyright 2017 Graz University of Technology + * EAAF-Core Components has been developed in a cooperation between EGIZ, + * A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + *******************************************************************************/ +/******************************************************************************* + *******************************************************************************/ +/******************************************************************************* + *******************************************************************************/ + + +package at.gv.egiz.eaaf.core.impl.utils; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintStream; + +/** + * Utility methods for streams. + * + * @author Patrick Peck + * @version $Id$ + */ +public class StreamUtils { + + /** + * Compare the contents of two InputStreams. + * + * @param is1 The 1st InputStream to compare. + * @param is2 The 2nd InputStream to compare. + * @return boolean true, if both streams contain the exactly the + * same content, false otherwise. + * @throws IOException An error occurred reading one of the streams. + */ + public static boolean compareStreams(InputStream is1, InputStream is2) + throws IOException { + + byte[] buf1 = new byte[256]; + byte[] buf2 = new byte[256]; + int length1; + int length2; + + try { + while (true) { + length1 = is1.read(buf1); + length2 = is2.read(buf2); + + if (length1 != length2) { + return false; + } + if (length1 <= 0) { + return true; + } + if (!compareBytes(buf1, buf2, length1)) { + return false; + } + } + } catch (IOException e) { + throw e; + } finally { + // close both streams + try { + is1.close(); + is2.close(); + } catch (IOException e) { + // ignore this + } + } + } + + /** + * Compare two byte arrays, up to a given maximum length. + * + * @param b1 1st byte array to compare. + * @param b2 2nd byte array to compare. + * @param length The maximum number of bytes to compare. + * @return true, if the byte arrays are equal, false + * otherwise. + */ + private static boolean compareBytes(byte[] b1, byte[] b2, int length) { + if (b1.length != b2.length) { + return false; + } + + for (int i = 0; i < b1.length && i < length; i++) { + if (b1[i] != b2[i]) { + return false; + } + } + + return true; + } + + /** + * Reads a byte array from a stream. + * @param in The InputStream to read. + * @return The bytes contained in the given InputStream. + * @throws IOException on any exception thrown + */ + public static byte[] readStream(InputStream in) throws IOException { + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + copyStream(in, out, null); + + /* + ByteArrayOutputStream out = new ByteArrayOutputStream(); + int b; + while ((b = in.read()) >= 0) + out.write(b); + + */ + in.close(); + return out.toByteArray(); + } + + /** + * Reads a String from a stream, using given encoding. + * @param in The InputStream to read. + * @param encoding The character encoding to use for converting the bytes + * of the InputStream into a String. + * @return The content of the given InputStream converted into + * a String. + * @throws IOException on any exception thrown + */ + public static String readStream(InputStream in, String encoding) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + copyStream(in, out, null); + + /* + ByteArrayOutputStream out = new ByteArrayOutputStream(); + int b; + while ((b = in.read()) >= 0) + out.write(b); + */ + in.close(); + return out.toString(encoding); + } + + /** + * Reads all data (until EOF is reached) from the given source to the + * destination stream. If the destination stream is null, all data is dropped. + * It uses the given buffer to read data and forward it. If the buffer is + * null, this method allocates a buffer. + * + * @param source The stream providing the data. + * @param destination The stream that takes the data. If this is null, all + * data from source will be read and discarded. + * @param buffer The buffer to use for forwarding. If it is null, the method + * allocates a buffer. + * @exception IOException If reading from the source or writing to the + * destination fails. + */ + private static void copyStream(InputStream source, OutputStream destination, byte[] buffer) throws IOException { + if (source == null) { + throw new NullPointerException("Argument \"source\" must not be null."); + } + if (buffer == null) { + buffer = new byte[8192]; + } + + if (destination != null) { + int bytesRead; + while ((bytesRead = source.read(buffer)) >= 0) { + destination.write(buffer, 0, bytesRead); + } + } else { + while (source.read(buffer) >= 0); + } + } + + /** + * Gets the stack trace of the Throwable passed in as a string. + * @param t The Throwable. + * @return a String representing the stack trace of the Throwable. + */ + public static String getStackTraceAsString(Throwable t) + { + ByteArrayOutputStream stackTraceBIS = new ByteArrayOutputStream(); + t.printStackTrace(new PrintStream(stackTraceBIS)); + return new String(stackTraceBIS.toByteArray()); + } +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/TransactionIDUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/TransactionIDUtils.java new file mode 100644 index 00000000..2e016848 --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/TransactionIDUtils.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright 2017 Graz University of Technology + * EAAF-Core Components has been developed in a cooperation between EGIZ, + * A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + *******************************************************************************/ +/******************************************************************************* + *******************************************************************************/ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eaaf.core.impl.utils; + + +import at.gv.egiz.eaaf.core.api.IRequest; + +/** + * @author tlenz + * + */ +public class TransactionIDUtils { + + //MDC variables for logging + public static final String MDC_TRANSACTION_ID = "transactionId"; + public static final String MDC_SESSION_ID = "sessionId"; + public static final String MDC_SERVICEPROVIDER_ID = "oaId"; + + /** + * Set all MDC variables from pending request to this threat context
+ * These includes SessionID, TransactionID, and unique service-provider identifier + * + * @param pendingRequest + */ + public static void setAllLoggingVariables(IRequest pendingRequest) { + setTransactionId(pendingRequest.getUniqueTransactionIdentifier()); + setSessionId(pendingRequest.getUniqueSessionIdentifier()); + setServiceProviderId(pendingRequest.getServiceProviderConfiguration().getUniqueIdentifier()); + + } + + /** + * Remove all MDC variables from this threat context + * + */ + public static void removeAllLoggingVariables() { + removeSessionId(); + removeTransactionId(); + removeServiceProviderId(); + + } + + + public static void setServiceProviderId(String oaUniqueId) { + org.slf4j.MDC.put(MDC_SERVICEPROVIDER_ID, oaUniqueId); + + } + + public static void removeServiceProviderId() { + org.slf4j.MDC.remove(MDC_SERVICEPROVIDER_ID); + + } + + public static void setTransactionId(String pendingRequestID) { + org.slf4j.MDC.put(MDC_TRANSACTION_ID, + "TID-" + pendingRequestID); + + } + + public static void removeTransactionId() { + org.slf4j.MDC.remove(MDC_TRANSACTION_ID); + + } + + public static void setSessionId(String uniqueSessionId) { + org.slf4j.MDC.put(MDC_SESSION_ID, + "SID-" + uniqueSessionId); + + } + + public static void removeSessionId() { + org.slf4j.MDC.remove(MDC_SESSION_ID); + + } + + +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/X509Utils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/X509Utils.java new file mode 100644 index 00000000..b3fb42c4 --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/X509Utils.java @@ -0,0 +1,62 @@ +package at.gv.egiz.eaaf.core.impl.utils; + +import java.security.cert.X509Certificate; +import java.util.List; + +import javax.security.auth.x500.X500Principal; + +public class X509Utils { + + /** + * Sorts the Certificate Chain by IssuerDN and SubjectDN. The [0]-Element should be the Hostname, + * the last Element should be the Root Certificate. + * + * @param certs + * The first element must be the correct one. + * @return sorted Certificate Chain + */ + public static List sortCertificates( + List certs) + { + int length = certs.size(); + if (certs.size() <= 1) + { + return certs; + } + + for (X509Certificate cert : certs) + { + if (cert == null) + { + throw new NullPointerException(); + } + } + + for (int i = 0; i < length; i++) + { + boolean found = false; + X500Principal issuer = certs.get(i).getIssuerX500Principal(); + for (int j = i + 1; j < length; j++) + { + X500Principal subject = certs.get(j).getSubjectX500Principal(); + if (issuer.equals(subject)) + { + // sorting necessary? + if (i + 1 != j) + { + X509Certificate tmp = certs.get(i + 1); + certs.set(i + 1, certs.get(j)); + certs.set(j, tmp); + } + found = true; + } + } + if (!found) + { + break; + } + } + + return certs; + } +} diff --git a/pom.xml b/pom.xml index ba39b59d..5711cf5a 100644 --- a/pom.xml +++ b/pom.xml @@ -1,8 +1,6 @@ - - + --> 4.0.0 at.gv.egiz eaaf @@ -154,8 +152,9 @@ eaaf_core_api eaaf_core - eaaf_modules - + eaaf_modules + eaaf_core_utils + @@ -164,7 +163,11 @@ eaaf_core_api ${egiz.eaaf.version}
- + + at.gv.egiz.eaaf + eaaf_core_utils + ${egiz.eaaf.version} + at.gv.egiz.components eventlog-api @@ -457,4 +460,4 @@ - + \ No newline at end of file -- cgit v1.2.3