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 }