123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- #!/usr/bin/python
- #
- # Copyright 2011 Nick Mathewson, Michael Stone
- #
- # You may do anything with this work that copyright law would normally
- # restrict, so long as you retain the above notice(s) and this license
- # in all redistributed copies and derived works. There is no warranty.
- from __future__ import with_statement
- import os
- import templating
- import subprocess
- import sys
- import re
- import errno
- def mkdir_p(d):
- try:
- os.makedirs(d)
- except OSError, e:
- if e.errno == errno.EEXIST:
- return
- raise
- class Node:
- ########
- # Users are expected to call these:
- def __init__(self, parent=None, **kwargs):
- self._parent = parent
- self._fields = self._createEnviron(parent, kwargs)
- def getN(self, N):
- return [ Node(self) for i in xrange(N) ]
- def specialize(self, **kwargs):
- return Node(parent=self, **kwargs)
- #######
- # Users are NOT expected to call these:
- def _createTorrcFile(self, checkOnly=False):
- template = self._getTorrcTemplate()
- env = self._fields
- fn_out = templating.Template("${torrc_fname}").format(env)
- output = template.format(env)
- if checkOnly:
- return
- with open(fn_out, 'w') as f:
- f.write(output)
- def _getTorrcTemplate(self):
- env = self._fields
- template_path = env['torrc_template_path']
- t = "$${include:$torrc}"
- return templating.Template(t, includePath=template_path)
- def _getFreeVars(self):
- template = self._getTorrcTemplate()
- env = self._fields
- return template.freevars(env)
- def _createEnviron(self, parent, argdict):
- if parent:
- parentfields = parent._fields
- else:
- parentfields = self._getDefaultFields()
- return TorEnviron(parentfields, **argdict)
- def _getDefaultFields(self):
- return _BASE_FIELDS
- def _checkConfig(self, net):
- self._createTorrcFile(checkOnly=True)
- def _preConfig(self, net):
- self._makeDataDir()
- if self._fields['authority']:
- self._genAuthorityKey()
- if self._fields['relay']:
- self._genRouterKey()
- def _config(self, net):
- self._createTorrcFile()
- #self._createScripts()
- def _postConfig(self, net):
- #self.net.addNode(self)
- pass
- def _setnodenum(self, num):
- self._fields['nodenum'] = num
- def _makeDataDir(self):
- env = self._fields
- datadir = env['dir']
- mkdir_p(os.path.join(datadir, 'keys'))
- def _genAuthorityKey(self):
- env = self._fields
- datadir = env['dir']
- tor_gencert = env['tor_gencert']
- lifetime = env['auth_cert_lifetime']
- idfile = os.path.join(datadir,'keys',"authority_identity_key")
- skfile = os.path.join(datadir,'keys',"authority_signing_key")
- certfile = os.path.join(datadir,'keys',"authority_certificate")
- addr = "%s:%s" % (env['ip'], env['dirport'])
- passphrase = env['auth_passphrase']
- if all(os.path.exists(f) for f in [idfile, skfile, certfile]):
- return
- cmdline = [
- tor_gencert,
- '--create-identity-key',
- '--passphrase-fd', '0',
- '-i', idfile,
- '-s', skfile,
- '-c', certfile,
- '-m', str(lifetime),
- '-a', addr]
- print "Creating identity key %s for %s with %s"%(idfile,env['nick']," ".join(cmdline))
- p = subprocess.Popen(cmdline, stdin=subprocess.PIPE)
- p.communicate(passphrase+"\n")
- assert p.returncode == 0 #XXXX BAD!
- def _genRouterKey(self):
- env = self._fields
- datadir = env['dir']
- tor = env['tor']
- idfile = os.path.join(datadir,'keys',"identity_key")
- cmdline = [
- tor,
- "--quiet",
- "--list-fingerprint",
- "--orport", "1",
- "--dirserver",
- "xyzzy 127.0.0.1:1 ffffffffffffffffffffffffffffffffffffffff",
- "--datadirectory", datadir ]
- p = subprocess.Popen(cmdline, stdout=subprocess.PIPE)
- stdout, stderr = p.communicate()
- fingerprint = "".join(stdout.split()[1:])
- assert re.match(r'^[A-F0-9]{40}$', fingerprint)
- env['fingerprint'] = fingerprint
- def _getDirServerLine(self):
- env = self._fields
- if not env['authority']:
- return ""
- datadir = env['dir']
- certfile = os.path.join(datadir,'keys',"authority_certificate")
- v3id = None
- with open(certfile, 'r') as f:
- for line in f:
- if line.startswith("fingerprint"):
- v3id = line.split()[1].strip()
- break
- assert v3id is not None
- return "DirServer %s v3ident=%s orport=%s %s %s:%s %s\n" %(
- env['nick'], v3id, env['orport'], env['dirserver_flags'],
- env['ip'], env['dirport'], env['fingerprint'])
- DEFAULTS = {
- 'authority' : False,
- 'relay' : False,
- 'connlimit' : 60,
- 'net_base_dir' : 'net',
- 'tor' : 'tor',
- 'auth_cert_lifetime' : 12,
- 'ip' : '127.0.0.1',
- 'dirserver_flags' : 'no-v2',
- 'privnet_dir' : '.',
- 'torrc_fname' : '${dir}/torrc',
- 'orport_base' : 6000,
- 'dirport_base' : 7000,
- 'controlport_base' : 8000,
- 'socksport_base' : 9000,
- 'dirservers' : "Dirserver bleargh bad torrc file!"
- }
- class TorEnviron(templating.Environ):
- def __init__(self,parent=None,**kwargs):
- templating.Environ.__init__(self, parent=parent, **kwargs)
- def _get_orport(self, me):
- return me['orport_base']+me['nodenum']
- def _get_controlport(self, me):
- return me['controlport_base']+me['nodenum']
- def _get_socksport(self, me):
- return me['socksport_base']+me['nodenum']
- def _get_dirport(self, me):
- return me['dirport_base']+me['nodenum']
- def _get_dir(self, me):
- return os.path.abspath(os.path.join(me['net_base_dir'],
- "nodes",
- me['nick']))
- def _get_nick(self, me):
- return "%s-%02d"%(me['tag'], me['nodenum'])
- def _get_tor_gencert(self, me):
- return me['tor']+"-gencert"
- def _get_auth_passphrase(self, me):
- return self['nick'] # OMG TEH SECURE!
- def _get_torrc_template_path(self, me):
- return [ os.path.join(me['privnet_dir'], 'torrc_templates') ]
- class Network:
- def __init__(self,defaultEnviron):
- self._nodes = []
- self._dfltEnv = defaultEnviron
- self._nextnodenum = 0
- def addNode(self, n):
- n._setnodenum(self._nextnodenum)
- self._nextnodenum += 1
- self._nodes.append(n)
- def configure(self):
- network = self
- dirserverlines = []
- for n in self._nodes:
- n._checkConfig(network)
- for n in self._nodes:
- n._preConfig(network)
- dirserverlines.append(n._getDirServerLine())
- self._dfltEnv['dirservers'] = "".join(dirserverlines)
- for n in self._nodes:
- n._config(network)
- for n in self._nodes:
- n._postConfig(network)
- def ConfigureNodes(nodelist):
- network = _THE_NETWORK
- for n in nodelist:
- network.addNode(n)
- def runConfigFile(f):
- global _BASE_FIELDS
- global _THE_NETWORK
- _BASE_FIELDS = TorEnviron(templating.Environ(**DEFAULTS))
- _THE_NETWORK = Network(_BASE_FIELDS)
- _GLOBALS = dict(_BASE_FIELDS= _BASE_FIELDS,
- Node=Node,
- ConfigureNodes=ConfigureNodes,
- _THE_NETWORK=_THE_NETWORK)
- exec f in _GLOBALS
- network = _GLOBALS['_THE_NETWORK']
- network.configure()
- if __name__ == '__main__':
- f = open(sys.argv[1])
- runConfigFile(f)
|