/** * This file is part of Waarp Project. * * Copyright 2009, Frederic Bregier, and individual contributors by the @author tags. See the * COPYRIGHT.txt in the distribution for a full listing of individual contributors. * * All Waarp Project is free software: you can redistribute it and/or modify it under the terms of * the GNU General Public License as published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along with Waarp . If not, see * <http://www.gnu.org/licenses/>. */ package org.waarp.openr66.configuration; import java.io.File; import java.io.IOException; import java.util.Iterator; import java.util.List; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.io.SAXReader; import org.dom4j.tree.DefaultElement; import org.waarp.common.database.exception.WaarpDatabaseException; import org.waarp.common.database.exception.WaarpDatabaseNoConnectionException; import org.waarp.common.database.exception.WaarpDatabaseSqlException; import org.waarp.common.logging.WaarpLogger; import org.waarp.common.logging.WaarpLoggerFactory; import org.waarp.common.xml.XmlDecl; import org.waarp.common.xml.XmlHash; import org.waarp.common.xml.XmlType; import org.waarp.common.xml.XmlUtil; import org.waarp.common.xml.XmlValue; import org.waarp.openr66.database.DbConstant; import org.waarp.openr66.database.data.DbHostAuth; import org.waarp.openr66.protocol.configuration.Configuration; import org.waarp.openr66.protocol.exception.OpenR66ProtocolSystemException; /** * Authentication from File support * * @author Frederic Bregier * */ public class AuthenticationFileBasedConfiguration { /** * Internal Logger */ private static final WaarpLogger logger = WaarpLoggerFactory .getLogger(AuthenticationFileBasedConfiguration.class); /** * Authentication Fields */ private static final String XML_AUTHENTIFICATION_ROOT = "authent"; /** * Authentication Fields */ private static final String XML_AUTHENTIFICATION_ENTRY = "entry"; /** * Authentication Fields */ private static final String XML_AUTHENTIFICATION_BASED = "/" + XML_AUTHENTIFICATION_ROOT + "/" + XML_AUTHENTIFICATION_ENTRY; /** * Authentication Fields */ private static final String XML_AUTHENTIFICATION_HOSTID = "hostid"; /** * Authentication Fields */ private static final String XML_AUTHENTIFICATION_KEYFILE = "keyfile"; /** * Authentication Fields */ private static final String XML_AUTHENTIFICATION_KEY = "key"; /** * Authentication Fields */ private static final String XML_AUTHENTIFICATION_ADMIN = "admin"; /** * Authentication Fields */ private static final String XML_AUTHENTIFICATION_ADDRESS = "address"; /** * Authentication Fields */ private static final String XML_AUTHENTIFICATION_PORT = "port"; /** * Authentication Fields */ private static final String XML_AUTHENTIFICATION_ISSSL = "isssl"; /** * Authentication Fields */ private static final String XML_AUTHENTIFICATION_ISCLIENT = "isclient"; /** * Authentication Fields */ private static final String XML_AUTHENTIFICATION_ISACTIVE = "isactive"; /** * Authentication Fields */ private static final String XML_AUTHENTIFICATION_ISPROXIFIED = "isproxified"; /** * Structure of the Configuration file * */ private static final XmlDecl[] configAuthenticationDecls = { // identity new XmlDecl(XmlType.STRING, XML_AUTHENTIFICATION_HOSTID), new XmlDecl(XmlType.STRING, XML_AUTHENTIFICATION_KEYFILE), new XmlDecl(XmlType.STRING, XML_AUTHENTIFICATION_KEY), new XmlDecl(XmlType.BOOLEAN, XML_AUTHENTIFICATION_ADMIN), new XmlDecl(XmlType.STRING, XML_AUTHENTIFICATION_ADDRESS), new XmlDecl(XmlType.INTEGER, XML_AUTHENTIFICATION_PORT), new XmlDecl(XmlType.BOOLEAN, XML_AUTHENTIFICATION_ISSSL), new XmlDecl(XmlType.BOOLEAN, XML_AUTHENTIFICATION_ISCLIENT), new XmlDecl(XmlType.BOOLEAN, XML_AUTHENTIFICATION_ISACTIVE), new XmlDecl(XmlType.BOOLEAN, XML_AUTHENTIFICATION_ISPROXIFIED) }; /** * Global Structure for Server Configuration */ private static final XmlDecl[] authentElements = { new XmlDecl( XML_AUTHENTIFICATION_ENTRY, XmlType.XVAL, XML_AUTHENTIFICATION_BASED, configAuthenticationDecls, true) }; /** * Load Authentication from File * * @param filename * @return True if OK */ @SuppressWarnings("unchecked") public static boolean loadAuthentication(Configuration config, String filename) { Document document = null; try { document = new SAXReader().read(filename); } catch (DocumentException e) { logger.error("Unable to read the XML Authentication file: " + filename, e); return false; } if (document == null) { logger.error("Unable to read the XML Authentication file: " + filename); return false; } XmlValue[] values = XmlUtil.read(document, authentElements); XmlHash hash = new XmlHash(values); XmlValue value = hash.get(XML_AUTHENTIFICATION_ENTRY); List<XmlValue[]> list = (List<XmlValue[]>) value.getList(); Iterator<XmlValue[]> iterator = list.iterator(); File key; byte[] byteKeys; while (iterator.hasNext()) { XmlValue[] subvalues = iterator.next(); XmlHash subHash = new XmlHash(subvalues); value = subHash.get(XML_AUTHENTIFICATION_HOSTID); if (value == null || (value.isEmpty())) { continue; } String refHostId = value.getString(); value = subHash.get(XML_AUTHENTIFICATION_KEYFILE); if (value == null || (value.isEmpty())) { value = subHash.get(XML_AUTHENTIFICATION_KEY); if (value == null || (value.isEmpty())) { // Allow empty key byteKeys = null; } else { String skey = value.getString(); // key is crypted if (!skey.isEmpty()) { try { byteKeys = config.getCryptoKey().decryptHexInBytes(skey); } catch (Exception e) { logger.error("Cannot read key for hostId " + refHostId + ":" + skey); continue; } } else { byteKeys = null; } } } else { String skey = value.getString(); // load key from file key = new File(skey); if (!key.canRead()) { logger.error("Cannot read key for hostId " + refHostId + ":" + skey); continue; } try { byteKeys = config.getCryptoKey().decryptHexFile(key); } catch (Exception e2) { logger.error("Cannot read key for hostId " + refHostId, e2); continue; } } boolean isAdmin = false; value = subHash.get(XML_AUTHENTIFICATION_ADMIN); if (value != null && (!value.isEmpty())) { isAdmin = value.getBoolean(); } value = subHash.get(XML_AUTHENTIFICATION_ADDRESS); if (value == null || (value.isEmpty())) { continue; } String address = value.getString(); int port; value = subHash.get(XML_AUTHENTIFICATION_PORT); if (value != null && (!value.isEmpty())) { port = value.getInteger(); } else { continue; } boolean isSsl = false; value = subHash.get(XML_AUTHENTIFICATION_ISSSL); if (value != null && (!value.isEmpty())) { isSsl = value.getBoolean(); } boolean isClient = false; value = subHash.get(XML_AUTHENTIFICATION_ISCLIENT); if (value != null && (!value.isEmpty())) { isClient = value.getBoolean(); } boolean isActive = true; value = subHash.get(XML_AUTHENTIFICATION_ISACTIVE); if (value != null && (!value.isEmpty())) { isActive = value.getBoolean(); } boolean isProxified = false; value = subHash.get(XML_AUTHENTIFICATION_ISPROXIFIED); if (value != null && (!value.isEmpty())) { isProxified = value.getBoolean(); } DbHostAuth auth = new DbHostAuth(DbConstant.admin.getSession(), refHostId, address, port, isSsl, byteKeys, isAdmin, isClient); auth.setActive(isActive); auth.setProxified(isProxified); try { if (auth.exist()) { auth.update(); } else { auth.insert(); } } catch (WaarpDatabaseException e) { logger.error("Cannot create Authentication for hostId {}", refHostId); continue; } logger.debug("Add {} {}", refHostId, auth); } document = null; hash.clear(); values = null; return true; } /** * Construct a new Element with value * * @param name * @param value * @return the new Element */ private static Element newElement(String name, String value) { Element node = new DefaultElement(name); node.addText(value); return node; } /** * Write all authentication to a file with filename * * @param filename * @throws OpenR66ProtocolSystemException * @throws WaarpDatabaseNoConnectionException * @throws WaarpDatabaseSqlException */ public static void writeXML(Configuration config, String filename) throws OpenR66ProtocolSystemException, WaarpDatabaseNoConnectionException, WaarpDatabaseSqlException { Document document = DocumentHelper.createDocument(); Element root = document.addElement(XML_AUTHENTIFICATION_ROOT); DbHostAuth[] hosts = DbHostAuth.getAllHosts(DbConstant.admin.getSession()); logger.debug("Will write DbHostAuth: " + hosts.length + " in " + filename); for (DbHostAuth auth : hosts) { logger.debug("Will write DbHostAuth: " + auth.getHostid()); Element entry = new DefaultElement(XML_AUTHENTIFICATION_ENTRY); entry.add(newElement(XML_AUTHENTIFICATION_HOSTID, auth.getHostid())); byte[] key = auth.getHostkey(); String encode; try { encode = config.getCryptoKey().cryptToHex(key); } catch (Exception e) { encode = ""; } entry.add(newElement(XML_AUTHENTIFICATION_KEY, encode)); entry.add(newElement(XML_AUTHENTIFICATION_ADMIN, Boolean.toString(auth.isAdminrole()))); entry.add(newElement(XML_AUTHENTIFICATION_ADDRESS, auth.getAddress())); entry.add(newElement(XML_AUTHENTIFICATION_PORT, Integer.toString(auth.getPort()))); entry.add(newElement(XML_AUTHENTIFICATION_ISSSL, Boolean.toString(auth.isSsl()))); entry.add(newElement(XML_AUTHENTIFICATION_ISCLIENT, Boolean.toString(auth.isClient()))); entry.add(newElement(XML_AUTHENTIFICATION_ISACTIVE, Boolean.toString(auth.isActive()))); entry.add(newElement(XML_AUTHENTIFICATION_ISPROXIFIED, Boolean.toString(auth.isProxified()))); root.add(entry); } try { XmlUtil.writeXML(filename, null, document); } catch (IOException e) { throw new OpenR66ProtocolSystemException("Cannot write file: " + filename, e); } } }