addon-sdk/source/python-lib/cuddlefish/preflight.py

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rwxr-xr-x

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 # This Source Code Form is subject to the terms of the Mozilla Public
     2 # License, v. 2.0. If a copy of the MPL was not distributed with this
     3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
     5 import os, sys
     6 import base64
     7 import simplejson as json
     9 def create_jid():
    10     """Return 'jid1-XYZ', where 'XYZ' is a randomly-generated string. (in the
    11     previous jid0- series, the string securely identified a specific public
    12     key). To get a suitable add-on ID, append '@jetpack' to this string.
    13     """
    14     # per https://developer.mozilla.org/en/Install_Manifests#id all XPI id
    15     # values must either be in the form of a 128-bit GUID (crazy braces
    16     # and all) or in the form of an email address (crazy @ and all).
    17     # Firefox will refuse to install an add-on with an id that doesn't
    18     # match one of these forms. The actual regexp is at:
    19     # http://mxr.mozilla.org/mozilla-central/source/toolkit/mozapps/extensions/internal/XPIProvider.jsm#130
    20     # So the JID needs an @-suffix, and the only legal punctuation is
    21     # "-._". So we start with a base64 encoding, and replace the
    22     # punctuation (+/) with letters (AB), losing a few bits of integrity.
    24     # even better: windows has a maximum path length limitation of 256
    25     # characters:
    26     #  http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx
    27     # (unless all paths are prefixed with "\\?\", I kid you not). The
    28     # typical install will put add-on code in a directory like:
    29     # C:\Documents and Settings\<username>\Application Data\Mozilla\Firefox\Profiles\232353483.default\extensions\$JID\...
    30     # (which is 108 chars long without the $JID).
    31     # Then the unpacked XPI contains packaged resources like:
    32     #  resources/$JID-api-utils-lib/main.js   (35 chars plus the $JID)
    33     #
    34     # We create a random 80 bit string, base64 encode that (with
    35     # AB instead of +/ to be path-safe), then bundle it into
    36     # "jid1-XYZ@jetpack". This gives us 27 characters. The resulting
    37     # main.js will have a path length of 211 characters, leaving us 45
    38     # characters of margin.
    39     #
    40     # 80 bits is enough to generate one billion JIDs and still maintain lower
    41     # than a one-in-a-million chance of accidental collision. (1e9 JIDs is 30
    42     # bits, square for the "birthday-paradox" to get 60 bits, add 20 bits for
    43     # the one-in-a-million margin to get 80 bits)
    45     # if length were no issue, we'd prefer to use this:
    46     h = os.urandom(80/8)
    47     s = base64.b64encode(h, "AB").strip("=")
    48     jid = "jid1-" + s
    49     return jid
    51 def preflight_config(target_cfg, filename, stderr=sys.stderr):
    52     modified = False
    53     config = json.load(open(filename, 'r'))
    55     if "id" not in config:
    56         print >>stderr, ("No 'id' in package.json: creating a new ID for you.")
    57         jid = create_jid()
    58         config["id"] = jid
    59         modified = True
    61     if modified:
    62         i = 0
    63         backup = filename + ".backup"
    64         while os.path.exists(backup):
    65             if i > 1000:
    66                 raise ValueError("I'm having problems finding a good name"
    67                                  " for the backup file. Please move %s out"
    68                                  " of the way and try again."
    69                                  % (filename + ".backup"))
    70             backup = filename + ".backup-%d" % i
    71             i += 1
    72         os.rename(filename, backup)
    73         new_json = json.dumps(config, indent=4)
    74         open(filename, 'w').write(new_json+"\n")
    75         return False, True
    77     return True, False

mercurial