Exemplo n.º 1
0
        // =====================================================================
        // TLS support
        // =====================================================================

        /// <summary>
        /// Send IMap STARTTLS command and initialize client side TLS
        /// </summary>
        /// <param name="uTag">
        /// <c>0</c> when called by GetConnection to initialize imaps. Otherwise
        /// a valid tag number causes the STARTTLS imap command to be sent.
        /// </param>
        /// <returns>
        /// <c>true</c> if no problem occurred, <c>false</c> on errors.
        /// For TLS related error a <see cref="ZIMapException"/> is thrown.
        /// </returns>
        /// <remarks>
        /// This routine throws an exception when TLS is "Required" but not
        /// availlable. In "Auto" mode invalid server certificates are accepted,
        /// in mode "Required" an exception is thrown.
        /// </remarks>
        public bool StartTls(uint uTag)
        {
            if(uTag == 0)
                MonitorInfo( "StartTls: TLS via imaps");
            else
            {   if (tlsmode == TlsModeEnum.Disabled || tlsmode == TlsModeEnum.IMaps)
                    return true;                    // nothing to do

                MonitorInfo( "StartTls: send STARTLS");
                transport.Send(uTag, "STARTTLS");
                string tag, status, message;
                while (true)
                {   if (!transport.Receive(out tag, out status, out message)) break;
                    if (tag == uTag.ToString()) break;
                }
                if (status != "OK")
                {   if (tlsmode == TlsModeEnum.Required)
                    {   RaiseError(ZIMapException.Error.CannotConnect,
                                   "STARTTLS failed: " + message);
                        return false;               // required but not ready
                    }
                    MonitorInfo( "StartTls: STARTTLS failed: " + message);
                    tlsmode = TlsModeEnum.Disabled;
                    return true;
                }
            }

            // now get the TLS stream

            Stream strm = null;
            try                                     // all errors throw...
            {   strm = GetTlsStream();
                if(strm == null) return true;       // tls disabled
                stream = strm;
            }
            catch(Exception ex)
            {   if(tlsmode == TlsModeEnum.Required)
                {   RaiseError(ZIMapException.Error.CannotConnect, ex.Message);
                    return false;                   // required but not ready
                }
                if(ex is ZIMapException) throw ex;
                MonitorError("TLS failure: " + ex.Message);
                return false;
            }

            if(uTag == 0)
                tlsmode = TlsModeEnum.IMaps;
            else
                transport.Setup(socket, stream, timeout);
            return true;
        }
Exemplo n.º 2
0
        /// <summary>
        /// Creates a connection instance and opens an IMap connection.
        /// </summary>
        /// <param name="server">
        /// The server URL or IP Address.
        /// </param>
        /// <param name="port">
        /// The port number to be used, see <see cref="GetIMapPort(string)"/>.
        /// </param>
        /// <param name="tlsMode">
        /// Controls TLS (tranport layer security), see <see cref="TlsModeEnum"/>.
        /// </param>
        /// <param name="timeout">
        /// Connection timeout, use <c>0</c> for no timeout.
        /// </param>
        /// <returns>
        /// A new instance of <c>ZIMapConnection</c> that is connected to the
        /// specified IMap server.
        /// </returns>
        /// <remarks>
        /// The method raises an error of type <see cref="ZIMapException.Error.CannotConnect"/>
        /// if no connection can be established.
        /// </remarks>
        public static ZIMapConnection GetConnection(string server, uint port, 
                                                    TlsModeEnum tlsMode, uint timeout)
        {   ZIMapConnection conn = new ZIMapConnection();
            conn.tlsmode = tlsMode;
            conn.timeout = timeout;
            try
            {   conn.socket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, 
                                                              System.Net.Sockets.SocketType.Stream, 
                                                              System.Net.Sockets.ProtocolType.IP);
                // The socket timeouts will be reset by the transport layer!
                if(timeout > 0)
                {   conn.socket.ReceiveTimeout = (int)timeout * 1000;
                    conn.socket.SendTimeout = (int)timeout * 1000;
                }
                conn.socket.NoDelay = true;             // nagle causes more windows trouble
                
                conn.server = server;
                conn.socket.Connect(server, (int)port);

                conn.stream = new System.Net.Sockets.NetworkStream(conn.socket);
            }
            catch(Exception inner)
            {   if(inner is System.Net.Sockets.SocketException)
                    conn.MonitorError("GetConnection: " + inner.Message);
                else
                    conn.RaiseError(ZIMapException.Error.CannotConnect, inner.Message);
                return null;
            }

            // init transport level and start async receive ...
            if(port == 993 && !conn.StartTls(0))
                return null;                                // after Throw()
            conn.transport = new Transport(conn);
            
            // start async receive and init protocol layer ...
            conn.transport.Poll(0);
            conn.protocol = new Protocol(conn, conn.transport);
            return conn;
        }