View Javadoc

1   /**
2    * Copyright 2009, Frederic Bregier, and individual contributors by the @author
3    * tags. See the COPYRIGHT.txt in the distribution for a full listing of
4    * individual contributors.
5    *
6    * This is free software; you can redistribute it and/or modify it under the
7    * terms of the GNU Lesser General Public License as published by the Free
8    * Software Foundation; either version 3.0 of the License, or (at your option)
9    * any later version.
10   *
11   * This software is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14   * details.
15   *
16   * You should have received a copy of the GNU Lesser General Public License
17   * along with this software; if not, write to the Free Software Foundation,
18   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
19   * site: http://www.fsf.org.
20   */
21  package goldengate.ftp.exec.file;
22  
23  import goldengate.common.command.NextCommandReply;
24  import goldengate.common.command.ReplyCode;
25  import goldengate.common.command.exception.Reply421Exception;
26  import goldengate.common.command.exception.Reply530Exception;
27  import goldengate.common.logging.GgInternalLogger;
28  import goldengate.common.logging.GgInternalLoggerFactory;
29  import goldengate.ftp.core.command.FtpCommandCode;
30  import goldengate.ftp.core.file.FtpDir;
31  import goldengate.ftp.core.session.FtpSession;
32  import goldengate.ftp.filesystembased.FilesystemBasedFtpAuth;
33  import goldengate.ftp.filesystembased.FilesystemBasedFtpRestart;
34  import goldengate.ftp.exec.config.FileBasedConfiguration;
35  import goldengate.ftp.exec.database.DbConstant;
36  import goldengate.ftp.exec.exec.AbstractExecutor.CommandExecutor;
37  
38  import java.io.File;
39  
40  /**
41   * FtpAuth implementation based on a list of (user/password/account) stored in a
42   * xml file load at startup from configuration.
43   *
44   * @author Frederic Bregier
45   *
46   */
47  public class FileBasedAuth extends FilesystemBasedFtpAuth {
48      /**
49       * Internal Logger
50       */
51      private static final GgInternalLogger logger = GgInternalLoggerFactory
52              .getLogger(FileBasedAuth.class);
53  
54      /**
55       * Current authentication
56       */
57      private SimpleAuth currentAuth = null;
58  
59      /**
60       * Special Id for the current transfer
61       */
62      private long specialId = DbConstant.ILLEGALVALUE;
63      
64      /**
65       * @param session
66       */
67      public FileBasedAuth(FtpSession session) {
68          super(session);
69      }
70  
71      @Override
72      protected void businessClean() {
73          currentAuth = null;
74      }
75  
76      /**
77       * @param user
78       *            the user to set
79       * @return (NOOP,230) if the user is OK, else return the following command
80       *         that must follow (usually PASS) and the associated reply
81       * @throws Reply421Exception
82       *             if there is a problem during the authentication
83       * @throws Reply530Exception
84       *             if there is a problem during the authentication
85       */
86      @Override
87      protected NextCommandReply setBusinessUser(String user)
88              throws Reply421Exception, Reply530Exception {
89          SimpleAuth auth = ((FileBasedConfiguration) ((FtpSession) getSession())
90                  .getConfiguration()).getSimpleAuth(user);
91          if (auth == null) {
92              setIsIdentified(false);
93              currentAuth = null;
94              throw new Reply530Exception("User name not allowed");
95          }
96          currentAuth = auth;
97          // logger.debug("User: {}", user);
98          return new NextCommandReply(FtpCommandCode.PASS,
99                  ReplyCode.REPLY_331_USER_NAME_OKAY_NEED_PASSWORD, null);
100     }
101 
102     /**
103      * Set the password according to any implementation and could set the
104      * rootFromAuth. If NOOP is returned, isIdentifed must be TRUE. A special
105      * case is implemented for test user.
106      *
107      * @param password
108      * @return (NOOP,230) if the Password is OK, else return the following
109      *         command that must follow (usually ACCT) and the associated reply
110      * @throws Reply421Exception
111      *             if there is a problem during the authentication
112      * @throws Reply530Exception
113      *             if there is a problem during the authentication
114      */
115     @Override
116     protected NextCommandReply setBusinessPassword(String password)
117             throws Reply421Exception, Reply530Exception {
118         if (currentAuth == null) {
119             setIsIdentified(false);
120             throw new Reply530Exception("PASS needs a USER first");
121         }
122         if (currentAuth.isPasswordValid(password)) {
123             return new NextCommandReply(FtpCommandCode.ACCT,
124                     ReplyCode.REPLY_332_NEED_ACCOUNT_FOR_LOGIN, null);
125         }
126         throw new Reply530Exception("Password is not valid");
127     }
128 
129     /**
130      * Set the account according to any implementation and could set the
131      * rootFromAuth. If NOOP is returned, isIdentifed must be TRUE.
132      *
133      * @param account
134      * @return (NOOP,230) if the Account is OK, else return the following
135      *         command that must follow and the associated reply
136      * @throws Reply421Exception
137      *             if there is a problem during the authentication
138      * @throws Reply530Exception
139      *             if there is a problem during the authentication
140      */
141     @Override
142     protected NextCommandReply setBusinessAccount(String account)
143             throws Reply421Exception, Reply530Exception {
144         if (currentAuth == null) {
145             throw new Reply530Exception("ACCT needs a USER first");
146         }
147         if (currentAuth.isAccountValid(account)) {
148             // logger.debug("Account: {}", account);
149             setIsIdentified(true);
150             logger.info("User {} is authentified with account {}", user,
151                     account);
152             return new NextCommandReply(FtpCommandCode.NOOP,
153                     ReplyCode.REPLY_230_USER_LOGGED_IN, null);
154         }
155         throw new Reply530Exception("Account is not valid");
156     }
157 
158     public boolean isBusinessPathValid(String newPath) {
159         if (newPath == null) {
160             return false;
161         }
162         return newPath.startsWith(getBusinessPath());
163     }
164 
165     @Override
166     protected String setBusinessRootFromAuth() throws Reply421Exception {
167         String path = null;
168         if (account == null) {
169             path = FtpDir.SEPARATOR + user;
170         } else {
171             path = FtpDir.SEPARATOR + user + FtpDir.SEPARATOR +
172                     account;
173         }
174         String fullpath = getAbsolutePath(path);
175         File file = new File(fullpath);
176         if (!file.isDirectory()) {
177             throw new Reply421Exception("Filesystem not ready");
178         }
179         return path;
180     }
181 
182     public boolean isAdmin() {
183         if (currentAuth == null)
184             return false;
185         return currentAuth.isAdmin;
186     }
187     /**
188      * Special Authentication for local execution
189      * @param hostid
190      */
191     public void specialNoSessionAuth(String hostid) {
192         this.isIdentified = true;
193         SimpleAuth auth = new SimpleAuth(hostid, hostid, null, null, 0, null, 0);
194         currentAuth = auth;
195         setIsIdentified(true);
196         user = auth.user;
197         account = auth.user;
198         ((FtpSession) getSession()).setSpecialInit(this, 
199                 new FileBasedDir(((FtpSession) getSession())), 
200                 new FilesystemBasedFtpRestart(((FtpSession) getSession())));
201         try {
202             setBusinessRootFromAuth();
203         } catch (Reply421Exception e) {
204         }
205         getSession().getDir().initAfterIdentification();
206         currentAuth.setAdmin(true);
207     }
208 
209     /**
210      * @return the specialId
211      */
212     public long getSpecialId() {
213         return specialId;
214     }
215 
216     /**
217      * @param specialId the specialId to set
218      */
219     public void setSpecialId(long specialId) {
220         this.specialId = specialId;
221     }
222     /**
223      * 
224      * @return the associated Command Executor
225      */
226     public CommandExecutor getCommandExecutor() {
227         return this.currentAuth.commandExecutor;
228     }
229 }