View Javadoc
1   /*
2    * This file is part of Waarp Project (named also Waarp or GG).
3    *
4    *  Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
5    *  tags. See the COPYRIGHT.txt in the distribution for a full listing of
6    * individual contributors.
7    *
8    *  All Waarp Project is free software: you can redistribute it and/or
9    * modify it under the terms of the GNU General Public License as published by
10   * the Free Software Foundation, either version 3 of the License, or (at your
11   * option) any later version.
12   *
13   * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY
14   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15   * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16   *
17   *  You should have received a copy of the GNU General Public License along with
18   * Waarp . If not, see <http://www.gnu.org/licenses/>.
19   */
20  package org.waarp.openr66.configuration;
21  
22  import org.dom4j.Document;
23  import org.dom4j.DocumentException;
24  import org.dom4j.DocumentHelper;
25  import org.dom4j.Element;
26  import org.dom4j.tree.DefaultElement;
27  import org.waarp.common.database.exception.WaarpDatabaseException;
28  import org.waarp.common.database.exception.WaarpDatabaseNoConnectionException;
29  import org.waarp.common.database.exception.WaarpDatabaseSqlException;
30  import org.waarp.common.logging.WaarpLogger;
31  import org.waarp.common.logging.WaarpLoggerFactory;
32  import org.waarp.common.xml.XmlHash;
33  import org.waarp.common.xml.XmlUtil;
34  import org.waarp.common.xml.XmlValue;
35  import org.waarp.openr66.database.data.DbHostAuth;
36  import org.waarp.openr66.protocol.configuration.Configuration;
37  import org.waarp.openr66.protocol.exception.OpenR66ProtocolSystemException;
38  
39  import java.io.File;
40  import java.io.IOException;
41  import java.util.Iterator;
42  import java.util.List;
43  
44  import static org.waarp.openr66.configuration.FileBasedElements.*;
45  
46  /**
47   * Authentication from File support
48   */
49  public class AuthenticationFileBasedConfiguration {
50    private static final String CANNOT_READ_KEY_FOR_HOST_ID =
51        "Cannot read key for hostId ";
52    /**
53     * Internal Logger
54     */
55    private static final WaarpLogger logger =
56        WaarpLoggerFactory.getLogger(AuthenticationFileBasedConfiguration.class);
57  
58    private AuthenticationFileBasedConfiguration() {
59    }
60  
61    /**
62     * Load Authentication from File
63     *
64     * @param filename
65     *
66     * @return True if OK
67     */
68    @SuppressWarnings("unchecked")
69    public static boolean loadAuthentication(final Configuration config,
70                                             final String filename) {
71      final Document document;
72      try {
73        document = XmlUtil.getNewSaxReader().read(filename);
74      } catch (final DocumentException e) {
75        logger.error("Unable to read the XML Authentication file: " + filename,
76                     e);
77        return false;
78      }
79      if (document == null) {
80        logger.error("Unable to read the XML Authentication file: " + filename);
81        return false;
82      }
83      final XmlValue[] values = XmlUtil.read(document, authentElements);
84      final XmlHash hash = new XmlHash(values);
85      XmlValue value = hash.get(XML_AUTHENTICATION_ENTRY);
86      final List<XmlValue[]> list = (List<XmlValue[]>) value.getList();
87      final Iterator<XmlValue[]> iterator = list.iterator();
88      File key;
89      byte[] byteKeys;
90      while (iterator.hasNext()) {
91        final XmlValue[] subvalues = iterator.next();
92        final XmlHash subHash = new XmlHash(subvalues);
93        value = subHash.get(XML_AUTHENTICATION_HOSTID);
94        if (value == null || value.isEmpty()) {
95          continue;
96        }
97        final String refHostId = value.getString();
98        value = subHash.get(XML_AUTHENTICATION_KEYFILE);
99        if (value == null || value.isEmpty()) {
100         value = subHash.get(XML_AUTHENTICATION_KEY);
101         if (value == null || value.isEmpty()) {
102           // Allow empty key
103           byteKeys = null;
104         } else {
105           final String skey = value.getString();
106           // key is crypted
107           if (!skey.isEmpty()) {
108             try {
109               byteKeys = config.getCryptoKey().decryptHexInBytes(skey);
110             } catch (final Exception e) {
111               logger.error(
112                   CANNOT_READ_KEY_FOR_HOST_ID + refHostId + ':' + skey);
113               continue;
114             }
115           } else {
116             byteKeys = null;
117           }
118         }
119       } else {
120         final String skey = value.getString();
121         // load key from file
122         key = new File(skey);
123         if (!key.canRead()) {
124           logger.error(CANNOT_READ_KEY_FOR_HOST_ID + refHostId + ':' + skey);
125           continue;
126         }
127         try {
128           byteKeys = config.getCryptoKey().decryptHexFile(key);
129         } catch (final Exception e2) {
130           logger.error(CANNOT_READ_KEY_FOR_HOST_ID + refHostId, e2);
131           continue;
132         }
133       }
134       boolean isAdmin = false;
135       value = subHash.get(XML_AUTHENTICATION_ADMIN);
136       if (value != null && !value.isEmpty()) {
137         isAdmin = value.getBoolean();
138       }
139       value = subHash.get(XML_AUTHENTICATION_ADDRESS);
140       if (value == null || value.isEmpty()) {
141         continue;
142       }
143       final String address = value.getString();
144       final int port;
145       value = subHash.get(XML_AUTHENTICATION_PORT);
146       if (value != null && !value.isEmpty()) {
147         port = value.getInteger();
148       } else {
149         continue;
150       }
151       boolean isSsl = false;
152       value = subHash.get(XML_AUTHENTICATION_ISSSL);
153       if (value != null && !value.isEmpty()) {
154         isSsl = value.getBoolean();
155       }
156       boolean isClient = false;
157       value = subHash.get(XML_AUTHENTICATION_ISCLIENT);
158       if (value != null && !value.isEmpty()) {
159         isClient = value.getBoolean();
160       }
161       boolean isActive = true;
162       value = subHash.get(XML_AUTHENTICATION_ISACTIVE);
163       if (value != null && !value.isEmpty()) {
164         isActive = value.getBoolean();
165       }
166       boolean isProxified = false;
167       value = subHash.get(XML_AUTHENTICATION_ISPROXIFIED);
168       if (value != null && !value.isEmpty()) {
169         isProxified = value.getBoolean();
170       }
171       try {
172         final DbHostAuth auth =
173             new DbHostAuth(refHostId, address, port, isSsl, byteKeys, isAdmin,
174                            isClient);
175         auth.setActive(isActive);
176         auth.setProxified(isProxified);
177         if (auth.exist()) {
178           auth.update();
179         } else {
180           auth.insert();
181         }
182         logger.debug("Add {} {}", refHostId, auth);
183       } catch (final WaarpDatabaseException e) {
184         logger.error("Cannot create Authentication for hostId {}", refHostId);
185         continue;
186       }
187     }
188     hash.clear();
189     return true;
190   }
191 
192   /**
193    * Construct a new Element with value
194    *
195    * @param name
196    * @param value
197    *
198    * @return the new Element
199    */
200   private static Element newElement(final String name, final String value) {
201     final Element node = new DefaultElement(name);
202     node.addText(value);
203     return node;
204   }
205 
206   /**
207    * Write all authentication to a file with filename
208    *
209    * @param filename
210    *
211    * @throws OpenR66ProtocolSystemException
212    * @throws WaarpDatabaseNoConnectionException
213    * @throws WaarpDatabaseSqlException
214    */
215   public static void writeXML(final Configuration config, final String filename)
216       throws OpenR66ProtocolSystemException,
217              WaarpDatabaseNoConnectionException {
218     final Document document = DocumentHelper.createDocument();
219     final Element root = document.addElement(XML_AUTHENTICATION_ROOT);
220     final DbHostAuth[] hosts = DbHostAuth.getAllHosts();
221     logger.debug("Will write DbHostAuth: {} in {}", hosts.length, filename);
222     for (final DbHostAuth auth : hosts) {
223       logger.debug("Will write DbHostAuth: {}", auth.getHostid());
224       final Element entry = new DefaultElement(XML_AUTHENTICATION_ENTRY);
225       entry.add(newElement(XML_AUTHENTICATION_HOSTID, auth.getHostid()));
226       final byte[] key = auth.getHostkey();
227       String encode;
228       try {
229         encode = config.getCryptoKey().cryptToHex(key);
230       } catch (final Exception e) {
231         encode = "";
232       }
233       entry.add(newElement(XML_AUTHENTICATION_KEY, encode));
234       entry.add(newElement(XML_AUTHENTICATION_ADMIN,
235                            Boolean.toString(auth.isAdminrole())));
236       entry.add(newElement(XML_AUTHENTICATION_ADDRESS, auth.getAddress()));
237       entry.add(newElement(XML_AUTHENTICATION_PORT,
238                            Integer.toString(auth.getPort())));
239       entry.add(
240           newElement(XML_AUTHENTICATION_ISSSL, Boolean.toString(auth.isSsl())));
241       entry.add(newElement(XML_AUTHENTICATION_ISCLIENT,
242                            Boolean.toString(auth.isClient())));
243       entry.add(newElement(XML_AUTHENTICATION_ISACTIVE,
244                            Boolean.toString(auth.isActive())));
245       entry.add(newElement(XML_AUTHENTICATION_ISPROXIFIED,
246                            Boolean.toString(auth.isProxified())));
247       root.add(entry);
248     }
249     try {
250       XmlUtil.writeXML(filename, null, document);
251     } catch (final IOException e) {
252       throw new OpenR66ProtocolSystemException("Cannot write file: " + filename,
253                                                e);
254     }
255   }
256 }