1 /**
2 * This file is part of Waarp Project.
3 *
4 * Copyright 2009, Frederic Bregier, and individual contributors by the @author tags. See the
5 * COPYRIGHT.txt in the distribution for a full listing of individual contributors.
6 *
7 * All Waarp Project is free software: you can redistribute it and/or modify it under the terms of
8 * the GNU General Public License as published by the Free Software Foundation, either version 3 of
9 * the License, or (at your option) any later version.
10 *
11 * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13 * Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along with Waarp . If not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18 package org.waarp.ftp.simpleimpl.file;
19
20 import java.io.File;
21
22 import org.waarp.common.command.NextCommandReply;
23 import org.waarp.common.command.ReplyCode;
24 import org.waarp.common.command.exception.Reply421Exception;
25 import org.waarp.common.command.exception.Reply502Exception;
26 import org.waarp.common.command.exception.Reply530Exception;
27 import org.waarp.common.logging.WaarpLogger;
28 import org.waarp.common.logging.WaarpLoggerFactory;
29 import org.waarp.ftp.core.command.FtpCommandCode;
30 import org.waarp.ftp.core.file.FtpDir;
31 import org.waarp.ftp.core.session.FtpSession;
32 import org.waarp.ftp.filesystembased.FilesystemBasedFtpAuth;
33 import org.waarp.ftp.simpleimpl.config.FileBasedConfiguration;
34
35 /**
36 * FtpAuth implementation based on a list of (user/password/account) stored in a xml file load at
37 * startup from configuration. Not to be used in production!
38 *
39 * @author Frederic Bregier
40 *
41 */
42 public class FileBasedAuth extends FilesystemBasedFtpAuth {
43 /**
44 * Internal Logger
45 */
46 private static final WaarpLogger logger = WaarpLoggerFactory
47 .getLogger(FileBasedAuth.class);
48
49 /**
50 * Current authentication
51 */
52 private SimpleAuth currentAuth = null;
53
54 /**
55 * @param session
56 */
57 public FileBasedAuth(FtpSession session) {
58 super(session);
59 }
60
61 @Override
62 protected void businessClean() {
63 currentAuth = null;
64 }
65
66 /**
67 * @param user
68 * the user to set
69 * @return (NOOP,230) if the user is OK, else return the following command that must follow
70 * (usually PASS) and the associated reply
71 * @throws Reply421Exception
72 * if there is a problem during the authentication
73 * @throws Reply530Exception
74 * if there is a problem during the authentication
75 */
76 @Override
77 protected NextCommandReply setBusinessUser(String user)
78 throws Reply421Exception, Reply530Exception {
79 SimpleAuth auth = ((FileBasedConfiguration) ((FtpSession) getSession())
80 .getConfiguration()).getSimpleAuth(user);
81 if (auth == null) {
82 setIsIdentified(false);
83 currentAuth = null;
84 throw new Reply530Exception("User name not allowed");
85 }
86 currentAuth = auth;
87 // logger.debug("User: {}", user);
88 return new NextCommandReply(FtpCommandCode.PASS,
89 ReplyCode.REPLY_331_USER_NAME_OKAY_NEED_PASSWORD, null);
90 }
91
92 /**
93 * Set the password according to any implementation and could set the rootFromAuth. If NOOP is
94 * returned, isIdentifed must be TRUE. A special case is implemented for test user.
95 *
96 * @param password
97 * @return (NOOP,230) if the Password is OK, else return the following command that must follow
98 * (usually ACCT) and the associated reply
99 * @throws Reply421Exception
100 * if there is a problem during the authentication
101 * @throws Reply530Exception
102 * if there is a problem during the authentication
103 */
104 @Override
105 protected NextCommandReply setBusinessPassword(String password)
106 throws Reply421Exception, Reply530Exception {
107 if (currentAuth == null) {
108 setIsIdentified(false);
109 throw new Reply530Exception("PASS needs a USER first");
110 }
111 if (currentAuth.isPasswordValid(password)) {
112 if (user.equals("test")) {
113 // logger.debug("User test");
114 try {
115 return setAccount("test");
116 } catch (Reply502Exception e) {
117 }
118 }
119 return new NextCommandReply(FtpCommandCode.ACCT,
120 ReplyCode.REPLY_332_NEED_ACCOUNT_FOR_LOGIN, null);
121 }
122 throw new Reply530Exception("Password is not valid");
123 }
124
125 /**
126 * Set the account according to any implementation and could set the rootFromAuth. If NOOP is
127 * returned, isIdentifed must be TRUE.
128 *
129 * @param account
130 * @return (NOOP,230) if the Account is OK, else return the following command that must follow
131 * and the associated reply
132 * @throws Reply421Exception
133 * if there is a problem during the authentication
134 * @throws Reply530Exception
135 * if there is a problem during the authentication
136 */
137 @Override
138 protected NextCommandReply setBusinessAccount(String account)
139 throws Reply421Exception, Reply530Exception {
140 if (currentAuth == null) {
141 throw new Reply530Exception("ACCT needs a USER first");
142 }
143 if (currentAuth.isAccountValid(account)) {
144 // logger.debug("Account: {}", account);
145 setIsIdentified(true);
146 logger.info("User {} is authentified with account {}", user,
147 account);
148 return new NextCommandReply(FtpCommandCode.NOOP,
149 ReplyCode.REPLY_230_USER_LOGGED_IN, null);
150 }
151 throw new Reply530Exception("Account is not valid");
152 }
153
154 public boolean isBusinessPathValid(String newPath) {
155 if (newPath == null) {
156 return false;
157 }
158 return newPath.startsWith(getBusinessPath());
159 }
160
161 @Override
162 protected String setBusinessRootFromAuth() throws Reply421Exception {
163 String path = null;
164 if (account == null) {
165 path = FtpDir.SEPARATOR + user;
166 } else {
167 path = FtpDir.SEPARATOR + user + FtpDir.SEPARATOR +
168 account;
169 }
170 String fullpath = getAbsolutePath(path);
171 File file = new File(fullpath);
172 if (!file.isDirectory()) {
173 throw new Reply421Exception("Filesystem not ready");
174 }
175 return path;
176 }
177
178 public boolean isAdmin() {
179 return currentAuth.isAdmin();
180 }
181 }