/******************************************************************************* * 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.egovernment.moa.id.util; import java.io.ByteArrayInputStream; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.servlet.http.HttpServletRequest; import javax.xml.parsers.ParserConfigurationException; import org.xml.sax.SAXException; import at.gv.egiz.eaaf.core.impl.utils.DOMUtils; import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; import at.gv.egovernment.moa.id.commons.MOAIDAuthConstants; import at.gv.egovernment.moa.id.commons.api.AuthConfiguration; import at.gv.egovernment.moa.id.commons.api.exceptions.ConfigurationException; import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; import at.gv.egovernment.moa.util.StringUtils; public class ParamValidatorUtils extends MOAIDAuthConstants{ private static final Map parserFeatures = Collections.unmodifiableMap(new HashMap() { private static final long serialVersionUID = 1L; { put(DOMUtils.DISALLOW_DOCTYPE_FEATURE, true); } }); /** * Checks if the given target is valid * @param target HTTP parameter from request * @return */ public static boolean isValidTarget(String target) { Logger.debug("Ueberpruefe Parameter Target"); // if non parameter is given return true if (StringUtils.isEmpty(target)) { Logger.debug("Parameter Target ist null"); return true; } Pattern pattern = Pattern.compile("[a-zA-Z-]{1,5}"); Matcher matcher = pattern.matcher(target); boolean b = matcher.matches(); if (b) { Logger.debug("Parameter Target erfolgreich ueberprueft"); return true; } else { Logger.error("Fehler Ueberpruefung Parameter Target. Target entspricht nicht den Kriterien (nur Zeichen a-z, A-Z und -, sowie 1-5 Zeichen lang)"); return false; } } /** * Checks if the given ccc parameter is valid * @param ccc HTTP parameter from request * @return true if ccc is valid */ public static boolean isValidCCC(String ccc) { Logger.debug("Ueberpruefe Parameter CCC"); // if non parameter is given return true if (StringUtils.isEmpty(ccc)) { Logger.debug("Parameter CCC ist null"); return true; } Pattern pattern = Pattern.compile("[a-zA-Z]{2}"); Matcher matcher = pattern.matcher(ccc); boolean b = matcher.matches(); if (b) { Logger.debug("Parameter CCC erfolgreich ueberprueft"); return true; } else { Logger.error("Fehler Ueberpruefung Parameter CCC. CCC entspricht nicht den Kriterien (nur Zeichen a-z, A-Z, sowie 2 Zeichen lang)"); return false; } } /** * Checks if the given target is valid * @param sourceID HTTP parameter from request * @return */ public static boolean isValidSourceID(String sourceID) { Logger.debug("Ueberpruefe Parameter sourceID"); // if non parameter is given return true if (StringUtils.isEmpty(sourceID)) { Logger.debug("Parameter Target ist null"); return true; } Pattern pattern = Pattern.compile("[\\w-_]{1,20}"); Matcher matcher = pattern.matcher(sourceID); boolean b = matcher.matches(); if (b) { Logger.debug("Parameter sourceID erfolgreich ueberprueft"); return true; } else { Logger.error("Fehler Ueberpruefung Parameter sourceID. SourceID entspricht nicht den Kriterien (nur Zeichen a-z, A-Z, - und _, sowie 1-20 Zeichen lang)"); return false; } } /** * Checks if the given useMandate is valid * @param target HTTP parameter from request * @return */ public static boolean isValidUseMandate(String usemandate) { Logger.debug("Ueberpruefe Parameter useMandate"); // if non parameter is given return true if (StringUtils.isEmpty(usemandate)) { Logger.debug("Parameter useMandate ist null"); return true; } if (usemandate.compareToIgnoreCase("true") == 0 || usemandate.compareToIgnoreCase("false") == 0) { Logger.debug("Parameter useMandate erfolgreich ueberprueft"); return true; } else { Logger.error("Fehler Ueberpruefung Parameter useMandate. useMandate ist weder 'true' noch 'false')"); return false; } } /** * Checks if the given bkuURI is valid * @param target HTTP parameter from request * @return */ public static boolean isValidBKUURI(String bkuURI, List allowedBKUs) { Logger.debug("Ueberpruefe Parameter bkuURI"); // if non parameter is given return true if (StringUtils.isEmpty(bkuURI)) { Logger.debug("Parameter bkuURI ist null"); return true; } // check if template is a valid URL try { URL bkuUrl = new URL(bkuURI); // check if bku url starts with http or https if (bkuUrl.getProtocol().equals("http") || bkuUrl.getProtocol().equals("https")) { // check if bkuURI is a local BKU if (bkuURI.compareToIgnoreCase("https://localhost:3496/https-security-layer-request") == 0 || bkuURI.compareToIgnoreCase("http://localhost:3495/http-security-layer-request") == 0 || bkuURI.compareToIgnoreCase("http://127.0.0.1:3495/http-security-layer-request") == 0 || bkuURI.compareToIgnoreCase("https://127.0.0.1:3496/https-security-layer-request") == 0) { Logger.debug("Parameter bkuURI erfolgreich ueberprueft"); return true; } else { Logger.debug("Parameter bkuURI ist keine lokale BKU. Ueberpruefe Liste der vertrauenswuerdigen BKUs."); boolean b = allowedBKUs.contains(bkuURI); if (b) { Logger.debug("Parameter bkuURI erfolgreich ueberprueft"); return true; } else { Logger.error("Fehler Ueberpruefung Parameter bkuURI. " + bkuURI + " ist nicht auf Liste der vertrauenswuerdigen BKUs (Konfigurationselement: MOA-IDConfiguration/TrustedBKUs)"); return false; } } } else if (MOAIDAuthConstants.REQ_BKU_TYPES.contains(bkuURI)) { Logger.debug("Parameter bkuURI from configuration is used."); return true; } else { Logger.error("Fehler Ueberpruefung Parameter bkuURI. bkuURI beginnt nicht mit http or https"); return false; } } catch (MalformedURLException e) { Logger.error("Fehler Ueberpruefung Parameter bkuURI", e); return false; } } /** * Checks if the given template is valid * @param req * @param template * @param oaSlTemplates * @param useStrictValidation Enables strict validation with URLs from configuration, otherwise always allow templates from same host. * @return */ public static boolean isValidTemplate(HttpServletRequest req, String template, List oaSlTemplates, boolean useStrictValidation) { Logger.debug("Ueberpruefe Parameter Template bzw. bkuSelectionTemplateURL"); // if non parameter is given return true if (StringUtils.isEmpty(template)) { Logger.debug("Parameter Template bzw. bkuSelectionTemplateURL ist null"); return false; } // check if template is a valid URL try { if (useStrictValidation) { Logger.trace("Use strict validation of Template bzw. bkuSelectionTemplateURL"); return validateTemplateUrlToWhiteList(template, oaSlTemplates); } else { Logger.trace("Use lazy validation of Template bzw. bkuSelectionTemplateURL"); URL templateUrl = new URL(template); String serverName = req.getServerName(); // check if template url starts with http or https if (((templateUrl.getProtocol().startsWith("http") || templateUrl.getProtocol().startsWith("https"))) && templateUrl.getHost().equals(serverName)) { Logger.debug("Parameter Template bzw. bkuSelectionTemplateURL erfolgreich ueberprueft" + " Lazy check is activ and template is on same host as MOA-ID"); return true; } else { return validateTemplateUrlToWhiteList(template, oaSlTemplates); } } } catch (MalformedURLException | ConfigurationException e) { Logger.error("Fehler Ueberpruefung Parameter Template bzw. bkuSelectionTemplateURL.", e); return false; } } /** * Checks if the given sessionID is valid * @param target HTTP parameter from request * @return */ public static boolean isValidSessionID(String sessionID) { Logger.debug("Ueberpruefe Parameter MOASessionId"); // if non parameter is given return true if (StringUtils.isEmpty(sessionID)) { Logger.debug("Parameter MOASessionId ist null"); return true; } Pattern pattern = Pattern.compile("[0-9-]*"); Matcher matcher = pattern.matcher(sessionID); boolean b = matcher.matches(); if (b) { Logger.debug("Parameter MOASessionId erfolgreich ueberprueft"); return true; } else { Logger.error("Fehler Ueberpruefung Parameter MOASessionId. MOASessionId entspricht nicht den Kriterien (nur Zeichen 0-9 und -)"); return false; } } /** * Checks if the given oa is valid * @param target HTTP parameter from request * @return */ public static boolean isValidOA(String oa) { Logger.debug("Ueberpruefe Parameter oa"); // if non parameter is given return true if (StringUtils.isEmpty(oa)) { Logger.debug("Parameter oa ist null"); return true; } // check if template is a valid URL try { // check if template url starts with http or https if (oa.startsWith("http") || oa.startsWith("https")) { new URL(oa); Logger.debug("Parameter oa erfolgreich ueberprueft"); return true; } else { Logger.error("Fehler Ueberpruefung Parameter oa. oa beginnt nicht mit http or https"); return false; } } catch (MalformedURLException e) { Logger.error("Fehler Ueberpruefung Parameter oa", e); return false; } } /** * Checks if the given signurl is valid * @param target HTTP parameter from request * @return */ public static boolean isValidSignUrl(String signurl) { Logger.debug("Ueberpruefe Parameter signurl"); // if non parameter is given return true if (StringUtils.isEmpty(signurl)) { Logger.debug("Parameter signurl ist null"); return true; } // check if template is a valid URL try { // check if signurl starts with http or https if (signurl.startsWith("http") || signurl.startsWith("https")) { new URL(signurl); Logger.debug("Parameter signurl erfolgreich ueberprueft"); return true; } else { Logger.error("Fehler Ueberpruefung Parameter signurl. signurl beginnt nicht mit http or https"); return false; } } catch (MalformedURLException e) { Logger.error("Fehler Ueberpruefung Parameter signurl", e); return false; } } /** * Checks if , , , , * placeholders are contained in the given string. * The placeholder is not checked, as it is only required, * if other infoboxes as identity link will be treated. * @param data * @return */ // private static boolean checkPlaceHolders(String data) { // // boolean bku = data.contains(""); // boolean xmlrequest = data.contains(""); // boolean dataurl = data.contains(""); // boolean certinfoxmlrequest = data.contains(""); // boolean certinfodataurl = data.contains(""); // // System.out.println("Check Data: "); // System.out.println("bku: " + bku); // System.out.println("xmlrequest: " + xmlrequest); // System.out.println("dataurl: " + dataurl); // System.out.println("certinfoxmlrequest: " + certinfoxmlrequest); // System.out.println("certinfodataurl: " + certinfodataurl); // // // //return bku && xmlrequest && dataurl && certinfoxmlrequest && certinfodataurl; // return true; // // } // /** // * Converts an input stream to a string // * @param is // * @return // * @throws Exception // */ // private static String convertStreamToString(InputStream is) throws Exception { // BufferedReader reader = new BufferedReader(new InputStreamReader(is)); // StringBuilder sb = new StringBuilder(); // String line = null; // while ((line = reader.readLine()) != null) { // sb.append(line); // } // is.close(); // return sb.toString(); // } public static boolean isValidXMLDocument(String document) { if (StringUtils.isEmpty(document)) return false; Logger.debug("Ueberpruefe Parameter XMLDocument"); try { DOMUtils.parseXmlValidating(new ByteArrayInputStream(document.getBytes()), parserFeatures); // DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // DocumentBuilder builder = factory.newDocumentBuilder(); // InputSource is = new InputSource(new StringReader(document)); // builder.parse(is); Logger.debug("Parameter XMLDocument erfolgreich ueberprueft"); return true; } catch (ParserConfigurationException e) { Logger.error("Fehler Ueberpruefung Parameter XMLDocument", e); return false; } catch (SAXException e) { Logger.error("Fehler Ueberpruefung Parameter XMLDocument", e); return false; } catch (IOException e) { Logger.error("Fehler Ueberpruefung Parameter XMLDocument", e); return false; } } public static boolean areAllLegacyParametersAvailable(HttpServletRequest req) { String oaURL = req.getParameter(PARAM_OA); String bkuURL = req.getParameter(PARAM_BKU); String useMandate = req.getParameter(PARAM_USEMANDATE); String ccc = req.getParameter(PARAM_CCC); String useeIDAS = req.getParameter("useeIDAS"); // check parameter try { if (!ParamValidatorUtils.isValidOA(oaURL)) throw new WrongParametersException("StartAuthentication", PARAM_OA, "auth.12"); if (MiscUtil.isEmpty(bkuURL)) throw new WrongParametersException("StartAuthentication", PARAM_BKU, "auth.12"); if (!ParamValidatorUtils.isValidUseMandate(useMandate)) throw new WrongParametersException("StartAuthentication", PARAM_USEMANDATE, "auth.12"); if (!ParamValidatorUtils.isValidUseMandate(useeIDAS)) throw new WrongParametersException("StartAuthentication", "useeIDAS", "auth.12"); if (!ParamValidatorUtils.isValidCCC(ccc)) throw new WrongParametersException("StartAuthentication", PARAM_CCC, "auth.12"); } catch (WrongParametersException e) { return false; } if (StringUtils.isEmpty(bkuURL) && StringUtils.isEmpty(useeIDAS)) { return false; } else { return true; } } private static boolean validateTemplateUrlToWhiteList(String template, List oaSlTemplates) throws ConfigurationException { //check against configured trustet template urls AuthConfiguration authConf = AuthConfigurationProviderFactory.getInstance(); List trustedTemplateURLs = authConf.getSLRequestTemplates(); //get OA specific template URLs if (oaSlTemplates != null && oaSlTemplates.size() > 0) { for (String el : oaSlTemplates) if (MiscUtil.isNotEmpty(el)) trustedTemplateURLs.add(el); } boolean b = trustedTemplateURLs.contains(template); if (b) { Logger.debug("Parameter Template erfolgreich ueberprueft"); return true; } else { Logger.error("Fehler Ueberpruefung Parameter Template bzw. bkuSelectionTemplateURL. " + "Parameter ist nicht auf Liste der vertrauenswuerdigen Template URLs " + "(Konfigurationselement: MOA-IDConfiguration/TrustedTemplateURLs)"); return false; } } }