Skip to content

Commit 54448bb

Browse files
committed
Avoid NPEs in JavaNetAuthenticator for Type.DIRECT and unresolved socket addresses
1 parent fa783c3 commit 54448bb

File tree

2 files changed

+79
-13
lines changed

2 files changed

+79
-13
lines changed

okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/authenticator/JavaNetAuthenticator.kt

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,19 @@ class JavaNetAuthenticator(
5353
val dns = route?.address?.dns ?: defaultDns
5454
val auth =
5555
if (proxyAuthorization) {
56-
val proxyAddress = proxy.address() as InetSocketAddress
57-
Authenticator.requestPasswordAuthentication(
58-
proxyAddress.hostName,
59-
proxy.connectToInetAddress(url, dns),
60-
proxyAddress.port,
61-
url.scheme,
62-
challenge.realm,
63-
challenge.scheme,
64-
url.toUrl(),
65-
Authenticator.RequestorType.PROXY,
66-
)
56+
if (proxy.type() == Proxy.Type.HTTP) {
57+
val proxyAddress = proxy.address() as InetSocketAddress
58+
Authenticator.requestPasswordAuthentication(
59+
proxyAddress.hostName,
60+
proxy.connectToInetAddress(url, dns),
61+
proxyAddress.port,
62+
url.scheme,
63+
challenge.realm,
64+
challenge.scheme,
65+
url.toUrl(),
66+
Authenticator.RequestorType.PROXY,
67+
)
68+
} else null
6769
} else {
6870
Authenticator.requestPasswordAuthentication(
6971
url.host,
@@ -102,6 +104,11 @@ class JavaNetAuthenticator(
102104
): InetAddress =
103105
when (type()) {
104106
Proxy.Type.DIRECT -> dns.lookup(url.host).first()
105-
else -> (address() as InetSocketAddress).address
107+
else -> {
108+
val socketAddress = address() as InetSocketAddress
109+
if (socketAddress.isUnresolved) {
110+
dns.lookup(socketAddress.hostString).first()
111+
} else socketAddress.address
112+
}
106113
}
107114
}

okhttp/src/jvmTest/kotlin/okhttp3/internal/authenticator/JavaNetAuthenticatorTest.kt

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ package okhttp3.internal.authenticator
1717

1818
import java.net.Authenticator
1919
import java.net.InetAddress
20-
import junit.framework.TestCase.assertNull
20+
import java.net.InetSocketAddress
21+
import java.net.Proxy
2122
import okhttp3.FakeDns
2223
import okhttp3.Protocol.HTTP_2
2324
import okhttp3.Request
@@ -26,6 +27,7 @@ import okhttp3.TestValueFactory
2627
import okhttp3.internal.RecordingAuthenticator
2728
import org.junit.jupiter.api.AfterEach
2829
import org.junit.jupiter.api.Assertions.assertEquals
30+
import org.junit.jupiter.api.Assertions.assertNull
2931
import org.junit.jupiter.api.BeforeEach
3032
import org.junit.jupiter.api.Test
3133

@@ -100,4 +102,61 @@ class JavaNetAuthenticatorTest {
100102
val authRequest = authenticator.authenticate(null, response)
101103
assertNull(authRequest)
102104
}
105+
106+
@Test
107+
fun testProxyAuthDirect() {
108+
fakeDns["server"] = listOf(InetAddress.getLocalHost())
109+
110+
val route = factory.newRoute()
111+
112+
val request =
113+
Request
114+
.Builder()
115+
.url("https://server/robots.txt")
116+
.build()
117+
val response =
118+
Response
119+
.Builder()
120+
.request(request)
121+
.code(407)
122+
.header("Proxy-Authenticate", "Basic realm=\"User Visible Realm\"")
123+
.protocol(HTTP_2)
124+
.message("Unauthorized")
125+
.build()
126+
val authRequest = authenticator.authenticate(route, response)
127+
128+
assertNull(authRequest)
129+
}
130+
131+
@Test
132+
fun testProxyAuthUnresolvedAddress() {
133+
fakeDns["server"] = listOf(InetAddress.getLocalHost())
134+
fakeDns["127.0.0.1"] = listOf(InetAddress.getLocalHost())
135+
136+
// ProxySelector's default implementation, sun.net.spi.DefaultProxySelector, returns unresolved addresses
137+
val proxy = Proxy(Proxy.Type.HTTP, InetSocketAddress.createUnresolved("127.0.0.1", 3128))
138+
val route = factory.newRoute(proxy = proxy)
139+
140+
val request =
141+
Request
142+
.Builder()
143+
.url("https://server/robots.txt")
144+
.build()
145+
val response =
146+
Response
147+
.Builder()
148+
.request(request)
149+
.code(407)
150+
.header("Proxy-Authenticate", "Basic realm=\"User Visible Realm\"")
151+
.protocol(HTTP_2)
152+
.message("Unauthorized")
153+
.build()
154+
val authRequest = authenticator.authenticate(route, response)
155+
156+
assertEquals(
157+
"Basic ${RecordingAuthenticator.BASE_64_CREDENTIALS}",
158+
authRequest!!.header("Proxy-Authorization"),
159+
)
160+
}
161+
103162
}

0 commit comments

Comments
 (0)