[or-cvs] r17092: {updater} Add some in-code documentation, fix some dead code, add a li (in updater/trunk: . lib/thandy)

nickm at seul.org nickm at seul.org
Tue Oct 14 18:42:58 UTC 2008


Author: nickm
Date: 2008-10-14 14:42:57 -0400 (Tue, 14 Oct 2008)
New Revision: 17092

Added:
   updater/trunk/LICENSE
   updater/trunk/setup.py
Modified:
   updater/trunk/
   updater/trunk/Makefile
   updater/trunk/lib/thandy/ClientCLI.py
   updater/trunk/lib/thandy/ServerCLI.py
   updater/trunk/lib/thandy/SignerCLI.py
   updater/trunk/lib/thandy/__init__.py
   updater/trunk/lib/thandy/checkJson.py
   updater/trunk/lib/thandy/download.py
   updater/trunk/lib/thandy/formats.py
   updater/trunk/lib/thandy/keys.py
   updater/trunk/lib/thandy/master_keys.py
   updater/trunk/lib/thandy/repository.py
   updater/trunk/lib/thandy/tests.py
   updater/trunk/lib/thandy/util.py
Log:
Add some in-code documentation, fix some dead code, add a license, add a working distutils script.


Property changes on: updater/trunk
___________________________________________________________________
Name: svn:ignore
   + bin
build


Added: updater/trunk/LICENSE
===================================================================
--- updater/trunk/LICENSE	                        (rev 0)
+++ updater/trunk/LICENSE	2008-10-14 18:42:57 UTC (rev 17092)
@@ -0,0 +1,40 @@
+                 This file contains the license for Thandy,
+   a free software project to securely fetch and install software updates.
+
+             If you got this file as a part of a larger bundle,
+        there may be other license terms that you should be aware of.
+
+
+===============================================================================
+Thandy is distributed under this license:
+
+Copyright (c) 2008, The Tor Project, Inc.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+
+    * Neither the names of the copyright owners nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+===============================================================================

Modified: updater/trunk/Makefile
===================================================================
--- updater/trunk/Makefile	2008-10-14 17:05:52 UTC (rev 17091)
+++ updater/trunk/Makefile	2008-10-14 18:42:57 UTC (rev 17092)
@@ -1,6 +1,9 @@
 
-export PYTHONPATH=./lib
+all:
+	python setup.py build
 
 test:
-	#python -m sexp.tests
-	python -m thandy.tests
+	export PYTHONPATH=./lib && python -m thandy.tests
+
+install:
+	python setup.py install
\ No newline at end of file

Modified: updater/trunk/lib/thandy/ClientCLI.py
===================================================================
--- updater/trunk/lib/thandy/ClientCLI.py	2008-10-14 17:05:52 UTC (rev 17091)
+++ updater/trunk/lib/thandy/ClientCLI.py	2008-10-14 18:42:57 UTC (rev 17092)
@@ -1,3 +1,4 @@
+# Copyright 2008 The Tor Project, Inc.  See LICENSE for licensing information.
 
 import os
 import sys

Modified: updater/trunk/lib/thandy/ServerCLI.py
===================================================================
--- updater/trunk/lib/thandy/ServerCLI.py	2008-10-14 17:05:52 UTC (rev 17091)
+++ updater/trunk/lib/thandy/ServerCLI.py	2008-10-14 18:42:57 UTC (rev 17092)
@@ -1,3 +1,4 @@
+# Copyright 2008 The Tor Project, Inc.  See LICENSE for licensing information.
 
 import os
 import sys

Modified: updater/trunk/lib/thandy/SignerCLI.py
===================================================================
--- updater/trunk/lib/thandy/SignerCLI.py	2008-10-14 17:05:52 UTC (rev 17091)
+++ updater/trunk/lib/thandy/SignerCLI.py	2008-10-14 18:42:57 UTC (rev 17092)
@@ -1,3 +1,4 @@
+# Copyright 2008 The Tor Project, Inc.  See LICENSE for licensing information.
 
 import os
 import getopt

Modified: updater/trunk/lib/thandy/__init__.py
===================================================================
--- updater/trunk/lib/thandy/__init__.py	2008-10-14 17:05:52 UTC (rev 17091)
+++ updater/trunk/lib/thandy/__init__.py	2008-10-14 18:42:57 UTC (rev 17092)
@@ -1,3 +1,4 @@
+# Copyright 2008 The Tor Project, Inc.  See LICENSE for licensing information.
 
 __all__ = [ 'formats' ]
 

Modified: updater/trunk/lib/thandy/checkJson.py
===================================================================
--- updater/trunk/lib/thandy/checkJson.py	2008-10-14 17:05:52 UTC (rev 17091)
+++ updater/trunk/lib/thandy/checkJson.py	2008-10-14 18:42:57 UTC (rev 17092)
@@ -1,3 +1,4 @@
+# Copyright 2008 The Tor Project, Inc.  See LICENSE for licensing information.
 
 import re
 import sys

Modified: updater/trunk/lib/thandy/download.py
===================================================================
--- updater/trunk/lib/thandy/download.py	2008-10-14 17:05:52 UTC (rev 17091)
+++ updater/trunk/lib/thandy/download.py	2008-10-14 18:42:57 UTC (rev 17092)
@@ -1,5 +1,5 @@
+# Copyright 2008 The Tor Project, Inc.  See LICENSE for licensing information.
 
-
 import urllib2
 import httplib
 import random

Modified: updater/trunk/lib/thandy/formats.py
===================================================================
--- updater/trunk/lib/thandy/formats.py	2008-10-14 17:05:52 UTC (rev 17091)
+++ updater/trunk/lib/thandy/formats.py	2008-10-14 18:42:57 UTC (rev 17092)
@@ -1,3 +1,4 @@
+# Copyright 2008 The Tor Project, Inc.  See LICENSE for licensing information.
 
 import simplejson
 import time

Modified: updater/trunk/lib/thandy/keys.py
===================================================================
--- updater/trunk/lib/thandy/keys.py	2008-10-14 17:05:52 UTC (rev 17091)
+++ updater/trunk/lib/thandy/keys.py	2008-10-14 18:42:57 UTC (rev 17092)
@@ -1,3 +1,4 @@
+# Copyright 2008 The Tor Project, Inc.  See LICENSE for licensing information.
 
 # These require PyCrypto.
 import Crypto.PublicKey.RSA
@@ -17,9 +18,8 @@
 import thandy.util
 
 class PublicKey:
+    """Abstract base class for public keys."""
     def __init__(self):
-        # Confusingly, these roles are the ones used for a private key to
-        # remember what we're willing to do with it.
         self._roles = []
     def format(self):
         raise NotImplemented()
@@ -32,13 +32,25 @@
     def getKeyID(self):
         raise NotImplemented()
     def getRoles(self):
+        """Remove a list of all roles supported by this key.  A role is
+           from this key.  A role is a doctype,pathPattern tuple.
+        """
         return self._roles
     def addRole(self, role, path):
+        """Add a role to the list of roles supported by this key.
+           A role is a permission to sign a given kind of document
+           (one of thandy.format.ALL_ROLES) at a given set of relative
+           paths.
+        """
         assert role in thandy.formats.ALL_ROLES
         self._roles.append((role, path))
     def clearRoles(self):
+        """Remove all roles from this key."""
         del self._roles[:]
     def hasRole(self, role, path):
+        """Return true iff this key has a role that allows it to sign
+           a document of type 'role' at location in the repository 'path'.
+        """
         for r, p in self._roles:
             if r == role and thandy.formats.rolePathMatches(p, path):
                 return True
@@ -57,6 +69,7 @@
         return binascii.a2b_hex(h)
 elif hex(1L).upper() == "0X1":
     def intToBinary(number):
+        "Variant for future versions of pythons that don't append 'L'."
         h = hex(long(number))
         h = h[2:]
         if len(h)%2:
@@ -73,9 +86,11 @@
    return long(binascii.b2a_hex(binary), 16)
 
 def intToBase64(number):
+    """Convert an int or long to a big-endian base64-encoded value."""
     return thandy.formats.formatBase64(intToBinary(number))
 
 def base64ToInt(number):
+    """Convert a big-endian base64-encoded value to a long."""
     return binaryToInt(thandy.formats.parseBase64(number))
 
 def _pkcs1_padding(m, size):
@@ -123,11 +138,14 @@
 
     @staticmethod
     def generate(bits=2048):
+        """Generate a new RSA key, with modulus length 'bits'."""
         key = Crypto.PublicKey.RSA.generate(bits=bits, randfunc=os.urandom)
         return RSAKey(key)
 
     @staticmethod
     def fromJSon(obj):
+        """Construct an RSA key from the output of the format() method.
+        """
         # obj must match RSAKEY_SCHEMA
 
         thandy.formats.RSAKEY_SCHEMA.checkMatch(obj)
@@ -150,9 +168,14 @@
         return result
 
     def isPrivateKey(self):
+        """Return true iff this key has private-key components"""
         return hasattr(self.key, 'd')
 
     def format(self, private=False, includeRoles=False):
+        """Returna a new object to represent this key in json format.
+           If 'private', include private-key data.  If 'includeRoles',
+           include role information.
+        """
         n = intToBase64(self.key.n)
         e = intToBase64(self.key.e)
         result = { '_keytype' : 'rsa',
@@ -168,25 +191,19 @@
         return result
 
     def getKeyID(self):
+        """Return the KeyID for this key.
+        """
         if self.keyid == None:
             d_obj = Crypto.Hash.SHA256.new()
             thandy.formats.getDigest(self.format(), d_obj)
             self.keyid = thandy.formats.formatHash(d_obj.digest())
         return self.keyid
 
-    def _digest(self, obj, method=None):
-        if method in (None, "sha256-pkcs1"):
-            d_obj = Crypto.Hash.SHA256.new()
-            thandy.formats.getDigest(obj, d_obj)
-            digest = d_obj.digest()
-            return ("sha256-pkcs1", digest)
-
-        raise UnknownMethod(method)
-
     def sign(self, obj=None, digest=None):
         assert _xor(obj == None, digest == None)
+        method = "sha256-pkcs1"
         if digest == None:
-            method, digest = self._digest(obj)
+            digest = thandy.formats.getDigest(obj)
         m = _pkcs1_padding(digest, (self.key.size()+1) // 8)
         sig = intToBase64(self.key.sign(m, "")[0])
         return (method, sig)
@@ -194,9 +211,9 @@
     def checkSignature(self, method, sig, obj=None, digest=None):
         assert _xor(obj == None, digest == None)
         if method != "sha256-pkcs1":
-            raise UnknownMethod("method")
+            raise UnknownMethod(method)
         if digest == None:
-            method, digest = self._digest(obj, method)
+            digest = thandy.formats.getDigest(obj)
         sig = base64ToInt(sig)
         m = _pkcs1_padding(digest, (self.key.size()+1) // 8)
         return bool(self.key.verify(m, (sig,)))
@@ -324,6 +341,7 @@
     return secret
 
 class KeyStore(thandy.formats.KeyDB):
+    """Helper to store private keys in an encrypted file."""
     def __init__(self, fname, encrypted=True):
         thandy.formats.KeyDB.__init__(self)
 

Modified: updater/trunk/lib/thandy/master_keys.py
===================================================================
--- updater/trunk/lib/thandy/master_keys.py	2008-10-14 17:05:52 UTC (rev 17091)
+++ updater/trunk/lib/thandy/master_keys.py	2008-10-14 18:42:57 UTC (rev 17092)
@@ -1,5 +1,5 @@
+# Copyright 2008 The Tor Project, Inc.  See LICENSE for licensing information.
 
-
 MASTER_KEYS = [
 
 ]

Modified: updater/trunk/lib/thandy/repository.py
===================================================================
--- updater/trunk/lib/thandy/repository.py	2008-10-14 17:05:52 UTC (rev 17091)
+++ updater/trunk/lib/thandy/repository.py	2008-10-14 18:42:57 UTC (rev 17092)
@@ -1,3 +1,4 @@
+# Copyright 2008 The Tor Project, Inc.  See LICENSE for licensing information.
 
 import thandy.formats
 import thandy.util

Modified: updater/trunk/lib/thandy/tests.py
===================================================================
--- updater/trunk/lib/thandy/tests.py	2008-10-14 17:05:52 UTC (rev 17091)
+++ updater/trunk/lib/thandy/tests.py	2008-10-14 18:42:57 UTC (rev 17092)
@@ -1,3 +1,4 @@
+# Copyright 2008 The Tor Project, Inc.  See LICENSE for licensing information.
 
 import unittest
 import doctest

Modified: updater/trunk/lib/thandy/util.py
===================================================================
--- updater/trunk/lib/thandy/util.py	2008-10-14 17:05:52 UTC (rev 17091)
+++ updater/trunk/lib/thandy/util.py	2008-10-14 18:42:57 UTC (rev 17092)
@@ -1,3 +1,4 @@
+# Copyright 2008 The Tor Project, Inc.  See LICENSE for licensing information.
 
 import os
 import sys

Added: updater/trunk/setup.py
===================================================================
--- updater/trunk/setup.py	                        (rev 0)
+++ updater/trunk/setup.py	2008-10-14 18:42:57 UTC (rev 17092)
@@ -0,0 +1,124 @@
+#!/usr/bin/python
+# Copyright 2008 The Tor Project.  See LICENSE for licensing information.
+# $Id: setup.py,v 1.103 2007-09-15 19:06:37 nickm Exp $
+
+import sys
+
+#
+#   Current Thandy version
+#
+VERSION = '0.0.1-alpha'
+# System: 0==alpha, 50==beta, 98=pre, 99==release candidate, 100==release
+VERSION_INFO = (0,0,1)
+
+for name in [ "simplejson", "Crypto" ]:
+    try:
+        __import__(name)
+    except ImportError:
+        print "Missing support for module %s"%name
+        sys.exit(1)
+
+import os, re, shutil, string, struct, sys
+
+os.umask(022)
+
+#======================================================================
+# Create startup scripts if we're installing.
+
+if not os.path.isdir("./bin"):
+    os.mkdir("./bin")
+
+SCRIPTS = []
+
+def makescripts(extrapath=None):
+    del SCRIPTS[:]
+    for script_suffix, modname in [ ("server", "ServerCLI"),
+                                    ("client", "ClientCLI"),
+                                    ("pk", "SignerCLI"), ]:
+        fname = os.path.join("./bin", "thandy-%s"%script_suffix)
+        if sys.platform == "win32":
+            fname += ".py"
+        f = open(fname, 'w')
+        f.write("#!/bin/sh\n")
+        if extrapath:
+            f.write('PYTHONPATH="$PYTHONPATH:%s"\n'%extrapath)
+            f.write('export PYTHONPATH\n')
+        f.write("%s -m thandy.%s $*\n" %(sys.executable, modname))
+        f.close()
+        SCRIPTS.append(fname)
+
+#======================================================================
+# Define a helper to let us run commands from the compiled code.
+def _haveCmd(cmdname):
+    for entry in os.environ.get("PATH", "").split(os.pathsep):
+        if os.path.exists(os.path.join(entry, cmdname)):
+            return 1
+    return 0
+
+def requirePythonDev(e=None):
+    if os.path.exists("/etc/debian_version"):
+        v = sys.version[:3]
+        print "Debian may expect you to install python%s-dev"%v
+    elif os.path.exists("/etc/redhat-release"):
+        print "Redhat may expect you to install python2-devel"
+    else:
+        print "You may be missing some 'python development' package for your"
+        print "distribution."
+
+    if e:
+        print "(Error was: %s)"%e
+
+    sys.exit(1)
+
+try:
+    from distutils.core import Command
+    from distutils.errors import DistutilsPlatformError
+    from distutils.sysconfig import get_makefile_filename
+except ImportError, e:
+    print "\nUh oh. You have Python installed, but I didn't find the distutils"
+    print "module, which is supposed to come with the standard library.\n"
+
+    requirePythonDev()
+
+try:
+    # This catches failures to install python2-dev on some redhats.
+    get_makefile_filename()
+except IOError:
+    print "\nUh oh. You have Python installed, but distutils can't find the"
+    print "Makefile it needs to build additional Python components.\n"
+
+    requirePythonDev()
+
+#======================================================================
+# Now, tell setup.py how to cope.
+import distutils.core, distutils.command.install
+from distutils.core import setup, Distribution
+
+class InstallCommand(distutils.command.install.install):
+    def run(self):
+        script_path = None
+        sys_path = map(os.path.normpath, sys.path)
+        sys_path = map(os.path.normcase, sys_path)
+        install_lib = os.path.normcase(os.path.normpath(self.install_lib))
+
+        if install_lib not in sys_path:
+            script_path = install_lib
+
+        makescripts(self.install_lib)
+
+        distutils.command.install.install.run(self)
+
+setup(name='Thandy',
+      version=VERSION,
+      license="3-clause BSD",
+      description=
+      "Thandy: Secure cross-platform update automation tool.",
+      author="Nick Mathewson",
+      author_email="nickm at freehaven.net",
+      url="http://www.torproject/org",
+      package_dir={ '' : 'lib' },
+      packages=['thandy'],
+      scripts=SCRIPTS,
+      cmdclass={'install': InstallCommand},
+)
+



More information about the tor-commits mailing list