コード例 #1
0
        /// <summary>
        /// Ends the current client connection.
        /// </summary>
        /// <param name="sender">The current server to client connection channel.</param>
        private void EndConnection(Imap4TlsProxyConnection sender)
        {
            // Release the current client connection
            // resources and make avaliable a new connection.
            if (_client[sender.ClientIndex] != null)
            {
                _client[sender.ClientIndex].Dispose();
                _client[sender.ClientIndex] = null;

                // Decrement the count.
                Interlocked.Decrement(ref _clientCount);

                // Signal to the blocking handler
                // to un-block.
                _connAvailable.Set();
            }
        }
コード例 #2
0
 /// <summary>
 /// Unknown command received.
 /// </summary>
 /// <param name="sender">The current server to client connection channel.</param>
 private void Unknown(Imap4TlsProxyConnection sender)
 {
     if (sender.Connected)
     {
         // Reply to client with unknown command.
         ReplyToSender(sender, "-ERR Unknown command");
     }
     else
     {
         // If an unknown command is sent when the channel is opened
         // but the user has not supplied valid credentials then close
         // the socket channel to the client. This is needed when a
         // client opens a socket channel and starts sending a DOS
         // attack.
         Disconnect(sender, sender.Prefix + " LOGOUT");
     }
 }
コード例 #3
0
        /// <summary>
        /// Connect the client to the server.
        /// </summary>
        /// <param name="sender">The current server to client connection channel.</param>
        /// <param name="data">The data from the client.</param>
        private void Connect(Imap4TlsProxyConnection sender, string data)
        {
            try
            {
                // Add custom validation here.
                // Get the current data.
                string dataArray    = data.Trim();
                string userPassword = string.Empty;
                string prefix       = string.Empty;

                // Start and end of the login index.
                int start = dataArray.ToUpper().IndexOf("LOGIN") + 5;
                userPassword = dataArray.Substring(start);

                // Get the prefix of the current
                // message request.
                int endPrefix = dataArray.IndexOf(" ");
                prefix = dataArray.Substring(0, endPrefix).Trim();

                // Get the user name and passord
                // of the client creadentials.
                sender.ConnectionName = userPassword;
                sender.Prefix         = prefix;
                sender.Connected      = true;

                // Send the command to the imap4 server.
                sender.SendSocketCommand(data);
            }
            catch (Exception e)
            {
                // Detect a thread abort exception.
                if (e is ThreadAbortException)
                {
                    Thread.ResetAbort();
                }

                base.Write("Imap4TlsProxyServer", "Connect", e.Message,
                           382, WriteTo.EventLog, LogType.Error);

                // Reply to client internal server error command.
                ReplyToSender(sender, "500 Error");
            }
        }
コード例 #4
0
        /// <summary>
        /// Disconnect the client from the server, close the channel.
        /// </summary>
        /// <param name="sender">The current server to client connection channel.</param>
        /// <param name="data">The data from the client.</param>
        private void Disconnect(Imap4TlsProxyConnection sender, string data)
        {
            // Add custom validation here.
            // Get the current data.
            string dataArray = data.Trim();
            string prefix    = string.Empty;

            // Get the prefix of the current
            // message request.
            int endPrefix = dataArray.IndexOf(" ");

            prefix        = dataArray.Substring(0, endPrefix).Trim();
            sender.Prefix = prefix;

            // Disconnect the client.
            sender.Connected = false;
            sender.Disconnect(data);
            sender = null;
        }
コード例 #5
0
        /// <summary>
        /// Request an ssl connection to the server.
        /// </summary>
        /// <param name="sender">The current server to client connection channel.</param>
        /// <param name="data">The data from the client.</param>
        private void SslConnection(Imap4TlsProxyConnection sender, string data)
        {
            try
            {
                // Add custom validation here.
                // Get the current data.
                string dataArray = data.Trim();
                string prefix    = string.Empty;

                // Get the prefix of the current
                // message request.
                int endPrefix = dataArray.IndexOf(" ");
                prefix        = dataArray.Substring(0, endPrefix).Trim();
                sender.Prefix = prefix;

                // Create an ssl connection from the socket.
                // Reply to the client that a ssl connection
                // is being created.
                sender.InitializingSSLConnection(prefix + " OK Begin TLS negotiation now");
                sender.TlsNegotiated = true;
            }
            catch (Exception e)
            {
                // Detect a thread abort exception.
                if (e is ThreadAbortException)
                {
                    Thread.ResetAbort();
                }

                base.Write("Imap4TlsProxyServer", "SslConnection", e.Message,
                           382, WriteTo.EventLog, LogType.Error);

                // Reply to client internal server error command.
                ReplyToSender(sender, "500 -ERROR");
            }
        }
コード例 #6
0
 /// <summary>
 /// Reply to the current client.
 /// </summary>
 /// <param name="sender">The current server to client connection channel.</param>
 /// <param name="command">The command to send to the client.</param>
 private void ReplyToSender(Imap4TlsProxyConnection sender, string command)
 {
     sender.SendCommand(command);
 }
コード例 #7
0
        /// <summary>
        /// Processes all in-comming client command requests.
        /// </summary>
        /// <param name="sender">The current server to client connection channel.</param>
        /// <param name="dataReceived">The data received from the client.</param>
        private void client_OnDataReceived(Imap4TlsProxyConnection sender, string dataReceived)
        {
            try
            {
                // Decrypt the data recived from the client.
                string receivedData = dataReceived.Trim();
                string command      = string.Empty;

                // Get specific commands from the client.
                if (receivedData.ToUpper().IndexOf("LOGOUT") > -1)
                {
                    command = "LOGOUT";
                }
                else if (receivedData.ToUpper().IndexOf("LOGIN") > -1)
                {
                    command = "LOGIN";
                }
                else if (receivedData.ToUpper().IndexOf("STARTTLS") > -1)
                {
                    command = "STARTTLS";
                }
                else if (receivedData.ToUpper().IndexOf("CAPABILITY") > -1)
                {
                    command = "CAPABILITY";
                }
                else if (receivedData.ToUpper().IndexOf("AUTHENTICATE") > -1)
                {
                    command = "AUTHENTICATE";
                }
                else if (receivedData.ToUpper().IndexOf("ENDC") > -1)
                {
                    command = "ENDC";
                }
                else
                {
                    command = receivedData;
                }

                // Delay.
                System.Threading.Thread.Sleep(10);

                // Process the command.
                switch (command.ToUpper())
                {
                case "LOGOUT":
                    // Close the client connection.
                    Disconnect(sender, receivedData);
                    break;

                case "LOGIN":
                    // User name.
                    Connect(sender, receivedData);
                    break;

                case "CAPABILITY":
                    if (!sender.TlsNegotiated)
                    {
                        // Send TLS capable.
                        string dataArrayCapable = receivedData.Trim();
                        string prefixCapable    = string.Empty;

                        // Get the prefix of the current
                        // message request.
                        int endPrefixCapable = dataArrayCapable.IndexOf(" ");
                        prefixCapable = dataArrayCapable.Substring(0, endPrefixCapable).Trim();

                        sender.SendNonSSLClientCommand("* CAPABILITY IMAP4 IMAP4rev1 CHILDREN IDLE QUOTA SORT ACL NAMESPACE STARTTLS LOGINDISABLED");
                        sender.SendNonSSLClientCommand(prefixCapable + " OK CAPABILITY completed");
                    }
                    else
                    {
                        // Send the command to the imap4 server.
                        sender.SendSocketCommand(receivedData);
                    }

                    break;

                case "STARTTLS":
                    // Start a TLS connection.
                    SslConnection(sender, receivedData);
                    break;

                case "AUTHENTICATE":
                    // Start a SASL connection
                    string dataArray = receivedData.Trim();
                    string prefix    = string.Empty;

                    // Get the prefix of the current
                    // message request.
                    int endPrefix = dataArray.IndexOf(" ");
                    prefix = dataArray.Substring(0, endPrefix).Trim();

                    // Sent to the client that this
                    // command is not supported.
                    sender.SendNonSSLClientCommand(prefix + " NO Not supported");
                    break;

                case "ENDC":
                    // End the client connection.
                    EndConnection(sender);
                    break;

                default:
                    // An unknown command sent.
                    //Unknown(sender);
                    sender.SendSocketCommand(receivedData);
                    break;
                }
            }
            catch (Exception e)
            {
                // Detect a thread abort exception.
                if (e is ThreadAbortException)
                {
                    Thread.ResetAbort();
                }

                base.Write("Imap4TlsProxyServer", "client_OnDataReceived", e.Message,
                           292, WriteTo.EventLog, LogType.Error);

                // Reply to client internal server error command.
                ReplyToSender(sender, "500 Error");
            }
        }
コード例 #8
0
        /// <summary>
        /// Starts listening on the specified port.
        /// </summary>
        public void StartListen()
        {
            try
            {
                // Get the imap4 server information from
                // the configuration file, the host and
                // port of the imap4 server is located in
                // the default section, this data is used
                // to connect to the imap4 server.
                GetImap4ServerHost();

                // Get the listening port from the configuration
                // file, if no port specified then default or
                // the current port set will be used.
                GetListeningPort();

                // Get the maximum number of clients from the configuration
                // file, if no value is specified then default or
                // the current value will be used.
                GetMaxNumClients();

                // Get the client idle time out from the configuration
                // file, if no value is specified then default or
                // the current value will be used.
                GetClientTimeOut();

                // Get the local end point, the server will listen
                // on only the first IP address assigned.
                //IPEndPoint endPoint = new IPEndPoint(Dns.GetHostEntry(remoteHost).AddressList[0], listenPort);

                // Create a new tcp listener server,
                // and start the server.
                _listener = new TcpListener(System.Net.IPAddress.Any, _listenPort);
                _listener.Start();

                // While the server is alive accept in-comming client
                // connections.
                do
                {
                    // Do not allow any more clients
                    // if maximum is reached.
                    if (_clientCount < (_maxNumClients - 1))
                    {
                        // Find the next available
                        // connection within the list.
                        for (int i = 0; i < _client.Count(); i++)
                        {
                            if (_client[i] == null)
                            {
                                _clientIndex = i;
                                break;
                            }
                        }

                        // Create a new client connection handler for the current
                        // tcp client attempting to connect to the server. Creates
                        // a new channel from the client to the server.
                        _client[_clientIndex] =
                            new Imap4TlsProxyConnection(_listener.AcceptTcpClient(), _connection);

                        // Assign the current index.
                        _client[_clientIndex].ClientIndex = _clientIndex;

                        // if a time out has been set.
                        if (_timeOut > 0)
                        {
                            _client[_clientIndex].TimeOut = _timeOut;
                        }

                        // Create a new client data receive handler, this event
                        // handles commands from the current client.
                        _client[_clientIndex].OnDataReceived +=
                            new TlsProxyImap4ReceiveHandler(client_OnDataReceived);

                        // Increment the count.
                        Interlocked.Increment(ref _clientCount);
                    }
                    else
                    {
                        base.Write("Imap4TlsProxyServer", "StartListen", "Maximum number of client connections has been reached.",
                                   120, WriteTo.EventLog, LogType.Error);

                        // Blocks the current thread until a
                        // connection becomes available.
                        _connAvailable.WaitOne();
                    }
                } while (true);
            }
            catch (SocketException see)
            {
                base.Write("Imap4TlsProxyServer", "StartListen", see.Message,
                           121, WriteTo.EventLog, LogType.Error);
            }
            catch (Exception e)
            {
                // Detect a thread abort exception.
                if (e is ThreadAbortException)
                {
                    Thread.ResetAbort();
                }

                base.Write("Imap4TlsProxyServer", "StartListen", e.Message,
                           121, WriteTo.EventLog, LogType.Error);
            }
            finally
            {
                if (_listener != null)
                {
                    _listener.Stop();
                }

                _listener = null;
            }
        }