1.1 --- a/src/org/sonews/acl/AuthInfoCommand.java Wed Oct 19 21:40:51 2011 +0200
1.2 +++ b/src/org/sonews/acl/AuthInfoCommand.java Mon Nov 07 17:35:43 2011 +0100
1.3 @@ -18,40 +18,87 @@
1.4 package org.sonews.acl;
1.5
1.6 import java.io.IOException;
1.7 +import java.util.Arrays;
1.8 +import java.util.logging.Level;
1.9 +import java.util.logging.Logger;
1.10 +import java.util.regex.Matcher;
1.11 +import java.util.regex.Pattern;
1.12 import org.sonews.daemon.NNTPConnection;
1.13 import org.sonews.daemon.command.Command;
1.14 import org.sonews.storage.StorageBackendException;
1.15 +import org.sonews.storage.StorageManager;
1.16
1.17 /**
1.18 *
1.19 - * @author Christian Lins
1.20 - * @since sonews/1.1
1.21 + * @author František Kučera (frantovo.cz)
1.22 */
1.23 public class AuthInfoCommand implements Command {
1.24
1.25 - @Override
1.26 - public String[] getSupportedCommandStrings() {
1.27 - throw new UnsupportedOperationException("Not supported yet.");
1.28 - }
1.29 + private static final Logger log = Logger.getLogger(AuthInfoCommand.class.getName());
1.30 + private static String[] SUPPORTED_COMMANDS = {"AUTHINFO"};
1.31
1.32 @Override
1.33 public boolean hasFinished() {
1.34 - throw new UnsupportedOperationException("Not supported yet.");
1.35 + return true;
1.36 }
1.37
1.38 @Override
1.39 public String impliedCapability() {
1.40 - throw new UnsupportedOperationException("Not supported yet.");
1.41 + return "AUTHINFO";
1.42 }
1.43
1.44 @Override
1.45 public boolean isStateful() {
1.46 - throw new UnsupportedOperationException("Not supported yet.");
1.47 + return false;
1.48 }
1.49
1.50 @Override
1.51 - public void processLine(NNTPConnection conn, String line, byte[] rawLine)
1.52 - throws IOException, StorageBackendException {
1.53 - throw new UnsupportedOperationException("Not supported yet.");
1.54 + public String[] getSupportedCommandStrings() {
1.55 + return SUPPORTED_COMMANDS;
1.56 + }
1.57 +
1.58 + @Override
1.59 + public void processLine(NNTPConnection conn, String line, byte[] rawLine) throws IOException, StorageBackendException {
1.60 + Pattern commandPattern = Pattern.compile("AUTHINFO (USER|PASS) (.*)", Pattern.CASE_INSENSITIVE);
1.61 + Matcher commandMatcher = commandPattern.matcher(line);
1.62 +
1.63 + if (commandMatcher.matches()) {
1.64 +
1.65 + if (conn.getUser() != null && conn.getUser().isAuthenticated()) {
1.66 + conn.println("502 Command unavailable (you are already authenticated)");
1.67 + } else if ("USER".equalsIgnoreCase(commandMatcher.group(1))) {
1.68 + conn.setUser(new User(commandMatcher.group(2)));
1.69 + conn.println("381 Password required"); // ask user for his password
1.70 + log.log(Level.FINE, "User ''{0}'' greets us. We are waiting for his password.", conn.getUser().getUserName());
1.71 + } else if ("PASS".equalsIgnoreCase(commandMatcher.group(1))) {
1.72 + if (conn.getUser() == null) {
1.73 + conn.println("482 Authentication commands issued out of sequence");
1.74 + } else {
1.75 +
1.76 + char[] password = commandMatcher.group(2).toCharArray();
1.77 + boolean goodPassword = StorageManager.current().authenticateUser(conn.getUser().getUserName(), password);
1.78 + Arrays.fill(password, '*');
1.79 + commandMatcher = null;
1.80 +
1.81 + if (goodPassword) {
1.82 + conn.println("281 Authentication accepted");
1.83 + conn.getUser().setAuthenticated(true);
1.84 + log.log(Level.INFO, "User ''{0}'' has been succesfully authenticated.", conn.getUser().getUserName());
1.85 + } else {
1.86 + log.log(Level.INFO, "User ''{0}'' has provided wrong password.", conn.getUser().getUserName());
1.87 + conn.setUser(null);
1.88 + conn.println("481 Authentication failed: wrong password");
1.89 + }
1.90 +
1.91 + }
1.92 + } else {
1.93 + // impossible, see commandPattern
1.94 + conn.println("500 Unknown command");
1.95 + }
1.96 +
1.97 +
1.98 + } else {
1.99 + conn.println("500 Unknown command, expecting AUTHINFO USER username or AUTHINFO PASS password ");
1.100 + }
1.101 }
1.102 }