View Javadoc

1   /**
2      This file is part of GoldenGate Project (named also GoldenGate or GG).
3   
4      Copyright 2009, Frederic Bregier, 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 GoldenGate Project is free software: you can redistribute it and/or 
9      modify it under the terms of the GNU General Public License as published 
10     by the Free Software Foundation, either version 3 of the License, or
11     (at your option) any later version.
12  
13     GoldenGate is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17  
18     You should have received a copy of the GNU General Public License
19     along with GoldenGate .  If not, see <http://www.gnu.org/licenses/>.
20   */
21  package goldengate.ftp.simpleimpl.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.Reply502Exception;
27  import goldengate.common.command.exception.Reply530Exception;
28  import goldengate.common.logging.GgInternalLogger;
29  import goldengate.common.logging.GgInternalLoggerFactory;
30  import goldengate.ftp.core.command.FtpCommandCode;
31  import goldengate.ftp.core.file.FtpDir;
32  import goldengate.ftp.core.session.FtpSession;
33  import goldengate.ftp.filesystembased.FilesystemBasedFtpAuth;
34  import goldengate.ftp.simpleimpl.config.FileBasedConfiguration;
35  
36  import java.io.File;
37  
38  /**
39   * FtpAuth implementation based on a list of (user/password/account) stored in a
40   * xml file load at startup from configuration. Not to be used in production!
41   *
42   * @author Frederic Bregier
43   *
44   */
45  public class FileBasedAuth extends FilesystemBasedFtpAuth {
46      /**
47       * Internal Logger
48       */
49      private static final GgInternalLogger logger = GgInternalLoggerFactory
50              .getLogger(FileBasedAuth.class);
51  
52      /**
53       * Current authentication
54       */
55      private SimpleAuth currentAuth = null;
56  
57      /**
58       * @param session
59       */
60      public FileBasedAuth(FtpSession session) {
61          super(session);
62      }
63  
64      @Override
65      protected void businessClean() {
66          currentAuth = null;
67      }
68  
69      /**
70       * @param user
71       *            the user to set
72       * @return (NOOP,230) if the user is OK, else return the following command
73       *         that must follow (usually PASS) and the associated reply
74       * @throws Reply421Exception
75       *             if there is a problem during the authentication
76       * @throws Reply530Exception
77       *             if there is a problem during the authentication
78       */
79      @Override
80      protected NextCommandReply setBusinessUser(String user)
81              throws Reply421Exception, Reply530Exception {
82          SimpleAuth auth = ((FileBasedConfiguration) ((FtpSession) getSession())
83                  .getConfiguration()).getSimpleAuth(user);
84          if (auth == null) {
85              setIsIdentified(false);
86              currentAuth = null;
87              throw new Reply530Exception("User name not allowed");
88          }
89          currentAuth = auth;
90          // logger.debug("User: {}", user);
91          return new NextCommandReply(FtpCommandCode.PASS,
92                  ReplyCode.REPLY_331_USER_NAME_OKAY_NEED_PASSWORD, null);
93      }
94  
95      /**
96       * Set the password according to any implementation and could set the
97       * rootFromAuth. If NOOP is returned, isIdentifed must be TRUE. A special
98       * case is implemented for test user.
99       *
100      * @param password
101      * @return (NOOP,230) if the Password is OK, else return the following
102      *         command that must follow (usually ACCT) and the associated reply
103      * @throws Reply421Exception
104      *             if there is a problem during the authentication
105      * @throws Reply530Exception
106      *             if there is a problem during the authentication
107      */
108     @Override
109     protected NextCommandReply setBusinessPassword(String password)
110             throws Reply421Exception, Reply530Exception {
111         if (currentAuth == null) {
112             setIsIdentified(false);
113             throw new Reply530Exception("PASS needs a USER first");
114         }
115         if (currentAuth.isPasswordValid(password)) {
116             if (user.equals("test")) {
117                 // logger.debug("User test");
118                 try {
119                     return setAccount("test");
120                 } catch (Reply502Exception e) {
121                 }
122             }
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         return currentAuth.isAdmin;
184     }
185 }