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.context.authentication;
21  
22  import org.waarp.common.command.NextCommandReply;
23  import org.waarp.common.command.exception.Reply421Exception;
24  import org.waarp.common.command.exception.Reply530Exception;
25  import org.waarp.common.database.exception.WaarpDatabaseException;
26  import org.waarp.common.database.exception.WaarpDatabaseSqlException;
27  import org.waarp.common.file.DirInterface;
28  import org.waarp.common.file.filesystembased.FilesystemBasedAuthImpl;
29  import org.waarp.common.logging.SysErrLogger;
30  import org.waarp.common.logging.WaarpLogger;
31  import org.waarp.common.logging.WaarpLoggerFactory;
32  import org.waarp.common.role.RoleDefault;
33  import org.waarp.common.role.RoleDefault.ROLE;
34  import org.waarp.openr66.context.R66Session;
35  import org.waarp.openr66.database.data.DbHostAuth;
36  import org.waarp.openr66.protocol.configuration.Configuration;
37  
38  import java.io.File;
39  
40  /**
41   *
42   */
43  public class R66Auth extends FilesystemBasedAuthImpl {
44    /**
45     * Internal Logger
46     */
47    private static final WaarpLogger logger =
48        WaarpLoggerFactory.getLogger(R66Auth.class);
49  
50    /**
51     * Current authentication
52     */
53    private DbHostAuth currentAuth;
54    /**
55     * is Admin role
56     */
57    private boolean isAdmin;
58    /**
59     * Role set from configuration file only
60     */
61    private final RoleDefault role = new RoleDefault();
62  
63    /**
64     * @param session
65     */
66    public R66Auth(final R66Session session) {
67      super(session);
68    }
69  
70    /**
71     * To be able to store a clone of this Authentication
72     *
73     * @return the clone
74     */
75    public R66Auth clone() {
76      final R66Auth newAuth = new R66Auth((R66Session) session);
77      newAuth.currentAuth = currentAuth;
78      newAuth.role.clear();
79      newAuth.setIsIdentified(true);
80      newAuth.user = user;
81      newAuth.rootFromAuth = rootFromAuth;
82      newAuth.getSession().getDir().initAfterIdentification();
83      newAuth.isAdmin = currentAuth.isAdminrole();
84      newAuth.role.setRoleDefault(role);
85      return newAuth;
86    }
87  
88    /**
89     * For same channel, no proxy, authentification from already authenticated
90     * channel
91     *
92     * @param source
93     *
94     * @throws IllegalStateException if conditions are not valid to create a
95     *     correct R66Auth
96     */
97    public void setFromClone(final R66Auth source) {
98      if (source == null || !source.isIdentified()) {
99        throw new IllegalStateException("Source Authentification not valid");
100     }
101     currentAuth = source.currentAuth;
102     role.clear();
103     setIsIdentified(true);
104     user = source.user;
105     rootFromAuth = source.rootFromAuth;
106     getSession().getDir().initAfterIdentification();
107     isAdmin = currentAuth.isAdminrole();
108     role.setRoleDefault(source.role);
109     logger.debug("{}", role);
110   }
111 
112   @Override
113   protected final void businessClean() {
114     currentAuth = null;
115     isAdmin = false;
116     role.clear();
117   }
118 
119   @Override
120   public final String getBaseDirectory() {
121     return Configuration.configuration.getBaseDirectory();
122   }
123 
124   @Override
125   protected final NextCommandReply setBusinessPassword(final String arg0)
126       throws Reply421Exception {
127     throw new Reply421Exception("Command not valid");
128   }
129 
130   /**
131    * @param hostId
132    * @param arg0
133    *
134    * @return True if the connection is OK (authentication is OK)
135    *
136    * @throws Reply530Exception if the authentication is wrong
137    * @throws Reply421Exception If the service is not available
138    */
139   public final boolean connection(final String hostId, final byte[] arg0,
140                                   final boolean isSsl)
141       throws Reply530Exception, Reply421Exception {
142     final DbHostAuth auth;
143     try {
144       auth = new DbHostAuth(hostId);
145     } catch (final WaarpDatabaseException e) {
146       logger.error("Cannot find authentication for " + hostId);
147       setIsIdentified(false);
148       currentAuth = null;
149       throw new Reply530Exception("HostId not allowed: " + hostId);
150     }
151     if (auth.isSsl() != isSsl) {
152       if (auth.isSsl()) {
153         logger.error("Hostid {} must use SSL", hostId);
154       } else {
155         logger.error("Hostid {} cannot use SSL", hostId);
156       }
157       setIsIdentified(false);
158       currentAuth = null;
159       throw new Reply530Exception("HostId not allowed: mixed Ssl");
160     }
161     currentAuth = auth;
162     role.clear();
163     if (currentAuth.isKeyValid(arg0)) {
164       setIsIdentified(true);
165       user = hostId;
166       setRootFromAuth();
167       getSession().getDir().initAfterIdentification();
168       isAdmin = currentAuth.isAdminrole();
169       if (Configuration.configuration.getRoles().isEmpty()) {
170         if (isAdmin) {
171           role.setRole(ROLE.FULLADMIN);
172         } else {
173           role.setRole(ROLE.PARTNER);
174         }
175       } else {
176         final RoleDefault configRole =
177             Configuration.configuration.getRoles().get(hostId);
178         if (configRole == null) {
179           // set to default PARTNER
180           role.setRole(ROLE.PARTNER);
181         } else {
182           role.setRoleDefault(configRole);
183           if (role.isContaining(ROLE.FULLADMIN)) {
184             isAdmin = true;
185           }
186         }
187         if (isAdmin) {
188           role.setRole(ROLE.FULLADMIN);
189         }
190       }
191       logger.debug("{}", role);
192       return true;
193     }
194     throw new Reply530Exception("Key is not valid for this HostId");
195   }
196 
197   /**
198    * Set the root relative Path from current status of Authentication (should
199    * be
200    * the highest level for the
201    * current authentication). If setBusinessRootFromAuth returns null, by
202    * default set /user.
203    *
204    * @throws Reply421Exception if the business root is not available
205    */
206   @Override
207   protected final void setRootFromAuth() throws Reply421Exception {
208     rootFromAuth = setBusinessRootFromAuth();
209     if (rootFromAuth == null) {
210       rootFromAuth = DirInterface.SEPARATOR;
211     }
212   }
213 
214   @Override
215   protected final String setBusinessRootFromAuth() throws Reply421Exception {
216     final String path = null;
217     final String fullpath = getAbsolutePath(null);
218     final File file = new File(fullpath);
219     if (!file.isDirectory()) {
220       throw new Reply421Exception("Filesystem not ready");
221     }
222     return path;
223   }
224 
225   @Override
226   protected final NextCommandReply setBusinessUser(final String arg0)
227       throws Reply421Exception {
228     throw new Reply421Exception("Command not valid");
229   }
230 
231   @Override
232   public final boolean isAdmin() {
233     return isAdmin;
234   }
235 
236   /**
237    * @param roleCheck
238    *
239    * @return True if the current role contains the specified role to check
240    */
241   public final boolean isValidRole(final ROLE roleCheck) {
242     final ROLE[] roles = roleCheck.getComposingRoles();
243     for (final ROLE role1 : roles) {
244       if (!role.isContaining(role1)) {
245         return false;
246       }
247     }
248     return true;
249   }
250 
251   /**
252    * @return True if the associated host is using SSL
253    */
254   public final boolean isSsl() {
255     return currentAuth.isSsl();
256   }
257 
258   @Override
259   public final boolean isBusinessPathValid(final String newPath) {
260     return newPath != null;
261   }
262 
263   @Override
264   public String toString() {
265     return "Auth:" + isIdentified + ' ' +
266            (currentAuth != null? currentAuth.toString() : "no Internal Auth") +
267            ' ' + role;
268   }
269 
270   /**
271    * @param server
272    *
273    * @return the SimpleAuth if any for this user
274    */
275   public static DbHostAuth getServerAuth(final String server) {
276     final DbHostAuth auth;
277     try {
278       auth = new DbHostAuth(server);
279     } catch (final WaarpDatabaseException e) {
280       if (!server.equals(Configuration.configuration.getHostId())) {
281         logger.warn("Cannot find the authentication " + server + " : {}",
282                     e.getMessage());
283       }
284       return null;
285     }
286     return auth;
287   }
288 
289   /**
290    * Special Authentication for local execution
291    *
292    * @param isSSL
293    * @param hostid
294    */
295   public final void specialNoSessionAuth(final boolean isSSL,
296                                          final String hostid) {
297     isIdentified = true;
298     DbHostAuth auth = null;
299     try {
300       auth = new DbHostAuth(hostid);
301     } catch (final WaarpDatabaseException ignored) {
302       // nothing
303     }
304     if (auth == null) {
305       try {
306         auth =
307             new DbHostAuth(hostid, "127.0.0.1", 6666, isSSL, null, true, false);
308       } catch (final WaarpDatabaseSqlException e) {
309         SysErrLogger.FAKE_LOGGER.syserr(e);
310       }
311     }
312     role.clear();
313     currentAuth = auth;
314     setIsIdentified(true);
315     user = auth.getHostid(); // NOSONAR
316     try {
317       setRootFromAuth();
318     } catch (final Reply421Exception ignored) {
319       // nothing
320     }
321     getSession().getDir().initAfterIdentification();
322     isAdmin = isSSL;
323     if (isSSL) {
324       role.setRole(ROLE.FULLADMIN);
325       user = Configuration.configuration.getAdminName();
326     }
327   }
328 
329   /**
330    * connection from HTTPS (no default rights, must be set either as admin or
331    * specifically through ROLEs). Only
332    * "false client" with port with negative values are allowed.
333    *
334    * @param hostId
335    * @param arg0
336    *
337    * @return True if the connection is OK (authentication is OK)
338    *
339    * @throws Reply530Exception if the authentication is wrong
340    * @throws Reply421Exception If the service is not available
341    */
342   public final boolean connectionHttps(final String hostId, final byte[] arg0)
343       throws Reply530Exception, Reply421Exception {
344     final DbHostAuth auth = getServerAuth(hostId);
345     if (auth == null) {
346       logger.error("Cannot find authentication for " + hostId);
347       setIsIdentified(false);
348       currentAuth = null;
349       throw new Reply530Exception("HostId not allowed");
350     }
351     if (auth.getPort() >= 0) {
352       logger.error("Authentication is unacceptable for " + hostId);
353       setIsIdentified(false);
354       currentAuth = null;
355       throw new Reply530Exception("HostId not allowed");
356     }
357     role.clear();
358     currentAuth = auth;
359     if (currentAuth.isKeyValid(arg0)) {
360       setIsIdentified(true);
361       user = hostId;
362       setRootFromAuth();
363       getSession().getDir().initAfterIdentification();
364       isAdmin = currentAuth.isAdminrole();
365       if (!Configuration.configuration.getRoles().isEmpty()) {
366         final RoleDefault configRole =
367             Configuration.configuration.getRoles().get(hostId);
368         if (configRole != null) {
369           role.setRoleDefault(configRole);
370           if (role.isContaining(ROLE.FULLADMIN)) {
371             isAdmin = true;
372           }
373         }
374       }
375       if (isAdmin) {
376         role.setRole(ROLE.FULLADMIN);
377       }
378       logger.info("{}:{}", role, currentAuth);
379       return true;
380     }
381     throw new Reply530Exception("Key is not valid for this HostId");
382   }
383 
384   /**
385    * @return a copy of the Role of the current authenticated partner
386    */
387   public final RoleDefault getRole() {
388     return new RoleDefault().setRoleDefault(role);
389   }
390 }