Example #1
0
        public override void Open(NpgsqlConnector context)
        {
            try
            {
                IPAddress[] ips    = ResolveIPHost(context.Host);
                Socket      socket = null;

                // try every ip address of the given hostname, use the first reachable one
                foreach (IPAddress ip in ips)
                {
                    IPEndPoint ep = new IPEndPoint(ip, context.Port);
                    socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

                    try
                    {
                        IAsyncResult result = socket.BeginConnect(ep, null, null);

                        if (!result.AsyncWaitHandle.WaitOne(context.ConnectionTimeout * 1000, true))
                        {
                            socket.Close();
                            throw new Exception("Connection establishment timeout. Increase Timeout value in ConnectionString.");
                        }

                        socket.EndConnect(result);

                        // connect was successful, leave the loop
                        break;
                    }
                    catch (Exception)
                    {
                        socket.Close();
                    }
                }

                if (socket == null || !socket.Connected)
                {
                    throw new Exception(string.Format("Failed to establish a connection to '{0}'.", context.Host));
                }

                Stream stream = new NpgsqlNetworkStream(context, socket, true);

                // If the PostgreSQL server has SSL connectors enabled Open SslClientStream if (response == 'S') {
                if (context.SSL || (context.SslMode == SslMode.Require) || (context.SslMode == SslMode.Prefer))
                {
                    PGUtil.WriteInt32(stream, 8);
                    PGUtil.WriteInt32(stream, 80877103);
                    // Receive response

                    Char response = (Char)stream.ReadByte();
                    if (response == 'S')
                    {
                        //create empty collection
                        X509CertificateCollection clientCertificates = new X509CertificateCollection();

                        //trigger the callback to fetch some certificates
                        context.DefaultProvideClientCertificatesCallback(clientCertificates);

                        stream = new SslClientStream(
                            stream,
                            context.Host,
                            true,
                            SecurityProtocolType.Default,
                            clientCertificates);

                        ((SslClientStream)stream).ClientCertSelectionDelegate =
                            new CertificateSelectionCallback(context.DefaultCertificateSelectionCallback);
                        ((SslClientStream)stream).ServerCertValidationDelegate =
                            new CertificateValidationCallback(context.DefaultCertificateValidationCallback);
                        ((SslClientStream)stream).PrivateKeyCertSelectionDelegate =
                            new PrivateKeySelectionCallback(context.DefaultPrivateKeySelectionCallback);
                    }
                    else if (context.SslMode == SslMode.Require)
                    {
                        throw new InvalidOperationException("Ssl connection requested. No Ssl enabled connection from this host is configured.");
                    }
                }

                context.Stream = new NpgsqlBufferedStream(stream);
                context.Socket = socket;

                ChangeState(context, NpgsqlConnectedState.Instance);
            }
            //FIXME: Exceptions that come from what we are handling should be wrapped - e.g. an error connecting to
            //the server should definitely be presented to the uesr as an NpgsqlError. Exceptions from userland should
            //be passed untouched - e.g. ThreadAbortException because the user started this in a thread they created and
            //then aborted should be passed through.
            //Are there any others that should be pass through? Alternatively, are there a finite number that should
            //be wrapped?
            catch (ThreadAbortException)
            {
                throw;
            }
            catch (Exception e)
            {
                throw new NpgsqlException(e.Message, e);
            }
        }
Example #2
0
		public override void Open(NpgsqlConnector context)
		{
			try
			{
				IPAddress[] ips = ResolveIPHost(context.Host);
				Socket socket = null;

				// try every ip address of the given hostname, use the first reachable one
				foreach (IPAddress ip in ips)
				{
					IPEndPoint ep = new IPEndPoint(ip, context.Port);
					socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

					try
					{
						IAsyncResult result = socket.BeginConnect(ep, null, null);

						if (!result.AsyncWaitHandle.WaitOne(context.ConnectionTimeout * 1000, true))
						{
							socket.Close();
							throw new Exception(resman.GetString("Exception_ConnectionTimeout"));
						}

						socket.EndConnect(result);

						// connect was successful, leave the loop
						break;
					}
					catch (Exception)
					{
						socket.Close();
					}
				}

				if (socket == null || !socket.Connected)
				{
					throw new Exception(string.Format(resman.GetString("Exception_FailedConnection"), context.Host));
				}

				Stream stream = new NpgsqlNetworkStream(context, socket, true);

				// If the PostgreSQL server has SSL connectors enabled Open SslClientStream if (response == 'S') {
				if (context.SSL || (context.SslMode == SslMode.Require) || (context.SslMode == SslMode.Prefer))
				{
					PGUtil.WriteInt32(stream, 8);
					PGUtil.WriteInt32(stream, 80877103);
					// Receive response

					Char response = (Char)stream.ReadByte();
					if (response == 'S')
					{
						//create empty collection
						X509CertificateCollection clientCertificates = new X509CertificateCollection();

						//trigger the callback to fetch some certificates
						context.DefaultProvideClientCertificatesCallback(clientCertificates);

						stream = new SslClientStream(
							stream,
							context.Host,
							true,
							SecurityProtocolType.Default,
							clientCertificates);

						((SslClientStream)stream).ClientCertSelectionDelegate =
							new CertificateSelectionCallback(context.DefaultCertificateSelectionCallback);
						((SslClientStream)stream).ServerCertValidationDelegate =
							new CertificateValidationCallback(context.DefaultCertificateValidationCallback);
						((SslClientStream)stream).PrivateKeyCertSelectionDelegate =
							new PrivateKeySelectionCallback(context.DefaultPrivateKeySelectionCallback);
					}
					else if (context.SslMode == SslMode.Require)
					{
						throw new InvalidOperationException(resman.GetString("Exception_Ssl_RequestError"));
					}
				}

				context.Stream = new NpgsqlBufferedStream(stream);
				context.Socket = socket;

				ChangeState(context, NpgsqlConnectedState.Instance);
			}
			//FIXME: Exceptions that come from what we are handling should be wrapped - e.g. an error connecting to
			//the server should definitely be presented to the uesr as an NpgsqlError. Exceptions from userland should
			//be passed untouched - e.g. ThreadAbortException because the user started this in a thread they created and
			//then aborted should be passed through.
			//Are there any others that should be pass through? Alternatively, are there a finite number that should
			//be wrapped?
			catch (ThreadAbortException)
			{
				throw;
			}
			catch (Exception e)
			{
				throw new NpgsqlException(e.Message, e);
			}
		}