Browse Source

defensive code against null create/update requests. fix mr user blocker

tags/v0.7.0
Jonathan Cobb 5 years ago
parent
commit
668831e51b
9 changed files with 22 additions and 10 deletions
  1. +2
    -0
      automation/roles/mitmproxy/files/dns_spoofing.py
  2. +2
    -1
      bubble-server/src/main/java/bubble/model/app/AppMatcher.java
  3. +5
    -1
      bubble-server/src/main/java/bubble/resources/account/AccountOwnedResource.java
  4. +8
    -3
      bubble-server/src/main/java/bubble/resources/stream/FilterHttpResource.java
  5. +1
    -1
      bubble-server/src/main/java/bubble/rule/bblock/BubbleBlockRuleDriver.java
  6. +1
    -1
      bubble-server/src/main/java/bubble/rule/social/block/JsUserBlockerRuleDriver.java
  7. +1
    -1
      bubble-server/src/main/resources/bubble/rule/bblock/BubbleBlockRuleDriver.js.hbs
  8. +1
    -1
      bubble-server/src/main/resources/bubble/rule/social/block/site/MR.js.hbs
  9. +1
    -1
      bubble-server/src/main/resources/models/apps/user_block/mr/bubbleApp_userBlock_mr_matchers.json

+ 2
- 0
automation/roles/mitmproxy/files/dns_spoofing.py View File

@@ -55,6 +55,8 @@ class Rerouter:
if re.match(m['urlRegex'], flow.request.path): if re.match(m['urlRegex'], flow.request.path):
bubble_log('get_matchers: rule matched, adding rule: '+m['rule']) bubble_log('get_matchers: rule matched, adding rule: '+m['rule'])
matcher_ids.append(m['uuid']) matcher_ids.append(m['uuid'])
else:
bubble_log('get_matchers: rule (regex='+m['urlRegex']+') did NOT match, skipping rule: '+m['rule'])


matcher_response = { 'matchers': matcher_ids, 'request_id': req_id } matcher_response = { 'matchers': matcher_ids, 'request_id': req_id }
bubble_log("get_matchers: returning "+repr(matcher_response)) bubble_log("get_matchers: returning "+repr(matcher_response))


+ 2
- 1
bubble-server/src/main/java/bubble/model/app/AppMatcher.java View File

@@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import org.cobbzilla.util.collection.ArrayUtil; import org.cobbzilla.util.collection.ArrayUtil;
import org.cobbzilla.util.collection.HasPriority; import org.cobbzilla.util.collection.HasPriority;
@@ -28,7 +29,7 @@ import static org.cobbzilla.wizard.model.crypto.EncryptedTypes.ENC_PAD;


@ECType(root=true) @ECType(root=true)
@ECTypeURIs(baseURI=EP_MATCHERS, listFields={"name", "app", "fqdn", "urlRegex", "rule"}) @ECTypeURIs(baseURI=EP_MATCHERS, listFields={"name", "app", "fqdn", "urlRegex", "rule"})
@Entity @NoArgsConstructor @Accessors(chain=true)
@Entity @NoArgsConstructor @Accessors(chain=true) @ToString
@ECIndexes({ @ECIndexes({
@ECIndex(unique=true, of={"account", "app", "name"}), @ECIndex(unique=true, of={"account", "app", "name"}),
@ECIndex(of={"account", "name"}), @ECIndex(of={"account", "name"}),


+ 5
- 1
bubble-server/src/main/java/bubble/resources/account/AccountOwnedResource.java View File

@@ -7,6 +7,7 @@ import bubble.model.account.HasAccount;
import bubble.model.account.HasAccountNoName; import bubble.model.account.HasAccountNoName;
import bubble.server.BubbleConfiguration; import bubble.server.BubbleConfiguration;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.glassfish.grizzly.http.server.Request; import org.glassfish.grizzly.http.server.Request;
import org.glassfish.jersey.server.ContainerRequest; import org.glassfish.jersey.server.ContainerRequest;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -23,6 +24,7 @@ import static org.cobbzilla.wizard.resources.ResourceUtil.*;


@Consumes(APPLICATION_JSON) @Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON) @Produces(APPLICATION_JSON)
@Slf4j
public class AccountOwnedResource<E extends HasAccount, DAO extends AccountOwnedEntityDAO<E>> { public class AccountOwnedResource<E extends HasAccount, DAO extends AccountOwnedEntityDAO<E>> {


@Autowired protected AccountDAO accountDAO; @Autowired protected AccountDAO accountDAO;
@@ -123,6 +125,7 @@ public class AccountOwnedResource<E extends HasAccount, DAO extends AccountOwned
public Response create(@Context Request req, public Response create(@Context Request req,
@Context ContainerRequest ctx, @Context ContainerRequest ctx,
E request) { E request) {
if (request == null) return invalid("err.request.invalid");
final Account caller = checkEditable(ctx); final Account caller = checkEditable(ctx);
E found = find(ctx, request.getName()); E found = find(ctx, request.getName());
if (found == null) { if (found == null) {
@@ -149,13 +152,14 @@ public class AccountOwnedResource<E extends HasAccount, DAO extends AccountOwned
public Response update(@Context ContainerRequest ctx, public Response update(@Context ContainerRequest ctx,
@PathParam("id") String id, @PathParam("id") String id,
E request) { E request) {
if (request == null) return invalid("err.request.invalid");
final Account caller = checkEditable(ctx); final Account caller = checkEditable(ctx);
E found = find(ctx, id); E found = find(ctx, id);
if (found == null) { if (found == null) {
found = findAlternateForUpdate(ctx, id); found = findAlternateForUpdate(ctx, id);
if (found == null) return notFound(id); if (found == null) return notFound(id);
} }
if (!(found instanceof HasAccountNoName) && !canChangeName() && request.hasName() && !found.getName().equals(request.getName())) {
if (!(found instanceof HasAccountNoName) && !canChangeName() && request.hasName() && !request.getName().equals(found.getName())) {
return notFound(id+"/"+request.getName()); return notFound(id+"/"+request.getName());
} }




+ 8
- 3
bubble-server/src/main/java/bubble/resources/stream/FilterHttpResource.java View File

@@ -144,8 +144,8 @@ public class FilterHttpResource {
if (device == null) { if (device == null) {
if (log.isDebugEnabled()) log.debug(prefix+"device not found for IP "+vpnAddr+", returning no matchers"); if (log.isDebugEnabled()) log.debug(prefix+"device not found for IP "+vpnAddr+", returning no matchers");
return ok(NO_MATCHERS); return ok(NO_MATCHERS);
} else if (log.isDebugEnabled()) {
log.debug(prefix+"found device "+device.id()+" for IP "+vpnAddr);
} else if (log.isTraceEnabled()) {
log.trace(prefix+"found device "+device.id()+" for IP "+vpnAddr);
} }
filterRequest.setDevice(device.getUuid()); filterRequest.setDevice(device.getUuid());
final FilterMatchersResponse response = getMatchersResponse(filterRequest, req, request); final FilterMatchersResponse response = getMatchersResponse(filterRequest, req, request);
@@ -188,6 +188,8 @@ public class FilterHttpResource {
case no_match: break; case no_match: break;
case match: retainMatchers.put(matcher.getUuid(), matcher); break; case match: retainMatchers.put(matcher.getUuid(), matcher); break;
} }
} else {
if (log.isDebugEnabled()) log.debug(prefix+"matcher "+matcher.getName()+" with pattern "+matcher.getUrlRegex()+" did NOT match uri: '"+uri+"'");
} }
} }
} }
@@ -208,6 +210,7 @@ public class FilterHttpResource {
if (log.isTraceEnabled()) log.trace(prefix+"checking all enabled matchers for fqdn: "+json(matchers, COMPACT_MAPPER)); if (log.isTraceEnabled()) log.trace(prefix+"checking all enabled matchers for fqdn: "+json(matchers, COMPACT_MAPPER));
matchers = matchers.stream() matchers = matchers.stream()
.filter(m -> appDAO.findByAccountAndId(accountUuid, m.getApp()).enabled()).collect(Collectors.toList()); .filter(m -> appDAO.findByAccountAndId(accountUuid, m.getApp()).enabled()).collect(Collectors.toList());
if (log.isTraceEnabled()) log.trace(prefix+"after removing disabled apps, enabled matchers for fqdn: "+json(matchers, COMPACT_MAPPER));
matchers = matchers.stream() matchers = matchers.stream()
.filter(m -> { .filter(m -> {
final AppSite site = siteDAO.findByAccountAndAppAndId(accountUuid, m.getApp(), m.getSite()); final AppSite site = siteDAO.findByAccountAndAppAndId(accountUuid, m.getApp(), m.getSite());
@@ -217,6 +220,7 @@ public class FilterHttpResource {
} }
return site.enabled(); return site.enabled();
}).collect(Collectors.toList()); }).collect(Collectors.toList());
if (log.isTraceEnabled()) log.trace(prefix+"after removing disabled sites, enabled matchers for fqdn: "+json(matchers, COMPACT_MAPPER));
matchers = matchers.stream() matchers = matchers.stream()
.filter(m -> { .filter(m -> {
final AppRule rule = ruleDAO.findByAccountAndAppAndId(accountUuid, m.getApp(), m.getRule()); final AppRule rule = ruleDAO.findByAccountAndAppAndId(accountUuid, m.getApp(), m.getRule());
@@ -226,7 +230,8 @@ public class FilterHttpResource {
} }
return rule.enabled(); return rule.enabled();
}).collect(Collectors.toList()); }).collect(Collectors.toList());
if (log.isDebugEnabled()) log.debug(prefix+"found "+matchers.size()+" candidate matchers: "+names(matchers));
if (log.isTraceEnabled()) log.trace(prefix+"after removing disabled rules, enabled matchers for fqdn: "+json(matchers, COMPACT_MAPPER));
else if (log.isDebugEnabled()) log.debug(prefix+"found "+matchers.size()+" candidate matchers: "+names(matchers));
return matchers; return matchers;
} }




+ 1
- 1
bubble-server/src/main/java/bubble/rule/bblock/BubbleBlockRuleDriver.java View File

@@ -170,7 +170,7 @@ public class BubbleBlockRuleDriver extends TrafficAnalyticsRuleDriver {
return in; return in;
} }


final String replacement = "<head><meta charset=\"UTF-8\"><script>" + getBubbleJs(filterRequest.getId(), decision) + "</script>";
final String replacement = "<head><script>" + getBubbleJs(filterRequest.getId(), decision) + "</script>";
final RegexReplacementFilter filter = new RegexReplacementFilter("<head>", replacement); final RegexReplacementFilter filter = new RegexReplacementFilter("<head>", replacement);
final RegexFilterReader reader = new RegexFilterReader(new InputStreamReader(in, UTF8cs), filter).setMaxMatches(1); final RegexFilterReader reader = new RegexFilterReader(new InputStreamReader(in, UTF8cs), filter).setMaxMatches(1);
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {


+ 1
- 1
bubble-server/src/main/java/bubble/rule/social/block/JsUserBlockerRuleDriver.java View File

@@ -32,7 +32,7 @@ public class JsUserBlockerRuleDriver extends AbstractAppRuleDriver {
@Override public InputStream doFilterResponse(FilterHttpRequest filterRequest, InputStream in) { @Override public InputStream doFilterResponse(FilterHttpRequest filterRequest, InputStream in) {
if (!isHtml(filterRequest.getContentType())) return in; if (!isHtml(filterRequest.getContentType())) return in;


final String replacement = "<head><script>" + getBubbleJs(filterRequest.getId()) + "</script>";
final String replacement = "<head><meta charset=\"UTF-8\"><script>" + getBubbleJs(filterRequest.getId()) + "</script>";
final RegexReplacementFilter filter = new RegexReplacementFilter("<head>", replacement); final RegexReplacementFilter filter = new RegexReplacementFilter("<head>", replacement);
final RegexFilterReader reader = new RegexFilterReader(new InputStreamReader(in), filter).setMaxMatches(1); final RegexFilterReader reader = new RegexFilterReader(new InputStreamReader(in), filter).setMaxMatches(1);
return new ReaderInputStream(reader, UTF8cs); return new ReaderInputStream(reader, UTF8cs);


+ 1
- 1
bubble-server/src/main/resources/bubble/rule/bblock/BubbleBlockRuleDriver.js.hbs View File

@@ -1,7 +1,7 @@
let {{JS_PREFIX}}_doc_ready = false; let {{JS_PREFIX}}_doc_ready = false;
const {{JS_PREFIX}}_request_id = '{{BUBBLE_REQUEST_ID}}'; const {{JS_PREFIX}}_request_id = '{{BUBBLE_REQUEST_ID}}';
const {{JS_PREFIX}}_interval = 50; const {{JS_PREFIX}}_interval = 50;
const {{JS_PREFIX}}_idle_interval = 1000;
const {{JS_PREFIX}}_idle_interval = 5000;


const {{JS_PREFIX}}_blacklist = {{{BUBBLE_BLACKLIST_JSON}}}; const {{JS_PREFIX}}_blacklist = {{{BUBBLE_BLACKLIST_JSON}}};
const {{JS_PREFIX}}_whitelist = {{{BUBBLE_WHITELIST_JSON}}}; const {{JS_PREFIX}}_whitelist = {{{BUBBLE_WHITELIST_JSON}}};


+ 1
- 1
bubble-server/src/main/resources/bubble/rule/social/block/site/MR.js.hbs View File

@@ -22,7 +22,7 @@ function {{JS_PREFIX}}_consider_block(comments, blocked_users) {
if (userElement.parentNode.querySelector('.bubble_block') === null) { if (userElement.parentNode.querySelector('.bubble_block') === null) {
const blockNode = document.createElement('span'); const blockNode = document.createElement('span');
blockNode.className = "bubble_block"; blockNode.className = "bubble_block";
blockNode.innerHTML = ' [<b><a href="#" onclick="_bubble_block_user(\'' + author.replace("'", "\\\'") + '\'); return false;">X</a></b>]&nbsp;&nbsp;';
blockNode.innerHTML = ' [<b><a href="#" onclick="{{JS_PREFIX}}_bubble_block_user(\'' + author.replace("'", "\\\'") + '\'); return false;">X</a></b>]&nbsp;&nbsp;';
console.log('inserting block control...'); console.log('inserting block control...');
userElement.parentNode.insertBefore(blockNode, userElement); userElement.parentNode.insertBefore(blockNode, userElement);
} }


+ 1
- 1
bubble-server/src/main/resources/models/apps/user_block/mr/bubbleApp_userBlock_mr_matchers.json View File

@@ -6,7 +6,7 @@
"site": "MarginalRevolution", "site": "MarginalRevolution",
"template": true, "template": true,
"fqdn": "marginalrevolution.com", "fqdn": "marginalrevolution.com",
"urlRegex": "marginalrevolution/20\\d{2}/\\d{2}/\\w+",
"urlRegex": "(/marginalrevolution)?/20\\d{2}/\\d{2}/\\w+",
"rule": "mr_user_blocker" "rule": "mr_user_blocker"
}, { }, {
"name": "MRTestMatcher", "name": "MRTestMatcher",


Loading…
Cancel
Save