Browse Source

Rework how the IRCAuthenticator works:

- IRCAuthenticator only stores a username/password for a proxyhost:proxyport pair for as long as there are servers registerd that use that proxy. (Servers configured to use the proxy but with no username/password are not known by the IRCAuthenticator)

Rework how the IRCParser uses the IRCAuthenticator:
- Connecting to any socks-proxied server is now semaphored to 1 at a time so that it shouldn't be possible for the IRCAuthenticator to know of more than 1 username/password pair at a time (which negates the need for the above change when used by this IRCParser)

This should prevent the issue described in issue 1852 from happening.

Change-Id: Ifaa3aaca5aafcddf11b2e8fcbc691903c2fefd10
Reviewed-on: http://gerrit.dmdirc.com/112
Tested-by: Shane Mc Cormack <shane@dmdirc.com>
Reviewed-by: Chris Smith <chris@dmdirc.com>
tags/0.6.3
Shane Mc Cormack 14 years ago
parent
commit
683f094627

+ 56
- 26
src/com/dmdirc/parser/irc/IRCAuthenticator.java View File

@@ -25,8 +25,12 @@ package com.dmdirc.parser.irc;
25 25
 import java.net.Authenticator;
26 26
 import java.net.PasswordAuthentication;
27 27
 
28
+import java.util.ArrayList;
28 29
 import java.util.Map;
29 30
 import java.util.HashMap;
31
+import java.util.List;
32
+
33
+import java.util.concurrent.Semaphore;
30 34
 
31 35
 /**
32 36
  * Handles proxy authentication for the parser.
@@ -47,7 +51,13 @@ public class IRCAuthenticator extends Authenticator {
47 51
     
48 52
     /** List of authentication replies. */
49 53
     private final Map<String,PasswordAuthentication> replies = new HashMap<String,PasswordAuthentication>();
50
-    
54
+
55
+    /** List of servers for each host. */
56
+    private final Map<String, List<ServerInfo>> owners = new HashMap<String, List<ServerInfo>>();
57
+
58
+    /** Semaphore for connection limiting. */
59
+    private final Semaphore mySemaphore = new Semaphore(1, true);
60
+
51 61
     /**
52 62
      * Create a new IRCAuthenticator.
53 63
      *
@@ -55,16 +65,6 @@ public class IRCAuthenticator extends Authenticator {
55 65
      * Authenticator.
56 66
      */
57 67
     private IRCAuthenticator() {
58
-/*        try {
59
-            final Field field = Authenticator.class.getDeclaredField("theAuthenticator");
60
-            field.setAccessible(true);
61
-            final Object authenticator = field.get(null);
62
-            if (authenticator instanceof Authenticator) {
63
-                oldAuthenticator = (Authenticator)authenticator;
64
-            }
65
-        } catch (NoSuchFieldException nsfe) {
66
-        } catch (IllegalAccessException iae) {
67
-        }*/
68 68
         Authenticator.setDefault(this);
69 69
     }
70 70
     
@@ -76,6 +76,9 @@ public class IRCAuthenticator extends Authenticator {
76 76
     public static synchronized IRCAuthenticator getIRCAuthenticator() {
77 77
         if (me == null) {
78 78
             me = new IRCAuthenticator();
79
+        } else {
80
+            // Make ourself the default authenticator again just incase.
81
+            Authenticator.setDefault(me);
79 82
         }
80 83
         return me;
81 84
     }
@@ -86,32 +89,59 @@ public class IRCAuthenticator extends Authenticator {
86 89
      * @param server ServerInfo object with proxy details.
87 90
      */
88 91
     public void addAuthentication(final ServerInfo server) {
89
-        addAuthentication(server.getProxyHost(), server.getProxyPort(), server.getProxyUser(), server.getProxyPass());
92
+        final String host = server.getProxyHost();
93
+        final int port = server.getProxyPort();
94
+        final String username = server.getProxyUser();
95
+        final String password = server.getProxyPass();
96
+
97
+        if (username == null || password == null || username.isEmpty() || password.isEmpty()) { return; }
98
+        
99
+        final PasswordAuthentication pass = new PasswordAuthentication(username, password.toCharArray());
100
+        final String fullhost = host.toLowerCase()+":"+port;
101
+
102
+        // Delete old username/password if one exists and then add the new one
103
+        replies.remove(fullhost);
104
+        replies.put(fullhost, pass);
105
+
106
+        // Store which servers are associated with which proxy
107
+        final List<ServerInfo> servers = owners.containsKey(fullhost) ? owners.get(fullhost) : new ArrayList<ServerInfo>();
108
+        owners.remove(fullhost);
109
+        servers.add(server);
110
+        owners.put(fullhost, servers);
90 111
     }
91 112
 
92 113
     /**
93
-     * Add a host to authenticate for.
114
+     * Get a copy of the semaphore
94 115
      *
95
-     * @param host Hostname
96
-     * @param port Port
97
-     * @param username Username to return for authentication
98
-     * @param password Password to return for authentication
116
+     * @return the IRCAuthenticator semaphore.
99 117
      */
100
-    public void addAuthentication(final String host, final int port, final String username, final String password) {
101
-        if (username == null || password == null || username.isEmpty() || password.isEmpty()) {
102
-            return;
103
-        }
104
-        final PasswordAuthentication pass = new PasswordAuthentication(username, password.toCharArray());
118
+    public Semaphore getSemaphore() {
119
+        return mySemaphore;
120
+    }
121
+
122
+    /**
123
+     * Remove a server to authenticate for.
124
+     *
125
+     * @param server ServerInfo object with proxy details.
126
+     */
127
+    public void removeAuthentication(final ServerInfo server) {
128
+        final String host = server.getProxyHost();
129
+        final int port = server.getProxyPort();
130
+
105 131
         final String fullhost = host.toLowerCase()+":"+port;
106
-        
107
-        if (replies.containsKey(fullhost)) {
132
+
133
+        // See if any other servers are associated with this proxy.
134
+        final List<ServerInfo> servers = owners.containsKey(fullhost) ? owners.get(fullhost) : new ArrayList<ServerInfo>();
135
+        servers.remove(server);
136
+        if (servers.size() == 0) {
137
+            // No more servers need this authentication info, remove.
138
+            owners.remove(fullhost);
108 139
             replies.remove(fullhost);
109 140
         }
110
-        
111
-        replies.put(fullhost, pass);
112 141
     }
113 142
     
114 143
     /** {@inheritDoc} */
144
+    @Override
115 145
     protected PasswordAuthentication getPasswordAuthentication() {
116 146
         /*
117 147
          * getRequestingHost: 85.234.138.2

+ 10
- 3
src/com/dmdirc/parser/irc/IRCParser.java View File

@@ -681,10 +681,17 @@ public class IRCParser implements SecureParser, Runnable {
681 681
             final Proxy.Type proxyType = Proxy.Type.SOCKS;
682 682
             socket = new Socket(new Proxy(proxyType, new InetSocketAddress(server.getProxyHost(), server.getProxyPort())));
683 683
             currentSocketState = SocketState.OPENING;
684
-            if (server.getProxyUser() != null && !server.getProxyUser().isEmpty()) {
685
-                IRCAuthenticator.getIRCAuthenticator().addAuthentication(server);
684
+
685
+            final IRCAuthenticator ia = IRCAuthenticator.getIRCAuthenticator();
686
+
687
+            try {
688
+                try { ia.getSemaphore().acquire(); } catch (InterruptedException ex) { }
689
+                ia.addAuthentication(server);
690
+                socket.connect(new InetSocketAddress(server.getHost(), server.getPort()));
691
+            } finally {
692
+                ia.removeAuthentication(server);
693
+                ia.getSemaphore().release();
686 694
             }
687
-            socket.connect(new InetSocketAddress(server.getHost(), server.getPort()));
688 695
         } else {
689 696
             callDebugInfo(DEBUG_SOCKET, "Not using Proxy");
690 697
             if (!server.getSSL()) {

Loading…
Cancel
Save