preliminary authentication support
authoradam <adam@megacz.com>
Thu, 5 Aug 2004 23:24:33 +0000 (23:24 +0000)
committeradam <adam@megacz.com>
Thu, 5 Aug 2004 23:24:33 +0000 (23:24 +0000)
darcs-hash:20040805232433-5007d-8cf9dd17cffc0cb3064bb890f040d6a5bf0eed6b.gz

src/org/ibex/mail/Main.java
src/org/ibex/mail/protocol/IMAP.java
src/org/ibex/mail/protocol/NNTP.java

index cdca5a0..edc22c0 100644 (file)
@@ -12,11 +12,39 @@ import org.ibex.crypto.*;
 public class Main implements Listener {
 
     public void accept(Connection conn) {
-        Log.error(this, "connection port is " + conn.getLocalPort());
-        if (conn.getLocalPort() == 25) {
-            new SMTP.Server().handleRequest(conn);
-        } else if (conn.getLocalPort() == 143) {
-            new IMAP.Listener().handleRequest(conn);
+        try {
+            if (conn.getLocalPort() == 25)       new SMTP.Server().handleRequest(conn);
+            else if (conn.getLocalPort() == 143) new IMAP.Listener(auth).handleRequest(conn);
+            else if (conn.getLocalPort() == 119) new NNTP.Listener(auth).handleRequest(conn);
+        } finally {
+            conn.close();
+        }
+    }
+
+    private static final Auth auth = new Auth();
+    private static class Auth implements Login {
+        final Mailbox root = FileBasedMailbox.getFileBasedMailbox(Mailbox.STORAGE_ROOT, true).slash("user", true);
+        public Account anonymous() { return null; }
+        public Account login(String user, String pass) {
+            if (!EtcPasswd.verify(user, pass)) return null;
+            return new Account(user, null, root.slash(user, true)){
+                    public Mailbox getMailbox(Class protocol) {
+                        if (protocol == NNTP.class) {
+                            final Mailbox arch = new MailmanArchives();
+                            return new Mailbox.Default() {
+                                    public void add(Message m) { throw new RuntimeException("not supported"); }
+                                    public void add(Message m, int i) { throw new RuntimeException("not supported"); }
+                                    public int              uidValidity()  { return 1; }
+                                    public Mailbox.Iterator iterator()     { return null; }
+                                    public int              uidNext()      { return 0; }
+                                    public String[] children() { return new String[] { "us" }; }
+                                    public Mailbox slash(String name, boolean create) { return arch; }
+                                };
+                        } else {
+                            return super.getMailbox(protocol);
+                        }
+                    }
+                };
         }
     }
 
index 5b74005..8e2c1ed 100644 (file)
@@ -76,7 +76,6 @@ public class IMAP {
         public void      fetch(Query q, int spec, String[] headers, int start, int end, boolean uid);
         public void      lsub(String start, String ref);
         public void      list(String start, String ref);
-        public static interface Authenticator { public abstract Mailbox authenticate(String user, String pass); } 
         public static class Exn extends MailException { public Exn(String s) { super(s); } }
         public static class Bad extends Exn { public Bad(String s) { super(s); } }
         public static class No extends Exn { public No(String s) { super(s); } }
@@ -94,10 +93,10 @@ public class IMAP {
         Mailbox selected = null;
         Mailbox root = null;
         Mailbox selected() { if (selected == null) throw new Bad("no mailbox selected"); return selected; }
-        final Server.Authenticator auth;
+        final Login auth;
         final Client client;
 
-        public MailboxWrapper(Server.Authenticator auth, Client c) { this.auth=auth; this.client=c;}
+        public MailboxWrapper(Login auth, Client c) { this.auth=auth; this.client=c;}
 
         private Mailbox mailbox(String name, boolean create) {
             if (name.equalsIgnoreCase("inbox")) return inbox;
@@ -151,7 +150,9 @@ public class IMAP {
             for(Mailbox.Iterator it=selected().iterator(q);it.next();) to.add(it.cur(), it.flags() | Mailbox.Flag.RECENT); }
 
         public void login(String u, String p) {
-            if ((root = auth.authenticate(u,p)) == null) throw new No("Login failed.");
+            Account account = null;
+            if ((account = auth.login(u,p)) == null) throw new No("Login failed.");
+            root = account.getMailbox(IMAP.class);
             inbox = mailbox("INBOX", false);  // FEATURE: ??
         }
         public void unselect() { selected = null; }
@@ -227,9 +228,10 @@ public class IMAP {
         String selectedName = null;
         Mailbox inbox = null, root = null;
         Server api;
+        Login auth = null;
         Parser parser = null;
         Connection conn = null;
-        public Listener() { }
+        public Listener(Login auth) { this.auth = auth; }
         Parser.Token token() { return parser.token(); }
         void println(String s) { conn.println(s); }
         void newline() { parser.newline(); }
@@ -237,7 +239,7 @@ public class IMAP {
         public void handleRequest(Connection conn) {
             this.conn = conn;
             parser = new Parser(conn);
-            api = new IMAP.MailboxWrapper(new BogusAuthenticator(), this);
+            api = new IMAP.MailboxWrapper(auth, this);
             conn.setTimeout(30 * 60 * 1000);
             println("* OK " + conn.vhost + " " + IMAP.class.getName() + " IMAP4rev1 [RFC3501] v" + version + " server ready");
             for(String tag = null;; newline()) try {
@@ -790,26 +792,8 @@ public class IMAP {
 
     // Main //////////////////////////////////////////////////////////////////////////////
 
-    /** simple listener for testing purposes */
-    public static void main(String[] args) throws Exception {
-        ServerSocket ss = new ServerSocket(143);
-        for(;;) {
-            final Socket s = ss.accept();
-            new Thread() { public void run() { try {
-                final Mailbox root = FileBasedMailbox.getFileBasedMailbox(Mailbox.STORAGE_ROOT+File.separatorChar+"imap", true);
-                new Listener();
-            } catch (Exception e) { e.printStackTrace(); } } }.start();
-        }
-    }
-
     public static final int
         PEEK=0x1, BODYSTRUCTURE=0x2, ENVELOPE=0x4, FLAGS=0x8, INTERNALDATE=0x10, FIELDS=0x800, FIELDSNOT=0x1000,
         RFC822=0x20, RFC822TEXT=0x40, RFC822SIZE=0x80, HEADERNOT=0x100, UID=0x200, HEADER=0x400;
 
-
-    public static class BogusAuthenticator implements IMAP.Server.Authenticator {
-        final Mailbox root = FileBasedMailbox.getFileBasedMailbox(Mailbox.STORAGE_ROOT, true).slash("user", true);
-        public Mailbox authenticate(String user, String pass) {
-            return EtcPasswd.verify(user, pass) ? root.slash(user, false) : null; }
-    }
 }
index 7cf409c..862d375 100644 (file)
@@ -96,13 +96,10 @@ public class NNTP {
     }
 
     public static class Listener implements Worker {
-        private Server api;
+        private Server api = null;
+        private Login login;
         private Connection conn;
-        public Listener(Server api) { this.api = api; }
-        public Listener() {
-            Mailbox root = FileBasedMailbox.getFileBasedMailbox("/var/org.ibex.mail/user/megacz/newmail/", true);
-            this.api = new MailboxWrapper(root);
-        }
+        public Listener(Login l) { this.login = l; }
 
         private void println(String s) { Log.warn("[nntp-write]", s); conn.println(s); }
         private void println() { Log.warn("[nntp-write]", ""); conn.println(); }
@@ -127,10 +124,29 @@ public class NNTP {
             this.conn = conn;
             conn.setTimeout(30 * 60 * 1000);
             println("200 " + conn.vhost + " [" + NNTP.class.getName() + "]");
+            String user = null;
+            String pass = null;
+            Account account = login.anonymous();
+            this.api = account == null ? null : new MailboxWrapper(account.getMailbox(NNTP.class));
             for(String line = conn.readln(); line != null; line = conn.readln()) try {
                 Log.warn("[nntp-read]", line);
                 StringTokenizer st = new StringTokenizer(line, " ");
                 String command = st.nextToken().toUpperCase();
+                if (command.equals("AUTHINFO")) {
+                    String uop = st.nextToken();
+                    if (uop.equals("USER")) user = st.nextToken();
+                    else if (uop.equals("PASS")) pass = st.nextToken();
+                    // FIXME error here
+                }
+                if (this.api == null) {
+                    if (user == null) { println("480 Authentication required"); continue; }
+                    if (pass == null) { println("381 Password required"); continue; }
+                    account = login.login(user, pass);
+                    if (account == null) { println("502 Invalid"); continue; }
+                    this.api = new MailboxWrapper(account.getMailbox(NNTP.class));
+                    println("281 Good to go");
+                    continue;
+                }
                 if        (command.equals("ARTICLE"))   { article(st.hasMoreTokens() ? st.nextToken() : null, true,  true); 
                 } else if (command.equals("HEAD"))      { article(st.hasMoreTokens() ? st.nextToken() : null, true,  false); 
                 } else if (command.equals("MODE"))      { println("201 Hello, you can post.");