tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

beacon-store.py (2960B)


      1 """
      2 Event beacon store server.
      3 
      4 - When a request body is specified, stores the data in the body for the 'type'
      5  specified in the query parameters and serves a 200 response without body.
      6 - When a request body is not specified and the request is not served with an
      7  'expected_body' parameter, stores an empty body for the 'type' specified in
      8  the query parameters and serves a 200 response without body.
      9 - When a request body is not specified and the request is served with an
     10  'expected_body' parameter, serves a 200 response whose body contains the
     11  stored value from the automatic beacon. Since the data is stored using a hash
     12  of the data as the key, it uses the `expected_body` query parameter to know
     13  what key to look up. If the stored value doesn't exist, serves a 200 response
     14  with an empty body.
     15 """
     16 import uuid
     17 import hashlib
     18 
     19 NO_DATA_STRING = b"<No data>"
     20 NOT_SET_STRING = b"<Not set>"
     21 
     22 # The server stash requires a uuid to store data. Use a hash of the automatic
     23 # beacon data as the uuid to store and retrieve the data.
     24 def string_to_uuid(input):
     25    hash_value = hashlib.md5(str(input).encode("UTF-8")).hexdigest()
     26    return str(uuid.UUID(hex=hash_value))
     27 
     28 def main(request, response):
     29    stash = request.server.stash;
     30    event_type = request.GET.first(b"type", NO_DATA_STRING)
     31 
     32    # The stash is accessed concurrently by many clients. A lock is used to
     33    # avoid interleaved read/write from different clients.
     34    with stash.lock:
     35        # GET requests with an 'expected_body' parameter imply they were sent as
     36        # the request from nextBeacon().
     37        if request.method == "GET" and b"expected_body" in request.GET:
     38          expected_body = request.GET.first(b"expected_body", NO_DATA_STRING)
     39          data = stash.take(string_to_uuid(event_type + expected_body)) or NOT_SET_STRING
     40          return (200, [], data)
     41 
     42        # Requests with a body imply they were sent as a reporting beacon
     43        # (either through reportEvent() or through an automatic beacon).
     44        if request.method == "POST" and event_type:
     45            request_body = request.body or NO_DATA_STRING
     46            request_origin = request.headers.get("Origin") or NO_DATA_STRING
     47            request_referrer = request.headers.get("Referer") or NO_DATA_STRING
     48            stash.put(string_to_uuid(event_type + request_body),
     49                (request_origin + b"," + request_referrer))
     50            return (200, [], b"")
     51        # GET requests without an 'expected_body' parameter imply they were sent
     52        # as a destination URL reporting beacon.
     53        if request.method == "GET" and event_type:
     54            request_origin = request.headers.get("Origin") or NO_DATA_STRING
     55            request_referrer = request.headers.get("Referer") or NO_DATA_STRING
     56            stash.put(string_to_uuid(event_type + NO_DATA_STRING),
     57                (request_origin + b"," + request_referrer))
     58            return (200, [], b"")
     59 
     60        return (400, [], u"")