< prev index next >
test/jdk/java/net/httpclient/ProxyServer.java
Print this page
*** 1,7 ****
/*
! * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
--- 1,7 ----
/*
! * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*** 23,32 ****
--- 23,35 ----
import java.net.*;
import java.io.*;
import java.util.*;
import java.security.*;
+ import static java.nio.charset.StandardCharsets.UTF_8;
+ import static java.util.Arrays.asList;
+ import static java.util.stream.Collectors.toList;
/**
* A minimal proxy server that supports CONNECT tunneling. It does not do
* any header transformations. In future this could be added.
* Two threads are created per client connection. So, it's not
*** 35,66 ****
public class ProxyServer extends Thread implements Closeable {
ServerSocket listener;
int port;
volatile boolean debug;
/**
* Create proxy on port (zero means don't care). Call getPort()
* to get the assigned port.
*/
public ProxyServer(Integer port) throws IOException {
this(port, false);
}
! public ProxyServer(Integer port, Boolean debug) throws IOException {
this.debug = debug;
listener = new ServerSocket();
listener.setReuseAddress(false);
listener.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), port));
this.port = listener.getLocalPort();
setName("ProxyListener");
setDaemon(true);
connections = new LinkedList<>();
start();
}
! public ProxyServer(String s) { }
/**
* Returns the port number this proxy is listening on
*/
public int getPort() {
--- 38,104 ----
public class ProxyServer extends Thread implements Closeable {
ServerSocket listener;
int port;
volatile boolean debug;
+ private final Credentials credentials; // may be null
+
+ private static class Credentials {
+ private final String name;
+ private final String password;
+ private Credentials(String name, String password) {
+ this.name = name;
+ this.password = password;
+ }
+ public String name() { return name; }
+ public String password() { return password; }
+ }
/**
* Create proxy on port (zero means don't care). Call getPort()
* to get the assigned port.
*/
public ProxyServer(Integer port) throws IOException {
this(port, false);
}
! public ProxyServer(Integer port,
! Boolean debug,
! String username,
! String password)
! throws IOException
! {
! this(port, debug, new Credentials(username, password));
! }
!
! public ProxyServer(Integer port,
! Boolean debug)
! throws IOException
! {
! this(port, debug, null);
! }
!
! public ProxyServer(Integer port,
! Boolean debug,
! Credentials credentials)
! throws IOException
! {
this.debug = debug;
listener = new ServerSocket();
listener.setReuseAddress(false);
listener.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), port));
this.port = listener.getLocalPort();
+ this.credentials = credentials;
setName("ProxyListener");
setDaemon(true);
connections = new LinkedList<>();
start();
}
! public ProxyServer(String s) {
! credentials = null;
! }
/**
* Returns the port number this proxy is listening on
*/
public int getPort() {
*** 192,211 ****
}
}
return -1;
}
public void init() {
try {
! byte[] buf = readHeaders(clientIn);
! int p = findCRLF(buf);
! if (p == -1) {
close();
return;
}
String cmd = new String(buf, 0, p, "US-ASCII");
String[] params = cmd.split(" ");
if (params[0].equals("CONNECT")) {
doTunnel(params[1]);
} else {
doProxy(params[1], buf, p, cmd);
}
--- 230,302 ----
}
}
return -1;
}
+ // Checks credentials in the request against those allowable by the proxy.
+ private boolean authorized(Credentials credentials,
+ List<String> requestHeaders) {
+ List<String> authorization = requestHeaders.stream()
+ .filter(n -> n.toLowerCase(Locale.US).startsWith("proxy-authorization"))
+ .collect(toList());
+
+ if (authorization.isEmpty())
+ return false;
+
+ if (authorization.size() != 1) {
+ throw new IllegalStateException("Authorization unexpected count:" + authorization);
+ }
+ String value = authorization.get(0).substring("proxy-authorization".length()).trim();
+ if (!value.startsWith(":"))
+ throw new IllegalStateException("Authorization malformed: " + value);
+ value = value.substring(1).trim();
+
+ if (!value.startsWith("Basic "))
+ throw new IllegalStateException("Authorization not Basic: " + value);
+
+ value = value.substring("Basic ".length());
+ String values = new String(Base64.getDecoder().decode(value), UTF_8);
+ int sep = values.indexOf(':');
+ if (sep < 1) {
+ throw new IllegalStateException("Authorization no colon: " + values);
+ }
+ String name = values.substring(0, sep);
+ String password = values.substring(sep + 1);
+
+ if (name.equals(credentials.name()) && password.equals(credentials.password()))
+ return true;
+
+ return false;
+ }
+
public void init() {
try {
! byte[] buf;
! while (true) {
! buf = readHeaders(clientIn);
! if (findCRLF(buf) == -1) {
close();
return;
}
+
+ List<String> headers = asList(new String(buf, UTF_8).split("\r\n"));
+ // check authorization credentials, if required by the server
+ if (credentials != null && !authorized(credentials, headers)) {
+ String resp = "HTTP/1.1 407 Proxy Authentication Required\r\n" +
+ "Content-Length: 0\r\n" +
+ "Proxy-Authenticate: Basic realm=\"proxy realm\"\r\n\r\n";
+
+ clientOut.write(resp.getBytes(UTF_8));
+ } else {
+ break;
+ }
+ }
+
+ int p = findCRLF(buf);
String cmd = new String(buf, 0, p, "US-ASCII");
String[] params = cmd.split(" ");
+
if (params[0].equals("CONNECT")) {
doTunnel(params[1]);
} else {
doProxy(params[1], buf, p, cmd);
}
< prev index next >