use of com.biglybt.pif.ipfilter.IPRange in project BiglyBT by BiglySoftware.
the class RPRequestHandler method processRequestSupport.
protected RPReply processRequestSupport(RPRequest request, RPRequestAccessController access_controller) {
try {
RPObject object = request.getObject();
String method = request.getMethod();
if (object == null && method.equals("getSingleton")) {
RPObject pi = request.createRemotePluginInterface(plugin_interface);
RPReply reply = new RPReply(pi);
return (reply);
} else if (object == null && method.equals("getDownloads")) {
RPPluginInterface pi = request.createRemotePluginInterface(plugin_interface);
// short cut method for quick access to downloads
// used by GTS
RPObject dm = (RPObject) pi._process(new RPRequest(null, "getDownloadManager", null)).getResponse();
RPReply rep = dm._process(new RPRequest(null, "getDownloads", null));
rep.setProperty("azureus_name", pi.azureus_name);
rep.setProperty("azureus_version", pi.azureus_version);
return (rep);
} else if (object == null) {
throw new RPNoObjectIDException();
} else {
// System.out.println( "Request: con = " + request.getConnectionId() + ", req = " + request.getRequestId() + ", client = " + request.getClientIP());
object = RPObject._lookupLocal(object._getOID());
// _setLocal synchronizes the RP objects with their underlying
// plugin objects
object._setLocal();
if (method.equals("_refresh")) {
RPReply reply = new RPReply(object);
return (reply);
} else {
String name = object._getName();
if (access_controller != null) {
access_controller.checkAccess(name, request);
}
RPReply reply = object._process(request);
if (name.equals("IPFilter") && method.equals("setInRangeAddressesAreAllowed[boolean]") && request.getClientIP() != null) {
String client_ip = request.getClientIP();
// problem here, if someone changes the mode here they'll lose their
// connection coz they'll be denied access :)
boolean b = ((Boolean) request.getParams()[0]).booleanValue();
LoggerChannel[] channels = plugin_interface.getLogger().getChannels();
IPFilter filter = plugin_interface.getIPFilter();
if (b) {
if (filter.isInRange(client_ip)) {
for (int i = 0; i < channels.length; i++) {
channels[i].log(LoggerChannel.LT_INFORMATION, "Adding range for client '" + client_ip + "' as allow/deny flag changed to allow");
}
filter.createAndAddRange("auto-added for remote interface", client_ip, client_ip, false);
filter.save();
plugin_interface.getPluginconfig().save();
}
} else {
IPRange[] ranges = filter.getRanges();
for (int i = 0; i < ranges.length; i++) {
if (ranges[i].isInRange(client_ip)) {
for (int j = 0; j < channels.length; j++) {
channels[j].log(LoggerChannel.LT_INFORMATION, "deleting range '" + ranges[i].getStartIP() + "-" + ranges[i].getEndIP() + "' for client '" + client_ip + "' as allow/deny flag changed to deny");
}
ranges[i].delete();
}
}
filter.save();
plugin_interface.getPluginconfig().save();
}
}
return (reply);
}
}
} catch (RPException e) {
return (new RPReply(e));
} catch (Exception e) {
throw new RPInternalProcessException(e);
}
}
use of com.biglybt.pif.ipfilter.IPRange in project BiglyBT by BiglySoftware.
the class WebPlugin method setupAccess.
private void setupAccess() {
String access_str = param_access.getValue().trim();
String ip_ranges_str = "";
ip_ranges = null;
ip_range_all = false;
if (access_str.length() > 7 && Character.isDigit(access_str.charAt(0))) {
String[] ranges = access_str.replace(';', ',').split(",");
ip_ranges = new ArrayList<>();
for (String range : ranges) {
range = range.trim();
if (range.length() > 7) {
IPRange ip_range = plugin_interface.getIPFilter().createRange(true);
int sep = range.indexOf("-");
if (sep == -1) {
ip_range.setStartIP(range);
ip_range.setEndIP(range);
} else {
ip_range.setStartIP(range.substring(0, sep).trim());
ip_range.setEndIP(range.substring(sep + 1).trim());
}
ip_range.checkValid();
if (!ip_range.isValid()) {
log.log(LoggerChannel.LT_ERROR, "Access parameter '" + range + "' is invalid");
} else {
ip_ranges.add(ip_range);
ip_ranges_str += (ip_ranges_str.length() == 0 ? "" : ", ") + ip_range.getStartIP() + " - " + ip_range.getEndIP();
}
}
}
if (ip_ranges.size() == 0) {
ip_ranges = null;
}
} else {
if (access_str.equalsIgnoreCase("all") || access_str.length() == 0) {
ip_range_all = true;
}
}
log.log(LoggerChannel.LT_INFORMATION, "Acceptable IP range = " + (ip_ranges == null ? (ip_range_all ? "all" : "local") : (ip_ranges_str)));
}
use of com.biglybt.pif.ipfilter.IPRange in project BiglyBT by BiglySoftware.
the class WebPlugin method setupServer.
protected void setupServer() {
try {
if (!plugin_enabled) {
if (tracker_context != null) {
tracker_context.destroy();
tracker_context = null;
}
return;
}
final int port = param_port.getValue();
String protocol_str = param_protocol.getValue().trim();
String bind_str = param_bind.getValue().trim();
InetAddress bind_ip = null;
if (bind_str.length() > 0) {
try {
bind_ip = InetAddress.getByName(bind_str);
} catch (Throwable e) {
}
if (bind_ip == null) {
// might be an interface name, see if we can resolve it
final NetworkAdmin na = NetworkAdmin.getSingleton();
InetAddress[] addresses = na.resolveBindAddresses(bind_str);
if (addresses.length > 0) {
bind_ip = addresses[0];
if (!na_intf_listener_added) {
na_intf_listener_added = true;
na.addPropertyChangeListener(new NetworkAdminPropertyChangeListener() {
@Override
public void propertyChanged(String property) {
if (unloaded) {
na.removePropertyChangeListener(this);
} else {
if (property == NetworkAdmin.PR_NETWORK_INTERFACES) {
new AEThread2("setupserver") {
@Override
public void run() {
setupServer();
}
}.start();
}
}
}
});
}
}
}
if (bind_ip == null) {
log.log(LoggerChannel.LT_ERROR, "Bind IP parameter '" + bind_str + "' is invalid");
}
}
if (tracker_context != null) {
URL url = tracker_context.getURLs()[0];
String existing_protocol = url.getProtocol();
int existing_port = url.getPort() == -1 ? url.getDefaultPort() : url.getPort();
InetAddress existing_bind_ip = tracker_context.getBindIP();
if (existing_port == port && existing_protocol.equalsIgnoreCase(protocol_str) && sameAddress(bind_ip, existing_bind_ip)) {
return;
}
tracker_context.destroy();
tracker_context = null;
}
int protocol = protocol_str.equalsIgnoreCase("HTTP") ? Tracker.PR_HTTP : Tracker.PR_HTTPS;
Map<String, Object> tc_properties = new HashMap<>();
Boolean prop_non_blocking = (Boolean) properties.get(PR_NON_BLOCKING);
if (prop_non_blocking != null && prop_non_blocking) {
tc_properties.put(Tracker.PR_NON_BLOCKING, true);
}
log.log(LoggerChannel.LT_INFORMATION, "Server initialisation: port=" + port + (bind_ip == null ? "" : (", bind=" + bind_str + "->" + bind_ip + ")")) + ", protocol=" + protocol_str + (root_dir.length() == 0 ? "" : (", root=" + root_dir)) + (properties.size() == 0 ? "" : (", props=" + properties)));
tracker_context = plugin_interface.getTracker().createWebContext(Constants.APP_NAME + " - " + plugin_interface.getPluginName(), port, protocol, bind_ip, tc_properties);
Boolean prop_enable_i2p = (Boolean) properties.get(PR_ENABLE_I2P);
if (prop_enable_i2p == null || prop_enable_i2p) {
network_dispatcher.dispatch(new AERunnable() {
@Override
public void runSupport() {
Map<String, Object> options = new HashMap<>();
options.put(AEProxyFactory.SP_PORT, port);
Map<String, Object> reply = AEProxyFactory.getPluginServerProxy(plugin_interface.getPluginName(), AENetworkClassifier.AT_I2P, plugin_interface.getPluginID(), options);
if (reply != null) {
param_i2p_dest.setVisible(true);
String host = (String) reply.get("host");
if (!param_i2p_dest.getValue().equals(host)) {
param_i2p_dest.setValue(host);
if (p_sid != null) {
updatePairing(p_sid);
}
}
}
}
});
}
Boolean prop_enable_tor = (Boolean) properties.get(PR_ENABLE_TOR);
if (prop_enable_tor == null || prop_enable_tor) {
network_dispatcher.dispatch(new AERunnable() {
@Override
public void runSupport() {
Map<String, Object> options = new HashMap<>();
options.put(AEProxyFactory.SP_PORT, port);
Map<String, Object> reply = AEProxyFactory.getPluginServerProxy(plugin_interface.getPluginName(), AENetworkClassifier.AT_TOR, plugin_interface.getPluginID(), options);
if (reply != null) {
param_tor_dest.setVisible(true);
String host = (String) reply.get("host");
if (!param_tor_dest.getValue().equals(host)) {
param_tor_dest.setValue(host);
if (p_sid != null) {
updatePairing(p_sid);
}
}
}
}
});
}
Boolean pr_enable_keep_alive = (Boolean) properties.get(PR_ENABLE_KEEP_ALIVE);
if (pr_enable_keep_alive != null && pr_enable_keep_alive) {
tracker_context.setEnableKeepAlive(true);
}
tracker_context.addPageGenerator(this);
tracker_context.addAuthenticationListener(new TrackerAuthenticationAdapter() {
private String last_pw = "";
private byte[] last_hash = {};
private final int DELAY = 10 * 1000;
private Map<String, Object[]> fail_map = new HashMap<>();
@Override
public boolean authenticate(String headers, URL resource, String user, String pw) {
// System.out.println( resource + ": " + user + "/" + pw );
long now = SystemTime.getMonotonousTime();
String client_address = getHeaderField(headers, "X-Real-IP");
if (client_address == null) {
client_address = "<unknown>";
}
synchronized (logout_timer) {
Long logout_time = logout_timer.get(client_address);
if (logout_time != null && now - logout_time <= LOGOUT_GRACE_MILLIS) {
tls.set(GRACE_PERIOD_MARKER);
return (true);
}
}
boolean result = authenticateSupport(headers, resource, user, pw);
if (!result) {
if (!pw.equals("")) {
AESemaphore waiter = null;
synchronized (fail_map) {
Object[] x = fail_map.get(client_address);
if (x == null) {
x = new Object[] { new AESemaphore("af:waiter"), new Long(-1), new Long(-1), now };
fail_map.put(client_address, x);
} else {
x[1] = x[2];
x[2] = x[3];
x[3] = now;
long t = (Long) x[1];
if (now - t < 10 * 1000) {
log("Too many recent authentication failures from '" + client_address + "' - rate limiting");
x[2] = now + DELAY;
// there's a bug where flipping the password on doesn't reset the pw so we automatically fail without checking
// this is not the correct fix, but it works
last_pw = "";
waiter = (AESemaphore) x[0];
}
}
}
if (waiter != null) {
waiter.reserve(DELAY);
}
}
} else {
synchronized (fail_map) {
fail_map.remove(client_address);
}
String cookies = getHeaderField(headers, "Cookie");
if (pairing_session_code != null) {
if (cookies == null || !cookies.contains(pairing_session_code)) {
tls.set(pairing_session_code);
}
}
}
recordAuthRequest(client_address, result);
if (!result) {
// going to be generous here as (old android browsers at least) sometimes fail to provide
// auth on .png files
// no I'm not, too many risks associated with this (e.g. xmwebui has some
// prefix url logic which may be exploitable)
// if ( resource.getPath().endsWith( ".png" )){
//
// result = true;
// }
}
return (result);
}
private boolean authenticateSupport(String headers, URL resource, String user, String pw) {
boolean result;
boolean auto_auth = param_auto_auth != null && param_auto_auth.getValue();
if (!pw_enable.getValue()) {
String whitelist = p_no_pw_whitelist.getValue().trim();
if (whitelist.equals("*")) {
result = true;
} else {
String actual_host = getHeaderField(headers, "host");
int actual_port = protocol == Tracker.PR_HTTP ? 80 : 443;
String referrer = getHeaderField(headers, "referer");
if (actual_host.startsWith("[")) {
int pos = actual_host.lastIndexOf(']');
if (pos != -1) {
String rem = actual_host.substring(pos + 1);
actual_host = actual_host.substring(0, pos + 1);
pos = rem.indexOf(':');
if (pos != -1) {
actual_port = Integer.parseInt(rem.substring(pos + 1).trim());
}
}
} else {
int pos = actual_host.indexOf(':');
if (pos != -1) {
actual_port = Integer.parseInt(actual_host.substring(pos + 1).trim());
actual_host = actual_host.substring(0, pos);
}
}
String[] allowed = whitelist.split(",");
result = false;
String msg = "";
if (actual_port != port) {
msg = "port mismatch: " + port + "/" + actual_port;
} else {
for (String a : allowed) {
a = a.trim();
if (a.equals("$")) {
InetAddress bind = getServerBindIP();
if (bind != null) {
if (bind instanceof Inet6Address) {
a = "[" + bind.getHostAddress() + "]";
} else {
a = bind.getHostAddress();
}
}
}
if (actual_host.equals(a.trim())) {
result = true;
break;
}
// Support ranges (copied from code in setupAccess)
IPRange ip_range = plugin_interface.getIPFilter().createRange(true);
String aTrimmed = a.trim();
int sep = aTrimmed.indexOf("-");
if (sep == -1) {
ip_range.setStartIP(aTrimmed);
ip_range.setEndIP(aTrimmed);
} else {
ip_range.setStartIP(aTrimmed.substring(0, sep).trim());
ip_range.setEndIP(aTrimmed.substring(sep + 1).trim());
}
ip_range.checkValid();
if (ip_range.isValid() && ip_range.isInRange(actual_host)) {
result = true;
break;
}
}
if (!result) {
msg = "host '" + actual_host + "' not in whitelist";
} else {
if (referrer != null) {
result = false;
try {
URL url = new URL(referrer);
int ref_port = url.getPort();
if (ref_port == -1) {
ref_port = url.getDefaultPort();
}
if (ref_port == port) {
result = true;
}
} catch (Throwable e) {
}
if (!result) {
msg = "referrer mismatch: " + referrer;
}
}
}
}
if (!result) {
log.log("Access denied: No password and " + msg);
}
}
} else {
if (auto_auth) {
user = user.trim().toLowerCase();
pw = pw.toUpperCase();
}
if (!user.equals(p_user_name.getValue())) {
log.log("Access denied: Incorrect user name: " + user);
result = false;
} else {
byte[] hash = last_hash;
if (!last_pw.equals(pw)) {
hash = plugin_interface.getUtilities().getSecurityManager().calculateSHA1(auto_auth ? pw.toUpperCase().getBytes() : pw.getBytes());
last_pw = pw;
last_hash = hash;
}
result = Arrays.equals(hash, p_password.getValue());
if (!result) {
log.log("Access denied: Incorrect password");
}
}
}
if (result) {
// user name and password match, see if we've come from the pairing process
checkCookieSet(headers, resource);
} else if (auto_auth) {
// either the ac is in the url, referer or we have a cookie set
int x = checkCookieSet(headers, resource);
if (x == 1) {
result = true;
} else if (x == 0) {
result = hasOurCookie(getHeaderField(headers, "Cookie"));
}
} else {
result = hasOurCookie(getHeaderField(headers, "Cookie"));
}
return (result);
}
/**
* @param headers
* @param resource
* @return 0 = unknown, 1 = ok, 2 = bad
*/
private int checkCookieSet(String headers, URL resource) {
if (pairing_access_code == null) {
return (2);
}
String[] locations = { resource.getQuery(), getHeaderField(headers, "Referer") };
for (String location : locations) {
if (location != null) {
boolean skip_fail = false;
int param_len = 0;
int p1 = location.indexOf("vuze_pairing_ac=");
if (p1 == -1) {
p1 = location.indexOf("ac=");
if (p1 != -1) {
param_len = 3;
skip_fail = true;
}
} else {
param_len = 16;
}
if (p1 != -1) {
int p2 = location.indexOf('&', p1);
String ac = location.substring(p1 + param_len, p2 == -1 ? location.length() : p2).trim();
p2 = ac.indexOf('#');
if (p2 != -1) {
ac = ac.substring(0, p2);
}
if (ac.equalsIgnoreCase(pairing_access_code)) {
tls.set(pairing_session_code);
return (1);
} else {
if (!skip_fail) {
return (2);
}
}
}
}
}
return (0);
}
private String getHeaderField(String headers, String field) {
String[] lines = headers.split("\n");
for (String line : lines) {
int pos = line.indexOf(':');
if (pos != -1) {
if (line.substring(0, pos).equalsIgnoreCase(field)) {
return (line.substring(pos + 1).trim());
}
}
}
return (null);
}
});
} catch (TrackerException e) {
log.log("Server initialisation failed", e);
}
}
use of com.biglybt.pif.ipfilter.IPRange in project BiglyBT by BiglySoftware.
the class WebPlugin method generate2.
private boolean generate2(TrackerWebPageRequest request, TrackerWebPageResponse response, boolean is_tunnel) throws IOException {
// System.out.println( request.getURL());
String client = request.getClientAddress();
if (!ip_range_all) {
try {
boolean valid_ip = true;
InetAddress client_ia = InetAddress.getByName(client);
if (ip_ranges == null) {
if (!client_ia.isLoopbackAddress()) {
InetAddress bind_ia = getServerBindIP();
if (bind_ia.isAnyLocalAddress() || !bind_ia.equals(client_ia)) {
log.log(LoggerChannel.LT_ERROR, "Client '" + client + "' is not local, rejecting");
valid_ip = false;
}
}
} else {
boolean ok = false;
for (IPRange range : ip_ranges) {
if (range.isInRange(client_ia.getHostAddress())) {
ok = true;
}
}
if (!ok) {
log.log(LoggerChannel.LT_ERROR, "Client '" + client + "' (" + client_ia.getHostAddress() + ") is not in range, rejecting");
valid_ip = false;
}
}
if (!valid_ip) {
response.setReplyStatus(403);
recordRequest(request, false, is_tunnel);
return (returnTextPlain(response, "Cannot access resource from this IP address."));
}
} catch (Throwable e) {
Debug.printStackTrace(e);
recordRequest(request, false, is_tunnel);
return (false);
}
}
recordRequest(request, true, is_tunnel);
String url = request.getURL();
if (url.toString().endsWith(".class")) {
System.out.println("WebPlugin::generate:" + url);
}
String cookie_to_set = tls.get();
if (cookie_to_set == GRACE_PERIOD_MARKER) {
return (returnTextPlain(response, "Logout in progress, please try again later."));
}
if (cookie_to_set != null) {
// set session cookie
response.setHeader("Set-Cookie", "vuze_pairing_sc=" + cookie_to_set + "; path=/; HttpOnly");
tls.set(null);
}
URL full_url = request.getAbsoluteURL();
String full_url_path = full_url.getPath();
if (full_url_path.equals("/isPairedServiceAvailable")) {
String redirect = getArgumentFromURL(full_url, "redirect_to");
if (redirect != null) {
try {
URL target = new URL(redirect);
String host = target.getHost();
if (!Constants.isAzureusDomain(host)) {
if (!InetAddress.getByName(host).isLoopbackAddress()) {
log("Invalid redirect host: " + host);
redirect = null;
}
}
} catch (Throwable e) {
Debug.out(e);
redirect = null;
}
}
if (redirect != null) {
response.setReplyStatus(302);
response.setHeader("Location", redirect);
return (true);
}
String callback = getArgumentFromURL(full_url, "jsoncallback");
if (callback != null) {
return (returnTextPlain(response, callback + "( {'pairedserviceavailable':true} )"));
}
} else if (full_url_path.equals("/isServicePaired")) {
boolean paired = cookie_to_set != null || hasOurCookie((String) request.getHeaders().get("cookie"));
return (returnTextPlain(response, "{ 'servicepaired': " + (paired ? "true" : "false") + " }"));
} else if (full_url_path.equals("/pairedServiceLogout")) {
synchronized (logout_timer) {
logout_timer.put(client, SystemTime.getMonotonousTime());
}
response.setHeader("Set-Cookie", "vuze_pairing_sc=<deleted>, expires=" + TimeFormatter.getCookieDate(0));
String redirect = getArgumentFromURL(full_url, "redirect_to");
if (redirect != null) {
try {
URL target = new URL(redirect);
String host = target.getHost();
if (!Constants.isAzureusDomain(host)) {
if (!InetAddress.getByName(host).isLoopbackAddress()) {
log("Invalid redirect host: " + host);
redirect = null;
}
}
} catch (Throwable e) {
Debug.out(e);
redirect = null;
}
}
if (redirect == null) {
return (returnTextPlain(response, ""));
} else {
response.setReplyStatus(302);
response.setHeader("Location", redirect);
return (true);
}
}
request.getHeaders().put("x-vuze-is-tunnel", is_tunnel ? "true" : "false");
if (generateSupport(request, response)) {
return (true);
}
if (is_tunnel) {
return (false);
}
if (url.equals("/") || url.startsWith("/?")) {
url = "/";
if (home_page != null) {
url = home_page;
} else {
for (int i = 0; i < welcome_files.length; i++) {
if (welcome_files[i].exists()) {
url = "/" + welcome_pages[i];
break;
}
}
}
}
if (useFile(request, response, file_root, UrlUtils.decode(url))) {
return (true);
}
// now try jars
String resource_name = url;
if (resource_name.startsWith("/")) {
resource_name = resource_name.substring(1);
}
int pos = resource_name.lastIndexOf(".");
if (pos != -1) {
String type = resource_name.substring(pos + 1);
ClassLoader cl = plugin_interface.getPluginClassLoader();
InputStream is = cl.getResourceAsStream(resource_name);
if (is == null) {
if (resource_root != null) {
resource_name = resource_root + "/" + resource_name;
is = cl.getResourceAsStream(resource_name);
}
}
if (is != null) {
try {
response.useStream(type, is);
} finally {
is.close();
}
return (true);
}
}
return (false);
}
Aggregations