[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-talk] Implement JSONP interface for check.torproject.org



I have made a patch to check.torproject.org to expose a JSONP interface
that would allow people to have the user check client side if (s)he is
using Tor.

This would allow people to embed a badge on their website
(privacybadge.html) that congratulates the user of using Tor or warns
him of non Tor usage with a link to torproject.org.

I can imagine privacy advocates having this deployed on their websites
or systems that engourage users to connect to them anonymously.

Compared to what check.torproject.org does at the moment the risk does
not change, it is erogating exactly the same service, just making it
more useful and flexible.

Basically what it does is check if the ip doing the connection is
connected through Tor. The web service will reply with a JSON encoded
array that can be loaded from the user and display in the browser a nice
looking badge.

You can see how this works on the live demo hosted here:

http://hellais.github.com/torcheck/privacybadge.html

I still need to finish the styling of the badge to contain links to
torproject.org and generally make it cooler.

Also, the check.torproject repo should be moved to svn.

- Art.
Index: privacybadge.html
===================================================================
--- privacybadge.html	(revision 0)
+++ privacybadge.html	(revision 0)
@@ -0,0 +1,44 @@
+<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.min.js";></script>
+<script type="text/javascript">
+        $(document).ready(function() {
+            $("#PrivacyBox").ready(function() {
+                function anonymous(value) {
+                    var box = $('#PrivacyBox');
+                    if (value) {
+                        //box.children("#image").addClass("anonymous");
+                        box.children("#image").replaceWith('<img src="anonymous.png"/>');
+                        box.children("#status").replaceWith('<p id="status">Anonymous</p>');
+                    } else {
+                        //box.children("#image").addClass("notanonymous");
+                        box.children("#image").replaceWith('<img src="notanonymous.png"/>');
+
+                        box.children("#status").replaceWith('<p id="status">Not Anonymous</p>');
+                    }
+                }
+                if ( $.cookie('privacystatus') ){
+                    console.log("hehe");
+                    if ($.cookie('privacystatus') == "True") {
+                        anonymous(true);
+                    } else {
+                        anonymous(false);
+                    }
+                } else {
+                    $.getJSON('https://check.torproject.org/badge', function(data) {
+                        if (data.Tor) {
+                            anonymous(data.Tor);
+                            $.cookie('privacystatus', 'True', { expires: 1, path: '/' });
+                        } else {
+                            anonymous(data.Tor);
+                            $.cookie('privacystatus', 'False', { expires: 1, path: '/' });
+                        }
+                    });
+                }
+            });
+        });
+</script>
+<div id="PrivacyBox">
+    <div id="image"></div>
+    <p id="status"></p>
+</div>
+
+
Index: cgi-bin/JSONPCheck.py
===================================================================
--- cgi-bin/JSONPCheck.py	(revision 0)
+++ cgi-bin/JSONPCheck.py	(revision 0)
@@ -0,0 +1,149 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+"""
+ TorCheck.py
+
+ https://check.torproject.org - originally in perl, rewritten in python
+
+ By Jacob Appelbaum <jacob@xxxxxxxxxxxxx>
+ Written at ToorCon Seattle 2008 (Thanks for the great time h1kari!)
+ Thanks to Crispen for a power outlet :-)
+
+ Additional python suggestions from nickm
+
+ Best used with the Debian packages:
+    python-dns
+    libapache2-mod-python
+    locales-all
+
+"""
+
+__program__ = 'TorCheck.py'
+__version__ = '20100429.01'
+__url__ = 'https://svn.torproject.org/svn/check/'
+__author__ = 'Jacob Appelbaum <jacob@xxxxxxxxxxxxx>'
+__copyright__ = 'Copyright (c) 2008, Jacob Appelbaum'
+__license__ = 'See LICENSE for licensing information'
+
+try:
+    from future import antigravity
+except ImportError:
+    antigravity = None
+
+import cgi
+import DNS
+from DNS import DNSError
+# This is pydns and can be downloaded from http://pydns.sourceforge.net/
+# Or use the Debian package listed above
+import cgitb; cgitb.enable()
+import gettext
+import locale
+import os
+
+#os.environ['LOCPATH']='/usr/share/locale:/srv/check.torproject.org/trunk/i18n/locale'
+localedir ='/srv/check.torproject.org/trunk/i18n/locale'
+
+# We could also explictly query the remote EL server
+# This is not as good as using a cache for obvious reasons
+DNS.DiscoverNameServers()
+
+def isUsingTor(clientIp, ELPort):
+    # This is the exit node ip address
+    # This is where we want to dynamically recieve this from Apache
+    splitIp = clientIp.split('.')
+    splitIp.reverse()
+    ELExitNode = ".".join(splitIp)
+
+    # We'll attempt to reach this port on the Target host
+    # ELPort is now set by the caller
+
+    # We'll try to reach this host
+    ElTarget = "38.229.70.31"
+
+    # This is the ExitList DNS server we want to query
+    ELHost = "ip-port.exitlist.torproject.org"
+
+    # Prepare the question as an A record request
+    ELQuestion = ELExitNode + "." + ELPort + "." + ElTarget + "." + ELHost
+    request = DNS.DnsRequest(name=ELQuestion,qtype='A')
+
+    # Ask the question and load the data into our answer
+    try:
+      answer=request.req()
+    except DNSError:
+      return 2
+
+    # Parse the answer and decide if it's allowing exits
+    # 127.0.0.2 is an exit and NXDOMAIN is not
+    if answer.header['status'] == "NXDOMAIN":
+        # We're not exiting from a Tor exit
+        return 1
+    else:
+        if not answer.answers:
+            # We're getting unexpected data - fail closed
+            return 2
+        for a in answer.answers:
+            if a['data'] != "127.0.0.2":
+                return 2
+        # If we're here, we've had a positive exit answer
+        return 0
+
+
+def isUpToDate(queryString):
+    """
+    determine if TBB is aware of newer versions
+    """
+    if 'uptodate=1' in queryString.lower():
+        return True
+    if 'uptodate=0' in queryString.lower():
+        return False
+    # This will be true until Torbutton 1.4.4 is released
+    if 'small=1' in queryString.lower():
+        return False
+
+    # The default case; No update information to provide
+    return True
+
+def handler(req, environ, start_response):
+    # Make a DNS request to the EL and decide what to tell the user
+    UsingTor = isUsingTor(environ['REMOTE_ADDR'], "80")
+    # Try to hit a cornercase where the user can exit to 443 but not 80
+    if UsingTor != 0:
+        UsingTor = isUsingTor(environ['REMOTE_ADDR'], "443")
+
+    # figure out if the client passed uptodate=0 or uptodate=1
+    # defaults to 1 if uptodate was not present in the query string
+    UpToDate = isUpToDate(environ['QUERY_STRING'])
+
+    response_headers = [('Content-type', 'text/html; charset=utf-8')]
+    start_response('200 OK', response_headers)
+
+    data = cgi.FieldStorage()
+    callback = data.getvalue('callback')
+
+    if callback:
+        if UsingTor == 0:
+            req.write(callback + "({'Tor': True});")
+        # This is the case where we have an NXDOMAIN and they aren't using Tor
+        elif UsingTor == 1:
+            req.write(callback + "({'Tor': False});")
+        # This means we have some strange data response we don't understand
+        # It's better that we fail closed and let the user know everything went wrong
+        elif UsingTor == 2:
+            req.write(callback + "({'Tor': 'Error'});")
+
+    else:
+        req.write("No callback set")
+
+class FakeReq(list):
+    def write(self, str):
+        self.append(str)
+
+def application(environ, start_response):
+    req = FakeReq()
+    handler(req, environ, start_response)
+    return req
+
+# vim:set ts=4:
+# vim:set et:
+# vim:set shiftwidth=4:

Property changes on: cgi-bin/JSONPCheck.py
___________________________________________________________________
Added: svn:executable
   + *

_______________________________________________
tor-talk mailing list
tor-talk@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-talk