use of com.biglybt.pif.tracker.TrackerException in project BiglyBT by BiglySoftware.
the class RPTracker method _process.
@Override
public RPReply _process(RPRequest request) {
String method = request.getMethod();
Object[] params = request.getParams();
if (method.equals("host[Torrent,boolean]")) {
try {
Torrent torrent = params[0] == null ? null : (Torrent) ((RPTorrent) params[0])._setLocal();
if (torrent == null) {
throw (new RPException("Invalid torrent"));
}
TrackerTorrent tt = delegate.host(torrent, ((Boolean) params[1]).booleanValue());
RPTrackerTorrent res = RPTrackerTorrent.create(tt);
return (new RPReply(res));
} catch (TrackerException e) {
return (new RPReply(e));
}
} else if (method.equals("getTorrents")) {
TrackerTorrent[] torrents = delegate.getTorrents();
RPTrackerTorrent[] res = new RPTrackerTorrent[torrents.length];
for (int i = 0; i < res.length; i++) {
res[i] = RPTrackerTorrent.create(torrents[i]);
}
return (new RPReply(res));
}
throw (new RPException("Unknown method: " + method));
}
use of com.biglybt.pif.tracker.TrackerException 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.tracker.TrackerException in project BiglyBT by BiglySoftware.
the class RPTracker method host.
// ************************************************************************
@Override
public TrackerTorrent host(Torrent torrent, boolean persistent) throws TrackerException {
try {
RPTrackerTorrent resp = (RPTrackerTorrent) _dispatcher.dispatch(new RPRequest(this, "host[Torrent,boolean]", new Object[] { torrent, Boolean.valueOf(persistent) })).getResponse();
resp._setRemote(_dispatcher);
return (resp);
} catch (RPException e) {
if (e.getCause() instanceof TrackerException) {
throw ((TrackerException) e.getCause());
}
throw (e);
}
}
Aggregations