Beispiel #1
0
 def _load_private_key(self):
     """Load (and generate if necessary) the Tor public and private keys"""
     log_msg("Loading private key...", 3)
     try:
         torKey = os.path.join(Globals.USER_DATA_DIR, "tor_data", "keys",
                               "secret_id_key")
         if not Files.file_exists(torKey):
             #have to create it ourselves.  First make the folders if necessary:
             keyFolder = os.path.join(Globals.USER_DATA_DIR, "tor_data",
                                      "keys")
             if not Files.file_exists(keyFolder):
                 os.makedirs(keyFolder)
             #then generate the key
             Globals.PRIVATE_KEY = PrivateKey.PrivateKey(1024)
             #and save it in the appropriate format
             if not Globals.PRIVATE_KEY.key.save_key(torKey, cipher=None):
                 raise Exception("Failed to save key as PEM!")
         else:
             Globals.PRIVATE_KEY = PrivateKey.PrivateKey(torKey)
         Globals.PUBLIC_KEY = Globals.PRIVATE_KEY.publickey()
         Globals.FINGERPRINT = TorUtils.fingerprint(Globals.PRIVATE_KEY.n,
                                                    Globals.PRIVATE_KEY.e)
         log_msg("Globals.FINGERPRINT = %s" % (Globals.FINGERPRINT), 3)
     except Exception, error:
         log_ex(error, "Failed while loading private key data")
Beispiel #2
0
 def new_desc_event(self, event):
   """Called when Tor learns a new server descriptor if listenting to
      NEWDESC events.
   @param event: the event structure from the Tor controller
   @type  event:  NewDescEvent
   """
   self.log_event(event, "NEW_DESC")
   for fullName in event.idlist:
     hexId = TorUtils.get_hex_id(fullName)
     self.torApp.load_relay(hexId)
Beispiel #3
0
 def new_desc_event(self, event):
     """Called when Tor learns a new server descriptor if listenting to
    NEWDESC events.
 @param event: the event structure from the Tor controller
 @type  event:  NewDescEvent
 """
     self.log_event(event, "NEW_DESC")
     for fullName in event.idlist:
         hexId = TorUtils.get_hex_id(fullName)
         self.torApp.load_relay(hexId)
Beispiel #4
0
 def does_relay_belong_to_account(self):
   """can we verify the signature on the hexid?
   basically, can we prove that the relay and no one else owns that hexid
   a hexid is derived from the relays public key, so they should be able to sign their id proving ownership
   sets: self.hexId
   @return: None"""
   thumb = TorUtils.fingerprint(self.n)
   key = PublicKey.PublicKey(self.n, 65537L)
   if not key.verify(thumb, self.hexIdSig):
     raise Exception("fingerprint doesn't match")
   self.hexId = thumb
   self.update_db()
Beispiel #5
0
 def or_conn_status_event(self, event):
     """Called when an OR connection's status changes if listening to
    ORCONNSTATUS events.
 @param event: the event structure from the Tor controller
 @type  event:  ORConnEvent"""
     self.log_event(event, "OR_CONN")
     #is this an IP address or a relay?
     vals = event.endpoint.split(":")
     if len(vals) == 2 and isIPAddress(vals[0]):
         #TODO:  handle these events, maybe look up the relay by IP/Port?
         pass
     #better be a hexId:
     else:
         hexId = TorUtils.get_hex_id(event.endpoint)
         #do we know about that router?
         r = self.torApp.get_relay(hexId)
         if r:
             r.on_or_event(event)
Beispiel #6
0
 def or_conn_status_event(self, event):
   """Called when an OR connection's status changes if listening to
      ORCONNSTATUS events.
   @param event: the event structure from the Tor controller
   @type  event:  ORConnEvent"""
   self.log_event(event, "OR_CONN")
   #is this an IP address or a relay?
   vals = event.endpoint.split(":")
   if len(vals) == 2 and isIPAddress(vals[0]):
     #TODO:  handle these events, maybe look up the relay by IP/Port?
     pass
   #better be a hexId:
   else:
     hexId = TorUtils.get_hex_id(event.endpoint)
     #do we know about that router?
     r = self.torApp.get_relay(hexId)
     if r:
       r.on_or_event(event)
Beispiel #7
0
 def _load_private_key(self):
   """Load (and generate if necessary) the Tor public and private keys"""
   log_msg("Loading private key...", 3)
   try:
     torKey = os.path.join(Globals.USER_DATA_DIR, "tor_data", "keys", "secret_id_key")
     if not Files.file_exists(torKey):
       #have to create it ourselves.  First make the folders if necessary:
       keyFolder = os.path.join(Globals.USER_DATA_DIR, "tor_data", "keys")
       if not Files.file_exists(keyFolder):
         os.makedirs(keyFolder)
       #then generate the key
       Globals.PRIVATE_KEY = PrivateKey.PrivateKey(1024)
       #and save it in the appropriate format
       if not Globals.PRIVATE_KEY.key.save_key(torKey, cipher=None):
         raise Exception("Failed to save key as PEM!")
     else:
       Globals.PRIVATE_KEY = PrivateKey.PrivateKey(torKey)
     Globals.PUBLIC_KEY = Globals.PRIVATE_KEY.publickey()
     Globals.FINGERPRINT = TorUtils.fingerprint(Globals.PRIVATE_KEY.n, Globals.PRIVATE_KEY.e)
     log_msg("Globals.FINGERPRINT = %s" % (Globals.FINGERPRINT), 3)
   except Exception, error:
     log_ex(error, "Failed while loading private key data")
Beispiel #8
0
 def __init__(self, event, app, id, finalPath=None):
   """Create a new Circuit based on an event from the Tor control interface.
   @param event:  The TorCtrl event
   @param app:  The application that this circuit belongs to.
   @param id:  The Circuit id (will be referenced by future TorCtl events)
   @param finalPath:  The sequence of relays that the circuit will go through when finished being built
   NOTE:  internal Circuits might not have been initialized starting from the "LAUNCHED"
   state because they may have been started before the controller.  Thus, no
   logic about state/status changes should depend on something having happened
   in response to a previous event, because that event may not have ever
   happened."""
   #call parent constructor:
   self.__class__.__bases__[0].__init__(self)
   #: the application that owns this circuit:
   self.app = app
   #: a list of all tor circuit status events that happened for this circuit
   self.events = []
   #: this is the current path (routers that have been successfully extended to)
   self.currentPath = []
   #: this is the path that this circuit will hopefully extend to.  Not necessarily defined unless isBitBlinderCircuit is True
   #: (note that this is NOT the routers that have already been extended to)
   self.finalPath = None
   #: whether the stream is already FAILED/CLOSED
   self.done = False
   #: whether to send payments for this circuit or not:
   self.sendPayments = True
   #: the way to pay to for our traffic (sort of weird, this will eventually be part of the circuit itself)
   self.parClient = None
   #: whether we're ready for refill_payments calls or not (need to get our global circ id first):
   self.readyForPayments = False
   #: how many relay data cells we've payed for:
   self.payedReadBytes = 0
   self.payedWriteBytes = 0
   #: how many circuit tokens there were at the last update (used to calculate bandwidth)
   self.lastPayedReads = 0
   self.lastPayedWrites = 0
   #: set our id:
   self.id = id
   #: whether this circuit successfully made it to BUILT status or not:
   self.succeeded = None
   #This indicates that the Circuit was not created by us:
   if event:
     #the circuit event handler will not be called for this first event, so
     #do everything here in the constructor:
     self.events.append(event)
     #indicates that this was NOT created by us:
     self.isBitBlinderCircuit = False
     #: current status of the circuit
     self.status = event.status
     self.reason = event.reason
     self.remoteReason = event.remote_reason
     #set the current path, the representation of the currently EXTENDED path
     #right now:
     for fullRouterName in event.path:
       hexId = TorUtils.get_hex_id(fullRouterName)
       r = self.app.torApp.get_relay(hexId)
       if r:
         self.currentPath.append(r)
       else:
         log_msg("circ init event has bad router name:  %s"%(hexId), 0)
     #set the final path, the path that attached streams would (have) use(d):
     if self.status in ("CLOSED", "FAILED", "BUILT"):
       self.finalPath = []
       for fullRouterName in event.path:
         hexId = TorUtils.get_hex_id(fullRouterName)
         self.finalPath.append(self.app.torApp.get_relay(hexId))
       #also pretend that the stream ended now
       #NOTE:  in this way, endedAt and createdAt might be the same
       #so be careful not to subtract and divide without checking for zero
       if self.status in ("CLOSED", "FAILED"):
         self.endedAt = time.time()
         self.done = True
   #in this case, we are the ones who launched the circuit
   else:
     if not finalPath:
       raise Exception("Must provide a path if you dont provide an event!")
     self.finalPath = copy.copy(finalPath)
     self.isBitBlinderCircuit = True
     self.status = "PRELAUNCH"
     self.reason = None
     self.remoteReason = None
   #: any streams waiting for this Circuit to gain a "BUILT" status?
   self.pendingStreams = set()
   #: all the streams actually using the Circuit
   self.streams = set()
   #: a pointer to the row in the display
   self.treeRow = None
   #: when the first stream was attached
   self.dirtiedAt = None
   #: inform the app that there has been a new circuit so it can update its list of circuits
   self.app.on_new_circuit(self)
   #: when the next payment event is scheduled for
   self.checkPaymentEvent = None
   #: whether some Tor control message is in progress that will tell us about the number of payment cells
   self.paymentCheckInProgress = False
   #: remote DHT requests that are waiting for the circuit to be built
   self.queuedDHTRequests = []
   #: the RemoteDHTRequest object for getting peers remotely via DHT
   self.dhtClient = None
   #: this will be set to True after ADDTOKENS has completed once.  Used to prevent premature PAR payments.
   self.initialTokensAdded = False
   #: will be triggered when the circuit is ready for streams
   self.builtDeferred = defer.Deferred()
Beispiel #9
0
  def circ_status_event(self, event):
    """Handle circuit_status events.  Note that previous events may not have
    occurred if isBitBlinderCircuit is False
    NOTE:  path and other events referring to routers now use the long names:
    hex(~|=)name
    @param event: a circuit status event that just arrived over the Tor control connection
    @type  event:  Event"""
    #update data from event:
    self.events.append(event)
    self.status = event.status
    self.reason = event.reason
    self.remoteReason = event.remote_reason
    #this is the current path (routers that have been successfully extended to)
    self.currentPath = []
    for fullRouterName in event.path:
      hexId = TorUtils.get_hex_id(fullRouterName)
      r = self.app.torApp.get_relay(hexId)
      if r:
        self.currentPath.append(r)
      else:
        log_msg("circ status event has bad router name:  %s"%(hexId), 0)

    #circuit has just been created
    if event.status == "LAUNCHED":
      return
    
    #if circuit just got (effectively) closed (FAILED always goes to CLOSED)
    if event.status in ("CLOSED", "FAILED"):
      self.on_done(event.reason, event.remote_reason)
    
    #circuit has been close, no streams can be attached
    if event.status == "CLOSED":
      return
    
    #circuit failed
    if event.status == "FAILED":
      if not event.reason:
        event.reason = "None"
      if not event.remote_reason:
        event.remote_reason = "None"
      log_msg(str(self.id)+" failed: REASON="+event.reason+" REMOTE_REASON="+event.remote_reason, 3, "circuit")
      return
    
    #circuit was successfully extended to the next hop in the path
    if event.status == "EXTENDED":
      return
        
    #finished a new circuit.  now have to do par setup:
    if event.status == "BUILT":
      #do we have a final path defined yet?
      if not self.finalPath:
        self.finalPath = []
        for fullRouterName in event.path:
          hexId = TorUtils.get_hex_id(fullRouterName)
          self.finalPath.append(self.app.torApp.get_relay(hexId))
      if self.isBitBlinderCircuit and self.sendPayments:
        #make sure we dont try to attach to a closed circuit
        if not self.is_ready():
          raise Exception("Circuit %d is not ready for message test" % (self.id))
        self.status = "PAR_SETUP"
        #REFACTOR:  move all of the parClient stuff into its own separate class
        def error(failure):
          if not self.is_done():
            if Basic.exception_is_a(failure, [TorCtl.TorCtlClosed, TorCtl.ErrorReply]):
              log_msg("Failed to create PAR client, closing", 1, "circuit")
            else:
              log_ex(failure, "Unexpected failure while starting circuit")
            self.on_done()
        def response(result):
          self.readyForPayments = True
          self.parClient.send_setup_message()
        d = self.parClient.start()
        d.addCallback(response)
        d.addErrback(error)
      else:
        #for Tor and internal circuits that we dont make payments for yet
        self.on_par_ready()
      return
    raise Exception("UNHANDLED CIRCUIT STATUS:  " + event.status)
Beispiel #10
0
 def __init__(self, event, app, id, finalPath=None):
     """Create a new Circuit based on an event from the Tor control interface.
 @param event:  The TorCtrl event
 @param app:  The application that this circuit belongs to.
 @param id:  The Circuit id (will be referenced by future TorCtl events)
 @param finalPath:  The sequence of relays that the circuit will go through when finished being built
 NOTE:  internal Circuits might not have been initialized starting from the "LAUNCHED"
 state because they may have been started before the controller.  Thus, no
 logic about state/status changes should depend on something having happened
 in response to a previous event, because that event may not have ever
 happened."""
     #call parent constructor:
     self.__class__.__bases__[0].__init__(self)
     #: the application that owns this circuit:
     self.app = app
     #: a list of all tor circuit status events that happened for this circuit
     self.events = []
     #: this is the current path (routers that have been successfully extended to)
     self.currentPath = []
     #: this is the path that this circuit will hopefully extend to.  Not necessarily defined unless isBitBlinderCircuit is True
     #: (note that this is NOT the routers that have already been extended to)
     self.finalPath = None
     #: whether the stream is already FAILED/CLOSED
     self.done = False
     #: whether to send payments for this circuit or not:
     self.sendPayments = True
     #: the way to pay to for our traffic (sort of weird, this will eventually be part of the circuit itself)
     self.parClient = None
     #: whether we're ready for refill_payments calls or not (need to get our global circ id first):
     self.readyForPayments = False
     #: how many relay data cells we've payed for:
     self.payedReadBytes = 0
     self.payedWriteBytes = 0
     #: how many circuit tokens there were at the last update (used to calculate bandwidth)
     self.lastPayedReads = 0
     self.lastPayedWrites = 0
     #: set our id:
     self.id = id
     #: whether this circuit successfully made it to BUILT status or not:
     self.succeeded = None
     #This indicates that the Circuit was not created by us:
     if event:
         #the circuit event handler will not be called for this first event, so
         #do everything here in the constructor:
         self.events.append(event)
         #indicates that this was NOT created by us:
         self.isBitBlinderCircuit = False
         #: current status of the circuit
         self.status = event.status
         self.reason = event.reason
         self.remoteReason = event.remote_reason
         #set the current path, the representation of the currently EXTENDED path
         #right now:
         for fullRouterName in event.path:
             hexId = TorUtils.get_hex_id(fullRouterName)
             r = self.app.torApp.get_relay(hexId)
             if r:
                 self.currentPath.append(r)
             else:
                 log_msg(
                     "circ init event has bad router name:  %s" % (hexId),
                     0)
         #set the final path, the path that attached streams would (have) use(d):
         if self.status in ("CLOSED", "FAILED", "BUILT"):
             self.finalPath = []
             for fullRouterName in event.path:
                 hexId = TorUtils.get_hex_id(fullRouterName)
                 self.finalPath.append(self.app.torApp.get_relay(hexId))
             #also pretend that the stream ended now
             #NOTE:  in this way, endedAt and createdAt might be the same
             #so be careful not to subtract and divide without checking for zero
             if self.status in ("CLOSED", "FAILED"):
                 self.endedAt = time.time()
                 self.done = True
     #in this case, we are the ones who launched the circuit
     else:
         if not finalPath:
             raise Exception(
                 "Must provide a path if you dont provide an event!")
         self.finalPath = copy.copy(finalPath)
         self.isBitBlinderCircuit = True
         self.status = "PRELAUNCH"
         self.reason = None
         self.remoteReason = None
     #: any streams waiting for this Circuit to gain a "BUILT" status?
     self.pendingStreams = set()
     #: all the streams actually using the Circuit
     self.streams = set()
     #: a pointer to the row in the display
     self.treeRow = None
     #: when the first stream was attached
     self.dirtiedAt = None
     #: inform the app that there has been a new circuit so it can update its list of circuits
     self.app.on_new_circuit(self)
     #: when the next payment event is scheduled for
     self.checkPaymentEvent = None
     #: whether some Tor control message is in progress that will tell us about the number of payment cells
     self.paymentCheckInProgress = False
     #: remote DHT requests that are waiting for the circuit to be built
     self.queuedDHTRequests = []
     #: the RemoteDHTRequest object for getting peers remotely via DHT
     self.dhtClient = None
     #: this will be set to True after ADDTOKENS has completed once.  Used to prevent premature PAR payments.
     self.initialTokensAdded = False
     #: will be triggered when the circuit is ready for streams
     self.builtDeferred = defer.Deferred()
Beispiel #11
0
    def circ_status_event(self, event):
        """Handle circuit_status events.  Note that previous events may not have
    occurred if isBitBlinderCircuit is False
    NOTE:  path and other events referring to routers now use the long names:
    hex(~|=)name
    @param event: a circuit status event that just arrived over the Tor control connection
    @type  event:  Event"""
        #update data from event:
        self.events.append(event)
        self.status = event.status
        self.reason = event.reason
        self.remoteReason = event.remote_reason
        #this is the current path (routers that have been successfully extended to)
        self.currentPath = []
        for fullRouterName in event.path:
            hexId = TorUtils.get_hex_id(fullRouterName)
            r = self.app.torApp.get_relay(hexId)
            if r:
                self.currentPath.append(r)
            else:
                log_msg("circ status event has bad router name:  %s" % (hexId),
                        0)

        #circuit has just been created
        if event.status == "LAUNCHED":
            return

        #if circuit just got (effectively) closed (FAILED always goes to CLOSED)
        if event.status in ("CLOSED", "FAILED"):
            self.on_done(event.reason, event.remote_reason)

        #circuit has been close, no streams can be attached
        if event.status == "CLOSED":
            return

        #circuit failed
        if event.status == "FAILED":
            if not event.reason:
                event.reason = "None"
            if not event.remote_reason:
                event.remote_reason = "None"
            log_msg(
                str(self.id) + " failed: REASON=" + event.reason +
                " REMOTE_REASON=" + event.remote_reason, 3, "circuit")
            return

        #circuit was successfully extended to the next hop in the path
        if event.status == "EXTENDED":
            return

        #finished a new circuit.  now have to do par setup:
        if event.status == "BUILT":
            #do we have a final path defined yet?
            if not self.finalPath:
                self.finalPath = []
                for fullRouterName in event.path:
                    hexId = TorUtils.get_hex_id(fullRouterName)
                    self.finalPath.append(self.app.torApp.get_relay(hexId))
            if self.isBitBlinderCircuit and self.sendPayments:
                #make sure we dont try to attach to a closed circuit
                if not self.is_ready():
                    raise Exception(
                        "Circuit %d is not ready for message test" % (self.id))
                self.status = "PAR_SETUP"

                #REFACTOR:  move all of the parClient stuff into its own separate class
                def error(failure):
                    if not self.is_done():
                        if Basic.exception_is_a(
                                failure,
                            [TorCtl.TorCtlClosed, TorCtl.ErrorReply]):
                            log_msg("Failed to create PAR client, closing", 1,
                                    "circuit")
                        else:
                            log_ex(
                                failure,
                                "Unexpected failure while starting circuit")
                        self.on_done()

                def response(result):
                    self.readyForPayments = True
                    self.parClient.send_setup_message()

                d = self.parClient.start()
                d.addCallback(response)
                d.addErrback(error)
            else:
                #for Tor and internal circuits that we dont make payments for yet
                self.on_par_ready()
            return
        raise Exception("UNHANDLED CIRCUIT STATUS:  " + event.status)
if __name__ == '__main__':
  #check if the script is already running:
  authFileName = "AUTH.PID"
  processes = []
  if os.path.exists(authFileName):
    pidFile = open(authFileName, "rb")
    data = pidFile.read()
    pidFile.close()
    data = data.split("\n")
    data.pop()
    for pid in data:
      System.kill_process(int(pid))
  pidFile = open(authFileName, "wb")
  #first generate the DirServer entries:
  dirServers = TorUtils.make_auth_lines(Conf.AUTH_SERVERS)
  #now make each of the torrc files and delete any leftover data:
  authConfs = []
  for i in range(1, len(Conf.AUTH_SERVERS)+1):
    data = dirServers + AUTH_TORRC_DATA
    conf = Conf.AUTH_SERVERS[i-1]
    found = False
    for arg in args:
      if arg == conf["address"]:
        found = True
        break
    if not found:
      continue
    dataDir = "tor_data%d" % (i)
    logFile = "%s/tor%d.out" % (LOG_FOLDER, i)
    data += "\nDataDirectory %s\n" % (dataDir)