Beispiel #1
0
        /// <summary>
        /// Loads all methods from interfaces and assigns an identifier
        /// to each. These are later synchronized with the client.
        /// </summary>
        private ServiceInstance CreateMethodMap(int keyIndex, Type serviceType, object service)
        {
            var instance = new ServiceInstance()
            {
                KeyIndex              = keyIndex,
                InterfaceType         = serviceType,
                InterfaceMethods      = new ConcurrentDictionary <int, MethodInfo>(),
                MethodParametersByRef = new ConcurrentDictionary <int, bool[]>(),
                SingletonInstance     = service
            };

            var currentMethodIdent = 0;

            if (serviceType.IsInterface)
            {
                var methodInfos = serviceType.GetMethods();
                foreach (var mi in methodInfos)
                {
                    instance.InterfaceMethods.TryAdd(currentMethodIdent, mi);
                    var parameterInfos = mi.GetParameters();
                    var isByRef        = new bool[parameterInfos.Length];
                    for (int i = 0; i < isByRef.Length; i++)
                    {
                        isByRef[i] = parameterInfos[i].ParameterType.IsByRef;
                    }
                    instance.MethodParametersByRef.TryAdd(currentMethodIdent, isByRef);
                    currentMethodIdent++;
                }
            }

            var interfaces = serviceType.GetInterfaces();

            foreach (var interfaceType in interfaces)
            {
                var methodInfos = interfaceType.GetMethods();
                foreach (var mi in methodInfos)
                {
                    instance.InterfaceMethods.TryAdd(currentMethodIdent, mi);
                    var parameterInfos = mi.GetParameters();
                    var isByRef        = new bool[parameterInfos.Length];
                    for (int i = 0; i < isByRef.Length; i++)
                    {
                        isByRef[i] = parameterInfos[i].ParameterType.IsByRef;
                    }
                    instance.MethodParametersByRef.TryAdd(currentMethodIdent, isByRef);
                    currentMethodIdent++;
                }
            }


            //Create a list of sync infos from the dictionary
            var syncSyncInfos = new List <MethodSyncInfo>();

            foreach (var kvp in instance.InterfaceMethods)
            {
                var parameters     = kvp.Value.GetParameters();
                var parameterTypes = new string[parameters.Length];
                for (var i = 0; i < parameters.Length; i++)
                {
                    parameterTypes[i] = parameters[i].ParameterType.ToConfigName();
                }
                syncSyncInfos.Add(new MethodSyncInfo
                {
                    MethodIdent      = kvp.Key,
                    MethodName       = kvp.Value.Name,
                    MethodReturnType = kvp.Value.ReturnType.ToConfigName(),
                    ParameterTypes   = parameterTypes
                });
            }

            var serviceSyncInfo = new ServiceSyncInfo
            {
                ServiceKeyIndex      = keyIndex,
                CompressionThreshold = _compressionThreshold,
                UseCompression       = _useCompression,
                MethodInfos          = syncSyncInfos.ToArray()
            };

            instance.ServiceSyncInfo = serviceSyncInfo;
            return(instance);
        }
        /// <summary>
        /// This method asks the server for a list of identifiers paired with method
        /// names and -parameter types. This is used when invoking methods server side.
        /// </summary>
        protected override void SyncInterface(Type serviceType,
                                              string username = null, string password = null)
        {
            if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password))
            {
                var sw = Stopwatch.StartNew();
                _logger.Debug("Zk authentiation started for: {0}, {1}", username, password);
                //do zk protocol authentication
                var sr = new ZkProtocol();

                // Step 1. Client sends username and ephemeral hash of random number.
                var aRand            = sr.CryptRand();
                var aClientEphemeral = sr.GetClientEphemeralA(aRand);

                // send username and aClientEphemeral to server
                _binWriter.Write((int)MessageType.ZkInitiate);
                _binWriter.Write(username);
                _logger.Debug("username sent to server: {0}", username);

                _binWriter.Write(aClientEphemeral); //always 32 bytes
                _logger.Debug("ClientEphemeral (A) sent to server: {0}", Convert.ToBase64String(aClientEphemeral));

                // get response from server
                var userFound = _binReader.ReadBoolean();
                if (!userFound)
                {
                    _logger.Debug("User not found. InvalidCredentialException thrown.");
                    throw new InvalidCredentialException("authentication failed");
                }
                var salt = _binReader.ReadBytes(32);
                _logger.Debug("Salt received from server: {0}", Convert.ToBase64String(salt));
                var bServerEphemeral = _binReader.ReadBytes(32);
                _logger.Debug("ServerEphemeral (B) received from server: {0}", Convert.ToBase64String(bServerEphemeral));

                // Step 3. Client and server calculate random scramble of ephemeral hash values exchanged.
                var clientScramble = sr.CalculateRandomScramble(aClientEphemeral, bServerEphemeral);

                // Step 4. Client computes session key
                var clientSessionKey = sr.ClientComputeSessionKey(salt, username, password,
                                                                  aClientEphemeral, bServerEphemeral, clientScramble);

                // Step 6. Client creates hash of session key and sends to server. Server creates same key and verifies.
                var clientSessionHash = sr.ClientCreateSessionHash(username, salt, aClientEphemeral,
                                                                   bServerEphemeral, clientSessionKey);
                // send to server and server verifies
                _binWriter.Write((int)MessageType.ZkProof);
                _binWriter.Write(clientSessionHash); //always 32 bytes

                _logger.Debug("ClientSessionKey Hash sent to server: {0}", Convert.ToBase64String(clientSessionHash));

                // get response
                var serverVerified = _binReader.ReadBoolean();
                if (!serverVerified)
                {
                    _logger.Debug("Server verification failed. InvalidCredentialException thrown.");
                    throw new InvalidCredentialException("authentication failed");
                }
                var serverSessionHash       = _binReader.ReadBytes(32);
                var clientServerSessionHash = sr.ServerCreateSessionHash(aClientEphemeral,
                                                                         clientSessionHash, clientSessionKey);
                if (!serverSessionHash.IsEqualTo(clientServerSessionHash))
                {
                    _logger.Debug("Server hash mismatch. InvalidCredentialException thrown. Has received: {0}", Convert.ToBase64String(serverSessionHash));
                    throw new InvalidCredentialException("authentication failed");
                }
                _logger.Debug("Server Hash match. Received from server: {0}", Convert.ToBase64String(serverSessionHash));
                _zkCrypto = new ZkCrypto(clientSessionKey, clientScramble);
                _logger.Debug("Zk authentiation completed successfully.");
                sw.Stop();
                _stats.Log("ZkAuthentication", sw.ElapsedMilliseconds);
            }

            if (!SyncInfoCache.TryGetValue(serviceType, out _syncInfo))
            {
                //write the message type
                _binWriter.Write((int)MessageType.SyncInterface);
                if (null != _zkCrypto)
                {
                    //sync interface with encryption
                    var assemName             = serviceType.ToConfigName();
                    var assemblyNameEncrypted = _zkCrypto.Encrypt(assemName.ConvertToBytes());
                    _binWriter.Write(assemblyNameEncrypted.Length);
                    _binWriter.Write(assemblyNameEncrypted);
                }
                else
                {
                    _binWriter.Write(serviceType.ToConfigName());
                }
                //read sync data
                var len = _binReader.ReadInt32();
                //len is zero when AssemblyQualifiedName not same version or not found
                if (len == 0)
                {
                    throw new TypeAccessException("SyncInterface failed. Type or version of type unknown.");
                }
                var bytes = _binReader.ReadBytes(len);
                if (null != _zkCrypto)
                {
                    _logger.Debug("Encrypted data received from server: {0}", Convert.ToBase64String(bytes));
                    bytes = _zkCrypto.Decrypt(bytes);
                    _logger.Debug("Decrypted data received from server: {0}", Convert.ToBase64String(bytes));
                }
                _syncInfo = _serializer.Deserialize <ServiceSyncInfo>(bytes);
                SyncInfoCache.AddOrUpdate(serviceType, _syncInfo, (t, info) => _syncInfo);
            }
        }
Beispiel #3
0
        /// <summary>
        /// This method asks the server for a list of identifiers paired with method
        /// names and -parameter types. This is used when invoking methods server side.
        /// </summary>
        protected override void SyncInterface(Type serviceType)
        {
            if (!_syncInfoCache.TryGetValue(serviceType, out _syncInfo))
            {
                //write the message type
                _binWriter.Write((int)MessageType.SyncInterface);
                _binWriter.Write(serviceType.AssemblyQualifiedName ?? serviceType.FullName);

                //read sync data
                var bytes = _binReader.ReadBytes(_binReader.ReadInt32());
                _syncInfo = (ServiceSyncInfo)bytes.ToDeserializedObject();

                _syncInfoCache.AddOrUpdate(serviceType, _syncInfo, (t, info) => _syncInfo);
            }
        }
        /// <summary>
        /// This method asks the server for a list of identifiers paired with method
        /// names and -parameter types. This is used when invoking methods server side.
        /// </summary>
        protected override void SyncInterface(Type serviceType, 
            string username = null, string password = null)
        {
            if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password))
            {
                //do zk protocol authentication
                var sr = new ZkProtocol();

                // Step 1. Client sends username and ephemeral hash of random number.
                var aRand = sr.CryptRand();
                var aClientEphemeral = sr.GetClientEphemeralA(aRand);

                // send username and aClientEphemeral to server
                _binWriter.Write((int)MessageType.ZkInitiate);
                _binWriter.Write(username);
                _binWriter.Write(aClientEphemeral); //always 32 bytes

                // get response from server
                var userFound = _binReader.ReadBoolean();
                if (!userFound)
                {
                    throw new InvalidCredentialException("authentication failed");
                }
                var salt = _binReader.ReadBytes(32);
                var bServerEphemeral = _binReader.ReadBytes(32);

                // Step 3. Client and server calculate random scramble of ephemeral hash values exchanged.
                var clientScramble = sr.CalculateRandomScramble(aClientEphemeral, bServerEphemeral);

                // Step 4. Client computes session key
                var clientSessionKey = sr.ClientComputeSessionKey(salt, username, password,
                    aClientEphemeral, bServerEphemeral, clientScramble);

                // Step 6. Client creates hash of session key and sends to server. Server creates same key and verifies.
                var clientSessionHash = sr.ClientCreateSessionHash(username, salt, aClientEphemeral,
                    bServerEphemeral, clientSessionKey);
                // send to server and server verifies
                _binWriter.Write((int)MessageType.ZkProof);
                _binWriter.Write(clientSessionHash); //always 32 bytes

                // get response
                var serverVerified = _binReader.ReadBoolean();
                if (!serverVerified)
                {
                    throw new InvalidCredentialException("authentication failed");
                }
                var serverSessionHash = _binReader.ReadBytes(32);
                var clientServerSessionHash = sr.ServerCreateSessionHash(aClientEphemeral,
                    clientSessionHash, clientSessionKey);
                if (!serverSessionHash.IsEqualTo(clientServerSessionHash))
                {
                    throw new InvalidCredentialException("authentication failed");
                }
                _zkCrypto = new ZkCrypto(clientSessionKey, clientScramble);
            }

            if (!_syncInfoCache.TryGetValue(serviceType, out _syncInfo))
            {
                //write the message type
                _binWriter.Write((int)MessageType.SyncInterface);
                if (null != _zkCrypto)
                {
                    //sync interface with encryption
                    var assemName = serviceType.FullName;
                    var assemblyNameEncrypted = _zkCrypto.Encrypt(assemName.ConvertToBytes());
                    _binWriter.Write(assemblyNameEncrypted.Length);
                    _binWriter.Write(assemblyNameEncrypted);
                }
                else
                {
                    _binWriter.Write(serviceType.FullName);
                }
                //read sync data
                var len = _binReader.ReadInt32();
                //len is zero when AssemblyQualifiedName not same version or not found
            #if (!NET35)
                if (len == 0) throw new TypeAccessException("SyncInterface failed. Type or version of type unknown.");
            #else
                if (len == 0) throw new Exception("SyncInterface failed. Type or version of type unknown.");
            #endif
                var bytes = _binReader.ReadBytes(len);
                if (null != _zkCrypto)
                {
                    bytes = _zkCrypto.Decrypt(bytes);
                }
                _syncInfo = bytes.ToDeserializedObject<ServiceSyncInfo>();
                _syncInfoCache.AddOrUpdate(serviceType, _syncInfo, (t, info) => _syncInfo);
            }
        }
Beispiel #5
0
        /// <summary>
        /// This method asks the server for a list of identifiers paired with method
        /// names and -parameter types. This is used when invoking methods server side.
        /// </summary>
        protected override void SyncInterface(Type serviceType,
                                              string username = null, string password = null)
        {
            if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password))
            {
                //do zk protocol authentication
                var sr = new ZkProtocol();

                // Step 1. Client sends username and ephemeral hash of random number.
                var aRand            = sr.CryptRand();
                var aClientEphemeral = sr.GetClientEphemeralA(aRand);

                // send username and aClientEphemeral to server
                _binWriter.Write((int)MessageType.ZkInitiate);
                _binWriter.Write(username);
                _binWriter.Write(aClientEphemeral); //always 32 bytes

                // get response from server
                var userFound = _binReader.ReadBoolean();
                if (!userFound)
                {
                    throw new InvalidCredentialException("authentication failed");
                }
                var salt             = _binReader.ReadBytes(32);
                var bServerEphemeral = _binReader.ReadBytes(32);

                // Step 3. Client and server calculate random scramble of ephemeral hash values exchanged.
                var clientScramble = sr.CalculateRandomScramble(aClientEphemeral, bServerEphemeral);

                // Step 4. Client computes session key
                var clientSessionKey = sr.ClientComputeSessionKey(salt, username, password,
                                                                  aClientEphemeral, bServerEphemeral, clientScramble);

                // Step 6. Client creates hash of session key and sends to server. Server creates same key and verifies.
                var clientSessionHash = sr.ClientCreateSessionHash(username, salt, aClientEphemeral,
                                                                   bServerEphemeral, clientSessionKey);
                // send to server and server verifies
                _binWriter.Write((int)MessageType.ZkProof);
                _binWriter.Write(clientSessionHash); //always 32 bytes

                // get response
                var serverVerified = _binReader.ReadBoolean();
                if (!serverVerified)
                {
                    throw new InvalidCredentialException("authentication failed");
                }
                var serverSessionHash       = _binReader.ReadBytes(32);
                var clientServerSessionHash = sr.ServerCreateSessionHash(aClientEphemeral,
                                                                         clientSessionHash, clientSessionKey);
                if (!serverSessionHash.IsEqualTo(clientServerSessionHash))
                {
                    throw new InvalidCredentialException("authentication failed");
                }
                _zkCrypto = new ZkCrypto(clientSessionKey, clientScramble);
            }

            if (!_syncInfoCache.TryGetValue(serviceType, out _syncInfo))
            {
                //write the message type
                _binWriter.Write((int)MessageType.SyncInterface);
                if (null != _zkCrypto)
                {
                    //sync interface with encryption
                    var assemName             = serviceType.FullName;
                    var assemblyNameEncrypted = _zkCrypto.Encrypt(assemName.ConvertToBytes());
                    _binWriter.Write(assemblyNameEncrypted.Length);
                    _binWriter.Write(assemblyNameEncrypted);
                }
                else
                {
                    _binWriter.Write(serviceType.FullName);
                }
                //read sync data
                var len = _binReader.ReadInt32();
                //len is zero when AssemblyQualifiedName not same version or not found
#if (!NET35)
                if (len == 0)
                {
                    throw new TypeAccessException("SyncInterface failed. Type or version of type unknown.");
                }
#else
                if (len == 0)
                {
                    throw new Exception("SyncInterface failed. Type or version of type unknown.");
                }
#endif
                var bytes = _binReader.ReadBytes(len);
                if (null != _zkCrypto)
                {
                    bytes = _zkCrypto.Decrypt(bytes);
                }
                _syncInfo = bytes.ToDeserializedObject <ServiceSyncInfo>();
                _syncInfoCache.AddOrUpdate(serviceType, _syncInfo, (t, info) => _syncInfo);
            }
        }