Пример #1
0
        /// <summary>Parses web data and updates the revoked users hashtable if
        /// successful</summary>
        protected void UpdateRl(byte[] data)
        {
            // message is length (4) + date (8) + data (variable) + hash (~20)
            int length = data.Length;

            if (length < 12)
            {
                throw new Exception("No data?  Didn't get enough data...");
            }

            length = NumberSerializer.ReadInt(data, 0);
            Brunet.DateTime date = new Brunet.DateTime(NumberSerializer.ReadLong(data, 4));
            // warn the user that this is an old revocation list, maybe there is an attack
            if (date < Brunet.DateTime.UtcNow.AddHours(-24))
            {
                ProtocolLog.WriteIf(IpopLog.GroupVPN, "Revocation list is over 24 hours old");
            }

            // Weird, data length is longer than the data we got
            if (length > data.Length - 12)
            {
                throw new Exception("Missing data?  Didn't get enough data...");
            }

            // hash the data and verify the signature
            SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();

            byte[] hash      = sha1.ComputeHash(data, 4, length);
            byte[] signature = new byte[data.Length - 4 - length];
            Array.Copy(data, 4 + length, signature, 0, signature.Length);

            if (!_ca_cert.PublicKey.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA1"), signature))
            {
                throw new Exception("Invalid signature!");
            }

            // convert the data to an array list as it was sent to us
            MemBlock mem = MemBlock.Reference(data, 12, length - 8);

            ArrayList rl = AdrConverter.Deserialize(mem) as ArrayList;

            if (rl == null)
            {
                throw new Exception("Data wasn't a list...");
            }

            // convert it into a hashtable for O(1) look ups
            Hashtable ht = new Hashtable();

            foreach (string username in rl)
            {
                ht[username] = true;
            }

            Interlocked.Exchange(ref _revoked_users, ht);
        }
Пример #2
0
        /// <summary>Tasks that should be performed during startup until completion
        /// and repetitive tasks are added here.
        protected void CheckNode(object o, EventArgs ea)
        {
            lock (_sync) {
                if (_dhcp_config == null)
                {
                    GetDhcpConfig();
                    if (_dhcp_config == null)
                    {
                        return;
                    }
                }

                // The rest doesn't quite work right yet...
                Brunet.DateTime now = Brunet.DateTime.UtcNow;
                if ((now - _last_check_node).TotalSeconds < 30)
                {
                    return;
                }
                _last_check_node = now;
            }
            ThreadPool.QueueUserWorkItem(CheckNetwork);
        }
Пример #3
0
    /**
    <summary>This provides a mechanism for a node to get a lease by using the
    Dht.  This uses Dht.Create which provides an atomic operation on the Dht,
    where this node is the first to store a value at a specific key.  The idea
    being that, this node being the first to store the IP, all nodes doing a
    lookup for that IP Address would be directed to this node.</summary>
    <remarks>Working with the Dht is a little tricky as transient errors could
    be misrepresented as a failed Create.  It is that reason why there is a 
    Renew parameter. If that is set, the algorithm for obtaining an address
    is slightly changed with more weight on reobtaining the RequestedAddr.
    </remarks>
    <param name="RequestedAddr">Optional parameter if the node would like to
    request a specific address.</param>
    <param name="Renew">Is the RequestedAddr a renewal?</param>
    <param name="node_address">The Brunet.Address where the DhtIpopNode resides
    </param>
    <param name="para">Optional, position 0 should hold the hostname.</param>
    */
    public override byte[] RequestLease(byte[] RequestedAddr, bool Renew,
                                       string node_address, params object[] para) {
      int max_renew_attempts = 1;
      int renew_attempts = max_renew_attempts;
      int attempts = 2;

      if(Renew) {
        if(!ValidIP(RequestedAddr)) {
          throw new Exception("Invalid requested address: " +
              Utils.BytesToString(RequestedAddr, '.'));
        }
        MemBlock request_addr = MemBlock.Reference(RequestedAddr);
        renew_attempts = 2;
        attempts = 1;
        if(request_addr.Equals(_current_ip) && Brunet.DateTime.UtcNow < _current_quarter_lifetime) {
          return _current_ip;
        }
      } else if(RequestedAddr == null || !ValidIP(RequestedAddr)) {
        RequestedAddr = MemBlock.Reference(RandomIPAddress());
      }

      byte[] hostname = null;
      if(para.Length > 0 && para[0] is string) {
        string shostname = para[0] as string;
        if(!shostname.Equals(string.Empty)) {
          hostname = Encoding.UTF8.GetBytes(Config.Namespace + "." + shostname + "." + Dns.DomainName);
        }
      }

      byte[] multicast_key = null;
      if(_multicast) {
        multicast_key = Encoding.UTF8.GetBytes(Config.Namespace + ".multicast.ipop");
      }

      byte[] node_addr = Encoding.UTF8.GetBytes(node_address);
      bool res = false;

      while (attempts-- > 0) {
        string str_addr = Utils.BytesToString(RequestedAddr, '.');
        ProtocolLog.WriteIf(IpopLog.DhcpLog, "Attempting to allocate IP Address:" + str_addr);

        byte[] dhcp_key = Encoding.UTF8.GetBytes("dhcp:" + Config.Namespace + ":" + str_addr);
        byte[] ip_addr = Encoding.UTF8.GetBytes(str_addr);

        while(renew_attempts-- > 0) {
          try {
            res = _dht.Create(dhcp_key, node_addr, Config.LeaseTime);

            if(hostname != null) {
              _dht.Put(hostname, ip_addr, Config.LeaseTime);
            }

            if(_multicast) {
              _dht.Put(multicast_key, node_addr, Config.LeaseTime);
            }

//            _dht.Put(node_addr, dhcp_key, Config.LeaseTime);
          }
          catch(Exception e) {
            ProtocolLog.WriteIf(IpopLog.DhcpLog, "Unable to allocate: " + e.Message);
            res = false;
          }
        }
        if(res) {
          _current_ip = MemBlock.Reference(RequestedAddr);
          _current_quarter_lifetime = Brunet.DateTime.UtcNow.AddSeconds(Config.LeaseTime / 4.0); 
          break;
        }
        else {
          // Failure!  Guess a new IP address
          RequestedAddr = RandomIPAddress();
          renew_attempts = max_renew_attempts;
        }
      }

      if(!res) {
        throw new Exception("Unable to get an IP Address!");
      }

      return RequestedAddr;
    }
Пример #4
0
        /**
         * <summary>This provides a mechanism for a node to get a lease by using the
         * Dht.  This uses Dht.Create which provides an atomic operation on the Dht,
         * where this node is the first to store a value at a specific key.  The idea
         * being that, this node being the first to store the IP, all nodes doing a
         * lookup for that IP Address would be directed to this node.</summary>
         * <remarks>Working with the Dht is a little tricky as transient errors could
         * be misrepresented as a failed Create.  It is that reason why there is a
         * Renew parameter. If that is set, the algorithm for obtaining an address
         * is slightly changed with more weight on reobtaining the RequestedAddr.
         * </remarks>
         * <param name="RequestedAddr">Optional parameter if the node would like to
         * request a specific address.</param>
         * <param name="Renew">Is the RequestedAddr a renewal?</param>
         * <param name="node_address">The Brunet.Address where the DhtIpopNode resides
         * </param>
         * <param name="para">Optional, position 0 should hold the hostname.</param>
         */
        public override byte[] RequestLease(byte[] RequestedAddr, bool Renew,
                                            string node_address, params object[] para)
        {
            int max_renew_attempts = 1;
            int renew_attempts     = max_renew_attempts;
            int attempts           = 2;

            if (Renew)
            {
                if (!ValidIP(RequestedAddr))
                {
                    throw new Exception("Invalid requested address: " +
                                        Utils.BytesToString(RequestedAddr, '.'));
                }
                MemBlock request_addr = MemBlock.Reference(RequestedAddr);
                renew_attempts = 2;
                attempts       = 1;
                if (request_addr.Equals(_current_ip) && Brunet.DateTime.UtcNow < _current_quarter_lifetime)
                {
                    return(_current_ip);
                }
            }
            else if (RequestedAddr == null || !ValidIP(RequestedAddr))
            {
                RequestedAddr = MemBlock.Reference(RandomIPAddress());
            }

            byte[] hostname = null;
            if (para.Length > 0 && para[0] is string)
            {
                string shostname = para[0] as string;
                if (!shostname.Equals(string.Empty))
                {
                    hostname = Encoding.UTF8.GetBytes(Config.Namespace + "." + shostname + "." + Dns.DomainName);
                }
            }

            byte[] multicast_key = null;
            if (_multicast)
            {
                multicast_key = Encoding.UTF8.GetBytes(Config.Namespace + ".multicast.ipop");
            }

            byte[] node_addr = Encoding.UTF8.GetBytes(node_address);
            bool   res       = false;

            while (attempts-- > 0)
            {
                string str_addr = Utils.BytesToString(RequestedAddr, '.');
                ProtocolLog.WriteIf(IpopLog.DhcpLog, "Attempting to allocate IP Address:" + str_addr);

                byte[] dhcp_key = Encoding.UTF8.GetBytes("dhcp:" + Config.Namespace + ":" + str_addr);
                byte[] ip_addr  = Encoding.UTF8.GetBytes(str_addr);

                while (renew_attempts-- > 0)
                {
                    try {
                        res = _dht.Create(dhcp_key, node_addr, Config.LeaseTime);

                        if (hostname != null)
                        {
                            _dht.Put(hostname, ip_addr, Config.LeaseTime);
                        }

                        if (_multicast)
                        {
                            _dht.Put(multicast_key, node_addr, Config.LeaseTime);
                        }

//            _dht.Put(node_addr, dhcp_key, Config.LeaseTime);
                    }
                    catch (Exception e) {
                        ProtocolLog.WriteIf(IpopLog.DhcpLog, "Unable to allocate: " + e.Message);
                        res = false;
                    }
                }
                if (res)
                {
                    _current_ip = MemBlock.Reference(RequestedAddr);
                    _current_quarter_lifetime = Brunet.DateTime.UtcNow.AddSeconds(Config.LeaseTime / 4.0);
                    break;
                }
                else
                {
                    // Failure!  Guess a new IP address
                    RequestedAddr  = RandomIPAddress();
                    renew_attempts = max_renew_attempts;
                }
            }

            if (!res)
            {
                throw new Exception("Unable to get an IP Address!");
            }

            return(RequestedAddr);
        }
Пример #5
0
    /// <summary>Tasks that should be performed during startup until completion
    /// and repetitive tasks are added here.
    protected void CheckNode(object o, EventArgs ea) {
      lock(_sync) {
        if(_dhcp_config == null) {
          GetDhcpConfig();
          if(_dhcp_config == null) {
            return;
          }
        }

        // The rest doesn't quite work right yet...
        Brunet.DateTime now = Brunet.DateTime.UtcNow;
        if((now - _last_check_node).TotalSeconds < 30) {
          return;
        }
        _last_check_node = now;
      }
      ThreadPool.QueueUserWorkItem(CheckNetwork);
    }
Пример #6
0
    /// <summary>Creates an IpopNode given a NodeConfig and an IpopConfig.
    /// Also sets up the Information, Ethernet device, and subscribes
    /// to Brunet for IP Packets</summary>
    /// <param name="node_config">The path to a NodeConfig xml file</param>
    /// <param name="ipop_config">The path to a IpopConfig xml file</param>
    public IpopNode(NodeConfig node_config, IpopConfig ipop_config,
        DHCPConfig dhcp_config) : base(node_config)
    {
      PublicNode = CreateNode(node_config);
      PublicNode.Node.DisconnectOnOverload = false;
      if(PublicNode.PrivateNode == null) {
        AppNode = PublicNode;
      } else {
        AppNode = PublicNode.PrivateNode;
        AppNode.Node.DisconnectOnOverload = false;
      }

      _ondemand = new OnDemandConnectionOverlord(AppNode.Node);
      AppNode.Node.AddConnectionOverlord(_ondemand);
      _ipop_config = ipop_config;

      Ethernet = new Ethernet(_ipop_config.VirtualNetworkDevice);
      Ethernet.Subscribe(this, null);

      Info = new Information(AppNode.Node, "IpopNode", AppNode.SecurityOverlord);
      Info.UserData["IpopNamespace"] = _ipop_config.IpopNamespace;
      if(PublicNode == AppNode) {
        PublicInfo = Info;
      } else {
        PublicInfo = new Information(PublicNode.Node, "PrivateIpopNode",
            PublicNode.SecurityOverlord);
        PublicInfo.UserData["IpopNamespace"] = _ipop_config.IpopNamespace;
      }

      if(_ipop_config.EndToEndSecurity && AppNode.SymphonySecurityOverlord != null) {
        _secure_senders = true;
      } else {
        _secure_senders = false;
      }
      AppNode.Node.GetTypeSource(PType.Protocol.IP).Subscribe(this, null);

      _sync = new object();
      _lock = 0;

      _ether_to_ip = new Dictionary<MemBlock, MemBlock>();
      _ip_to_ether = new Dictionary<MemBlock, MemBlock>();

      _dhcp_server_port = _ipop_config.DHCPPort != 0 ? _ipop_config.DHCPPort : 67;
      _dhcp_client_port = _dhcp_server_port + 1;
      ProtocolLog.WriteIf(IpopLog.DhcpLog, String.Format(
          "Setting Dhcp Ports to: {0},{1}", _dhcp_server_port, _dhcp_client_port));
      _ether_to_dhcp_server = new Dictionary<MemBlock, DhcpServer>();
      _static_mapping = new Dictionary<MemBlock, SimpleTimer>();
      _dhcp_config = dhcp_config;
      if(_dhcp_config != null) {
        SetDns();
        SetTAAuth();
        _dhcp_server = GetDhcpServer();
      }
      _checked_out = new Hashtable();

      AppNode.Node.HeartBeatEvent += CheckNode;
      _last_check_node = Brunet.DateTime.UtcNow;

      AppNode.Node.Rpc.AddHandler("Ipop", this);
    }
    /// <summary>Parses web data and updates the revoked users hashtable if
    /// successful</summary>
    protected void UpdateRl(byte[] data)
    {
      // message is length (4) + date (8) + data (variable) + hash (~20)
      int length = data.Length;
      if(length < 12) {
        throw new Exception("No data?  Didn't get enough data...");
      }

      length = NumberSerializer.ReadInt(data, 0);
      Brunet.DateTime date = new Brunet.DateTime(NumberSerializer.ReadLong(data, 4));
      // warn the user that this is an old revocation list, maybe there is an attack
      if(date < Brunet.DateTime.UtcNow.AddHours(-24)) {
        ProtocolLog.WriteIf(IpopLog.GroupVPN, "Revocation list is over 24 hours old");
      }

      // Weird, data length is longer than the data we got
      if(length > data.Length - 12) {
        throw new Exception("Missing data?  Didn't get enough data...");
      }

      // hash the data and verify the signature
      SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
      byte[] hash = sha1.ComputeHash(data, 4, length);
      byte[] signature = new byte[data.Length - 4 - length];
      Array.Copy(data, 4 + length, signature, 0, signature.Length);

      if(!_ca_cert.PublicKey.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA1"), signature)) {
        throw new Exception("Invalid signature!");
      }

      // convert the data to an array list as it was sent to us
      MemBlock mem = MemBlock.Reference(data, 12, length - 8);

      ArrayList rl = AdrConverter.Deserialize(mem) as ArrayList;
      if(rl == null) {
        throw new Exception("Data wasn't a list...");
      }

      // convert it into a hashtable for O(1) look ups
      Hashtable ht = new Hashtable();
      foreach(string username in rl) {
        ht[username] = true;
      }

      Interlocked.Exchange(ref _revoked_users, ht);
    }
Пример #8
0
        /// <summary>Creates an IpopNode given a NodeConfig and an IpopConfig.
        /// Also sets up the Information, Ethernet device, and subscribes
        /// to Brunet for IP Packets</summary>
        /// <param name="node_config">The path to a NodeConfig xml file</param>
        /// <param name="ipop_config">The path to a IpopConfig xml file</param>
        public IpopNode(NodeConfig node_config, IpopConfig ipop_config,
                        DHCPConfig dhcp_config) : base(node_config)
        {
            PublicNode = CreateNode(node_config);
            PublicNode.Node.DisconnectOnOverload = false;
            if (PublicNode.PrivateNode == null)
            {
                AppNode = PublicNode;
            }
            else
            {
                AppNode = PublicNode.PrivateNode;
                AppNode.Node.DisconnectOnOverload = false;
            }

            _ondemand = new OnDemandConnectionOverlord(AppNode.Node);
            AppNode.Node.AddConnectionOverlord(_ondemand);
            _ipop_config = ipop_config;

            Ethernet = new Ethernet(_ipop_config.VirtualNetworkDevice);
            Ethernet.Subscribe(this, null);

            Info = new Information(AppNode.Node, "IpopNode", AppNode.SecurityOverlord);
            Info.UserData["IpopNamespace"] = _ipop_config.IpopNamespace;
            if (PublicNode == AppNode)
            {
                PublicInfo = Info;
            }
            else
            {
                PublicInfo = new Information(PublicNode.Node, "PrivateIpopNode",
                                             PublicNode.SecurityOverlord);
                PublicInfo.UserData["IpopNamespace"] = _ipop_config.IpopNamespace;
            }

            if (_ipop_config.EndToEndSecurity && AppNode.SymphonySecurityOverlord != null)
            {
                _secure_senders = true;
            }
            else
            {
                _secure_senders = false;
            }
            AppNode.Node.GetTypeSource(PType.Protocol.IP).Subscribe(this, null);

            _sync = new object();
            _lock = 0;

            _ether_to_ip = new Dictionary <MemBlock, MemBlock>();
            _ip_to_ether = new Dictionary <MemBlock, MemBlock>();

            _dhcp_server_port = _ipop_config.DHCPPort != 0 ? _ipop_config.DHCPPort : 67;
            _dhcp_client_port = _dhcp_server_port + 1;
            ProtocolLog.WriteIf(IpopLog.DhcpLog, String.Format(
                                    "Setting Dhcp Ports to: {0},{1}", _dhcp_server_port, _dhcp_client_port));
            _ether_to_dhcp_server = new Dictionary <MemBlock, DhcpServer>();
            _static_mapping       = new Dictionary <MemBlock, SimpleTimer>();
            _dhcp_config          = dhcp_config;
            if (_dhcp_config != null)
            {
                SetDns();
                SetTAAuth();
                _dhcp_server = GetDhcpServer();
            }
            _checked_out = new Hashtable();

            AppNode.Node.HeartBeatEvent += CheckNode;
            _last_check_node             = Brunet.DateTime.UtcNow;

            AppNode.Node.Rpc.AddHandler("Ipop", this);
        }