示例#1
0
        /**
         * <summary>Disk caching is unsupported at this time.</summary>
         */
        /* When we have a cache eviction, we must write it to disk, we take
         * each entry, convert it explicitly into a hashtable, and then use adr
         * to create a stream and write it to disk
         */
        public void CacheEviction(Object o, EventArgs args)
        {
            Brunet.Collections.Cache.EvictionArgs eargs = (Brunet.Collections.Cache.EvictionArgs)args;
            MemBlock key = (MemBlock)eargs.Key;

            if (Dht.DhtLog.Enabled)
            {
                ProtocolLog.Write(Dht.DhtLog, String.Format(
                                      "Evicted out of cache {0}, entries in dht {1}, entries in cache {2}",
                                      (new BigInteger(key)).ToString(16), Count, _data.Count));
            }
            if (eargs.Value != null && ((LinkedList <Entry>)eargs.Value).Count > 0)
            {
                LinkedList <Entry> data = (LinkedList <Entry>)eargs.Value;
                // AdrConverter doesn't support LinkedLists
                Entry[] entries = new Entry[data.Count];
                data.CopyTo(entries, 0);
                Hashtable[] ht_entries = new Hashtable[entries.Length];
                int         index      = 0;
                foreach (Entry entry in entries)
                {
                    ht_entries[index++] = (Hashtable)entry;
                }

                string dir_path, filename;
                string file_path = GeneratePath(key, out dir_path, out filename);
                if (!Directory.Exists(dir_path))
                {
                    Directory.CreateDirectory(dir_path);
                }
                using (FileStream fs = File.Open(file_path, FileMode.Create)) {
                    AdrConverter.Serialize(ht_entries, fs);
                }
            }
        }
        /// <summary>Parse a revocation message.</summary>
        public UserRevocationMessage(Certificate cacert, MemBlock data)
        {
            _data = data;

            int pos    = 0;
            int length = 0;

            Username = AdrConverter.Deserialize(data, pos, out length) as string;
            pos     += length;
            // Random number to reduce likelihood of malicious duplication of messages
            NumberSerializer.ReadInt(data, pos);
            pos += 4;
            // Verify that there is a date contained therein, perhaps we should verify the time
            new DateTime(NumberSerializer.ReadLong(data, pos));
            pos      += 8;
            Signature = new byte[data.Length - pos];
            data.Slice(pos).CopyTo(Signature, 0);

            // hash the data
            SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();

            Hash = sha1.ComputeHash(data, 0, data.Length - Signature.Length);

            if (!cacert.PublicKey.VerifyHash(Hash,
                                             CryptoConfig.MapNameToOID("SHA1"), Signature))
            {
                throw new Exception("Invalid UserRevocationMessage signature");
            }
        }
示例#3
0
        protected void SendControlPacket(EndPoint end, int remoteid, int localid,
                                         ControlCode c, object state)
        {
            using (MemoryStream ms = new MemoryStream()) {
                NumberSerializer.WriteInt((int)c, ms);
                if (c == ControlCode.EdgeDataAnnounce)
                {
                    UdpEdge e = (UdpEdge)_id_ht[localid];
                    if ((e != null) && (e.RemoteID == remoteid))
                    {
                        Hashtable t = new Hashtable();
                        t["RemoteTA"] = e.RemoteTA.ToString();
                        t["LocalTA"]  = e.LocalTA.ToString();
                        AdrConverter.Serialize(t, ms);
                    }
                    else
                    {
                        if (ProtocolLog.UdpEdge.Enabled)
                        {
                            ProtocolLog.Write(ProtocolLog.UdpEdge, String.Format(
                                                  "Problem sending EdgeData: EndPoint: {0}, remoteid: {1}, " +
                                                  "localid: {2}, Edge: {3}", end, remoteid, localid, e));
                        }
                    }
                }

                _send_queue.Enqueue(new UdpMessage(localid, ~remoteid, MemBlock.Reference(ms.ToArray()), end));
                if (ProtocolLog.UdpEdge.Enabled)
                {
                    ProtocolLog.Write(ProtocolLog.UdpEdge, String.Format(
                                          "Sending control {1} to: {0}", end, c));
                }
            }
        }
示例#4
0
        /**
         * Implements the IReplyHandler (also provides some light-weight statistics)
         */
        public bool HandleReply(ReqrepManager man, ReqrepManager.ReqrepType rt,
                                int mid, PType prot, MemBlock payload, ISender ret_path,
                                ReqrepManager.Statistics statistics, object state)
        {
            RpcRequestState rs = (RpcRequestState)state;
            //ISender target = rs.RpcTarget;
            Channel bq = rs.Results;

            if (bq != null)
            {
                object    data = AdrConverter.Deserialize(payload);
                RpcResult res  = new RpcResult(ret_path, data, statistics);
                //handle possible exception:
                try {
                    bq.Enqueue(res);
                    //Keep listening unless the queue is closed
                    return(!bq.Closed);
                }
                catch (System.InvalidOperationException) {
                    //The queue is closed, stop listening for more results:
                    return(false);
                }
            }
            else
            {
                //If they didn't even pass us a queue, I guess they didn't want to
                //listen too long
                return(false);
            }
        }
示例#5
0
 public byte[] Serialize(object o)
 {
     using (MemoryStream ms = new MemoryStream()) {
         AdrConverter.Serialize(o, ms);
         return(ms.ToArray());
     }
 }
        /// <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);
            DateTime date = new DateTime(NumberSerializer.ReadLong(data, 4));

            // warn the user that this is an old revocation list, maybe there is an attack
            if (date < 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);
        }
示例#7
0
        public CertificateMaker(byte[] RawData)
        {
            _unsigned_data = RawData;
            Hashtable ht = (Hashtable)AdrConverter.Deserialize(MemBlock.Reference(RawData));

            _subject = new DistinguishedName((string)ht["Country"],
                                             (string)ht["Organization"], (string)ht["OrganizationalUnit"],
                                             (string)ht["Name"], (string)ht["Email"]);
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();

            rsa.ImportCspBlob((byte[])ht["PublicKey"]);
            _public_key   = rsa;
            _node_address = (string)ht["NodeAddress"];
        }
示例#8
0
        /**
         * <summary>Disk caching is unsupported at this time.</summary>
         */
        /* When we have a cache miss, we should try to load the data from disk,
         * if we are successful, we should also delete that file from the disk
         */
        public void CacheMiss(Object o, EventArgs args)
        {
            Brunet.Collections.Cache.MissArgs margs = (Brunet.Collections.Cache.MissArgs)args;
            MemBlock key  = (MemBlock)margs.Key;
            string   path = GeneratePath(key);

            if (File.Exists(path))
            {
                using (FileStream fs = File.Open(path, FileMode.Open)) {
                    ArrayList ht_entries = (ArrayList)AdrConverter.Deserialize(fs);
                    Entry[]   entries    = new Entry[ht_entries.Count];
                    int       index      = 0;
                    foreach (Hashtable entry in ht_entries)
                    {
                        entries[index++] = (Entry)entry;
                    }
                    _data[key] = new LinkedList <Entry>(entries);
                }
                File.Delete(path);
            }
        }
        /// <summary>Create a new revocation message.</summary>
        public UserRevocationMessage(RSACryptoServiceProvider private_key, string username)
        {
            Username = username;
            int signature_length = private_key.KeySize / 8;

            byte[] data = null;

            using (MemoryStream ms = new MemoryStream()) {
                AdrConverter.Serialize(Username, ms);
                Random rand = new Random();
                NumberSerializer.WriteInt(rand.Next(), ms);
                NumberSerializer.WriteLong(DateTime.UtcNow.Ticks, ms);
                data        = new byte[ms.Length + signature_length];
                ms.Position = 0;
                ms.Read(data, 0, (int)ms.Length);
            }

            SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();

            Hash      = sha1.ComputeHash(data, 0, data.Length - signature_length);
            Signature = private_key.SignHash(Hash, CryptoConfig.MapNameToOID("SHA1"));
            Signature.CopyTo(data, data.Length - signature_length);
            _data = MemBlock.Reference(data);
        }
示例#10
0
        public void Test()
        {
            CertificateHandler ch = new CertificateHandler();

            ch.AddCACertificate(_ca_cert.X509);
            ch.AddCertificateVerification(this);

            ArrayList revoked_users = new ArrayList();

            revoked_users.Add("joker");
            revoked_users.Add("bad_guy");
            revoked_users.Add("adversary");
            revoked_users.Add("noobs");

            // create revocation list
            byte[] to_sign = null;
            using (MemoryStream ms = new MemoryStream()) {
                NumberSerializer.WriteLong(DateTime.UtcNow.Ticks, ms);
                AdrConverter.Serialize(revoked_users, ms); to_sign = ms.ToArray();
            }

            // sign revocation list
            SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();

            byte[] hash      = sha1.ComputeHash(to_sign);
            byte[] signature = _private_key.SignHash(hash, CryptoConfig.MapNameToOID("SHA1"));
            byte[] data      = new byte[4 + to_sign.Length + signature.Length];
            NumberSerializer.WriteInt(to_sign.Length, data, 0);
            to_sign.CopyTo(data, 4);
            signature.CopyTo(data, 4 + to_sign.Length);

            UpdateRl(data);

            X509Certificate likable_guy  = CreateCert("likable_guy");
            X509Certificate joker        = CreateCert("joker");
            X509Certificate bad_guy      = CreateCert("bad_guy");
            X509Certificate good_guy     = CreateCert("good_guy");
            X509Certificate adversary    = CreateCert("adversary");
            X509Certificate noobs        = CreateCert("noobs");
            X509Certificate friendly_guy = CreateCert("friendly_guy");

            Assert.IsTrue(ch.Verify(likable_guy, null, _remote_id), "Likable guy");
            bool success = false;

            try {
                success = ch.Verify(adversary, null, _remote_id);
            } catch { }
            Assert.AreEqual(success, false, "adversary");

            try {
                success = ch.Verify(joker, null, _remote_id);
            } catch { }
            Assert.AreEqual(success, false, "joker");

            Assert.IsTrue(ch.Verify(friendly_guy, null, _remote_id), "friendly guy");

            try {
                success = ch.Verify(noobs, null, _remote_id);
            } catch { }
            Assert.AreEqual(success, false, "noobs");

            try {
                success = ch.Verify(bad_guy, null, _remote_id);
            } catch { }
            Assert.AreEqual(success, false, "bad_guy");

            Assert.IsTrue(ch.Verify(good_guy, null, _remote_id), "good guy");
        }
示例#11
0
        /**
         * <summary>Retrieves data from the Dht.</summary>
         * <remarks>First old entries for the key are deleted from the dht, second a
         * look up is performed, and finally using the token a range of data is
         * selectively returned.</remarks>
         * <param name="key">The index used to look up.</summary>
         * <param name="token">Contains the data necessary to do follow up look ups
         * if all the data stored in a key is to big for MAX_BYTES.</param>
         * <returns>IList of hashtables containing the results.  Compatible with
         * DhtGetResult.</returns>
         */

        public IList Get(MemBlock key, byte[] token)
        {
            int seen_start_idx = 0;
            int seen_end_idx   = 0;

            if (token != null)
            {
                using (MemoryStream ms = new MemoryStream(token)) {
                    int[] bounds = (int[])AdrConverter.Deserialize(ms);
                    seen_start_idx = bounds[0];
                    seen_end_idx   = bounds[1];
                    seen_start_idx = seen_end_idx + 1;
                }
            }

            int consumed_bytes = 0;

            Entry[] data = null;

            lock (_sync ) {
                _data.DeleteExpired(key);
                LinkedList <Entry> ll_data = _data.GetEntries(key);

                // Keys exist!
                if (ll_data != null)
                {
                    data = new Entry[ll_data.Count];
                    ll_data.CopyTo(data, 0);
                }
            }

            ArrayList result = null;

            if (data != null)
            {
                result = new ArrayList();
                ArrayList values          = new ArrayList();
                int       remaining_items = 0;
                byte[]    next_token      = null;

                seen_end_idx = data.Length - 1;
                for (int i = seen_start_idx; i < data.Length; i++)
                {
                    Entry e = (Entry)data[i];
                    if (e.Value.Length + consumed_bytes <= MAX_BYTES)
                    {
                        int age = (int)(DateTime.UtcNow - e.CreateTime).TotalSeconds;
                        int ttl = (int)(e.EndTime - DateTime.UtcNow).TotalSeconds;
                        consumed_bytes += e.Value.Length;
                        Hashtable item = new Hashtable();
                        item["age"]   = age;
                        item["value"] = (byte[])e.Value;
                        item["ttl"]   = ttl;
                        values.Add(item);
                    }
                    else
                    {
                        seen_end_idx = i - 1;
                        break;
                    }
                }
                remaining_items = data.Length - (seen_end_idx + 1);

                //Token creation
                int[] new_bounds = new int[2];
                new_bounds[0] = seen_start_idx;
                new_bounds[1] = seen_end_idx;
                using (MemoryStream ms = new System.IO.MemoryStream()) {
                    AdrConverter.Serialize(new_bounds, ms);
                    next_token = ms.ToArray();
                }
                result.Add(values);
                result.Add(remaining_items);
                result.Add(next_token);
            }
            return(result);
        }
示例#12
0
        /**
         * This handles lightweight control messages that may be sent
         * by UDP
         */
        protected void HandleControlPacket(int remoteid, int n_localid,
                                           MemBlock buffer, object state)
        {
            int     local_id = ~n_localid;
            UdpEdge e        = _id_ht[local_id] as UdpEdge;

            if (e == null)
            {
                return;
            }

            if (e.RemoteID == 0)
            {
                try {
                    e.RemoteID = remoteid;
                } catch {
                    return;
                }
            }

            if (e.RemoteID != remoteid)
            {
                return;
            }

            try {
                ControlCode code = (ControlCode)NumberSerializer.ReadInt(buffer, 0);
                if (ProtocolLog.UdpEdge.Enabled)
                {
                    ProtocolLog.Write(ProtocolLog.UdpEdge, String.Format(
                                          "Got control {1} from: {0}", e, code));
                }
                if (code == ControlCode.EdgeClosed)
                {
                    //The edge has been closed on the other side
                    RequestClose(e);
                    CloseHandler(e, null);
                }
                else if (code == ControlCode.EdgeDataAnnounce)
                {
                    //our NAT mapping may have changed:
                    IDictionary info =
                        (IDictionary)AdrConverter.Deserialize(buffer.Slice(4));
                    string our_local_ta = (string)info["RemoteTA"]; //his remote is our local
                    if (our_local_ta != null)
                    {
                        //Update our list:
                        TransportAddress new_ta = TransportAddressFactory.CreateInstance(our_local_ta);
                        TransportAddress old_ta = e.PeerViewOfLocalTA;
                        if (!new_ta.Equals(old_ta))
                        {
                            if (ProtocolLog.UdpEdge.Enabled)
                            {
                                ProtocolLog.Write(ProtocolLog.UdpEdge, String.Format(
                                                      "Local NAT Mapping changed on Edge: {0}\n{1} => {2}",
                                                      e, old_ta, new_ta));
                            }
                            //Looks like matters have changed:
                            this.UpdateLocalTAs(e, new_ta);

                            /**
                             * @todo, maybe we should ping the other edges sharing this
                             * EndPoint, but we need to be careful not to do some O(E^2)
                             * operation, which could easily happen if each EdgeDataAnnounce
                             * triggered E packets to be sent
                             */
                        }
                    }
                }
                else if (code == ControlCode.Null)
                {
                    //Do nothing in this case
                }
            }
            catch (Exception x) {
                //This could happen if this is some control message we don't understand
                if (ProtocolLog.Exceptions.Enabled)
                {
                    ProtocolLog.Write(ProtocolLog.Exceptions, x.ToString());
                }
            }
        }
示例#13
0
        /**
         * When requests come in this handles it
         */
        public void HandleData(MemBlock payload, ISender ret_path, object state)
        {
            Exception exception = null;

#if RPC_DEBUG
            Console.Error.WriteLine("[RpcServer: {0}] Getting method invocation request at: {1}.",
                                    _rrman.Info, DateTime.Now);
#endif
            try {
                object data = AdrConverter.Deserialize(payload);
                IList  l    = data as IList;

                if (l == null)
                {
                    //We could not cast the request into a list... so sad:
                    throw new AdrException(-32600, "method call not a list");
                }

                string methname = (string)l[0];
#if RPC_DEBUG
                Console.Error.WriteLine("[RpcServer: {0}] Getting invocation request,  method: {1}",
                                        _rrman.Info, methname);
#endif

                /*
                 * Lookup this method name in our table.
                 * This uses a cache, so it should be fast
                 * after the first time
                 */
                IRpcHandler handler = null;
                string      mname   = null;
                lock ( _sync ) {
                    object[] info = (object[])_method_cache[methname];
                    if (info == null)
                    {
                        int dot_idx = methname.IndexOf('.');
                        if (dot_idx == -1)
                        {
                            throw new AdrException(-32601, "No Handler for method: " + methname);
                        }
                        string hname = methname.Substring(0, dot_idx);
                        //Skip the '.':
                        mname = methname.Substring(dot_idx + 1);

                        handler = (IRpcHandler)_method_handlers[hname];
                        if (handler == null)
                        {
                            //No handler for this.
                            throw new AdrException(-32601, "No Handler for method: " + methname);
                        }
                        info    = new object[2];
                        info[0] = handler;
                        info[1] = mname;
                        _method_cache[methname] = info;
                    }
                    else
                    {
                        handler = (IRpcHandler)info[0];
                        mname   = (string)info[1];
                    }
                }

                ArrayList pa = (ArrayList)l[1];
#if DAVID_ASYNC_INVOKE
                object[] odata = new object[4];
                odata[0] = handler;
                odata[1] = ret_path;
                odata[2] = mname;
                odata[3] = pa;
                _rpc_command.Enqueue(odata);
#else
                handler.HandleRpc(ret_path, mname, pa, ret_path);
#endif
            }
            catch (ArgumentException argx) {
                exception = new AdrException(-32602, argx);
            }
            catch (TargetParameterCountException argx) {
                exception = new AdrException(-32602, argx);
            }
            catch (Exception x) {
                exception = x;
            }
            if (exception != null)
            {
                //something failed even before invocation began
#if RPC_DEBUG
                Console.Error.WriteLine("[RpcServer: {0}] Something failed even before invocation began: {1}",
                                        _rrman.Info, exception);
#endif
                using (MemoryStream ms = new MemoryStream()) {
                    AdrConverter.Serialize(exception, ms);
                    ret_path.Send(new CopyList(PType.Protocol.Rpc, MemBlock.Reference(ms.ToArray())));
                }
            }
        }
示例#14
0
 public object Deserialize(Stream stream)
 {
     return(AdrConverter.Deserialize(stream));
 }
示例#15
0
 public void Serialize(object obj, Stream stream)
 {
     AdrConverter.Serialize(obj, stream);
 }
示例#16
0
 public object Deserialize(byte[] b)
 {
     return(AdrConverter.Deserialize(b));
 }