Exemplo n.º 1
0
        public Server(DomainManager domains)
            : base(domains, Environment.MachineName)
        {
            SaveTimer = new Timer(SaveProc);
            Lines = new LineSet();
            DirectRemotes = new Dictionary<string, RemoteServer>();
            Remotes = new Dictionary<string, RemoteServer>();
            Settings = InitializeSettings();
            LocalRehash();

            Cache = Cache.Load();
            if (Cache == null)
            {
                Cache = Cache.Create();
                if (!Cache.Save())
                {
                    Console.WriteLine("Unable to save cache.  Will not start until cache is writable for security.");
                    Environment.Exit(1);
                    return;
                }
            }

            Certificates = new CertificateManager();
            string password = Settings.CertificatePassword;
            if (!Certificates.Load(Id, password) && !Certificates.Generate(Id, password))
            {
                Console.WriteLine("Unable to generate certificate on non-Windows OS.  There must be a single, valid X.509 certificate file named 'Certificate.{0}.*' in the current directory.", Id);
                Environment.Exit(1);
                return;
            }

            Initialize();
        }
Exemplo n.º 2
0
        /// <summary>
        ///     This is called when this proxy acts as a reverse proxy (like a real http server).
        ///     So for HTTPS requests we would start SSL negotiation right away without expecting a CONNECT request from client
        /// </summary>
        /// <param name="endPoint">The transparent endpoint.</param>
        /// <param name="clientConnection">The client connection.</param>
        /// <returns></returns>
        private async Task handleClient(TransparentProxyEndPoint endPoint, TcpClientConnection clientConnection)
        {
            var cancellationTokenSource = new CancellationTokenSource();
            var cancellationToken       = cancellationTokenSource.Token;

            var clientStream       = new CustomBufferedStream(clientConnection.GetStream(), BufferPool, BufferSize);
            var clientStreamWriter = new HttpResponseWriter(clientStream, BufferPool, BufferSize);

            SslStream sslStream = null;

            try
            {
                var clientHelloInfo = await SslTools.PeekClientHello(clientStream, BufferPool, cancellationToken);

                bool   isHttps       = clientHelloInfo != null;
                string httpsHostName = null;

                if (isHttps)
                {
                    httpsHostName = clientHelloInfo.GetServerName() ?? endPoint.GenericCertificateName;

                    var args = new BeforeSslAuthenticateEventArgs(cancellationTokenSource)
                    {
                        SniHostName = httpsHostName
                    };

                    await endPoint.InvokeBeforeSslAuthenticate(this, args, ExceptionFunc);

                    if (cancellationTokenSource.IsCancellationRequested)
                    {
                        throw new Exception("Session was terminated by user.");
                    }

                    if (endPoint.DecryptSsl && args.DecryptSsl)
                    {
                        //do client authentication using certificate
                        X509Certificate2 certificate = null;
                        try
                        {
                            sslStream = new SslStream(clientStream, true);

                            string certName = HttpHelper.GetWildCardDomainName(httpsHostName);
                            certificate = endPoint.GenericCertificate ??
                                          await CertificateManager.CreateServerCertificate(certName);

                            // Successfully managed to authenticate the client using the certificate
                            await sslStream.AuthenticateAsServerAsync(certificate, false, SslProtocols.Tls, false);

                            // HTTPS server created - we can now decrypt the client's traffic
                            clientStream = new CustomBufferedStream(sslStream, BufferPool, BufferSize);

                            clientStreamWriter = new HttpResponseWriter(clientStream, BufferPool, BufferSize);
                        }
                        catch (Exception e)
                        {
                            var certname = certificate?.GetNameInfo(X509NameType.SimpleName, false);
                            var session  = new SessionEventArgs(this, endPoint, cancellationTokenSource)
                            {
                                ProxyClient = { Connection = clientConnection },
                                HttpClient  = { ConnectRequest = null }
                            };
                            throw new ProxyConnectException(
                                      $"Couldn't authenticate host '{httpsHostName}' with certificate '{certname}'.", e, session);
                        }
                    }
                    else
                    {
                        var connection = await tcpConnectionFactory.GetServerConnection(httpsHostName, endPoint.Port,
                                                                                        httpVersion : null, isHttps : false, applicationProtocols : null,
                                                                                        isConnect : true, proxyServer : this, session : null, upStreamEndPoint : UpStreamEndPoint,
                                                                                        externalProxy : UpStreamHttpsProxy, noCache : true, cancellationToken : cancellationToken);

                        try
                        {
                            CustomBufferedStream serverStream = null;
                            int available = clientStream.Available;

                            if (available > 0)
                            {
                                // send the buffered data
                                var data = BufferPool.GetBuffer(BufferSize);
                                try
                                {
                                    // clientStream.Available should be at most BufferSize because it is using the same buffer size
                                    await clientStream.ReadAsync(data, 0, available, cancellationToken);

                                    serverStream = connection.Stream;
                                    await serverStream.WriteAsync(data, 0, available, cancellationToken);

                                    await serverStream.FlushAsync(cancellationToken);
                                }
                                finally
                                {
                                    BufferPool.ReturnBuffer(data);
                                }
                            }

                            await TcpHelper.SendRaw(clientStream, serverStream, BufferPool, BufferSize,
                                                    null, null, cancellationTokenSource, ExceptionFunc);
                        }
                        finally
                        {
                            await tcpConnectionFactory.Release(connection, true);
                        }

                        return;
                    }
                }
                // HTTPS server created - we can now decrypt the client's traffic
                // Now create the request
                await handleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter,
                                               cancellationTokenSource, isHttps?httpsHostName : null, null, null);
            }
            catch (ProxyException e)
            {
                onException(clientStream, e);
            }
            catch (IOException e)
            {
                onException(clientStream, new Exception("Connection was aborted", e));
            }
            catch (SocketException e)
            {
                onException(clientStream, new Exception("Could not connect", e));
            }
            catch (Exception e)
            {
                onException(clientStream, new Exception("Error occured in whilst handling the client", e));
            }
            finally
            {
                sslStream?.Dispose();
                clientStream.Dispose();

                if (!cancellationTokenSource.IsCancellationRequested)
                {
                    cancellationTokenSource.Cancel();
                }
            }
        }
Exemplo n.º 3
0
    // Acquires a client certificate from the service utility endpoint and
    // attempts to install it into the store.  All failures are
    // propagated back to the caller.
    private static X509Certificate2 InstallClientCertificateFromServer()
    {
        X509Certificate2 clientCertificate = new X509Certificate2(GetResourceFromServiceAsByteArray(ClientCertificateResource), "test", X509KeyStorageFlags.PersistKeySet);

        return(CertificateManager.InstallCertificateToMyStore(clientCertificate));
    }
Exemplo n.º 4
0
    // Acquires a root certificate from the service utility endpoint and
    // attempts to install it into the root store.  It returns the
    // certificate in the store, which may include one that was already
    // installed.  Exceptions are propagated to the caller.
    private static X509Certificate2 InstallRootCertificateFromServer()
    {
        X509Certificate2 rootCertificate = new X509Certificate2(GetResourceFromServiceAsByteArray(RootCertificateResource));

        return(CertificateManager.InstallCertificateToRootStore(rootCertificate));
    }
Exemplo n.º 5
0
        /// <summary>
        /// This is called when client is aware of proxy
        /// So for HTTPS requests client would send CONNECT header to negotiate a secure tcp tunnel via proxy
        /// </summary>
        /// <param name="endPoint"></param>
        /// <param name="tcpClient"></param>
        /// <returns></returns>
        private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClient tcpClient)
        {
            var clientStream = new CustomBufferedStream(tcpClient.GetStream(), BufferSize);

            var clientStreamReader = new CustomBinaryReader(clientStream, BufferSize);
            var clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize);

            try
            {
                string connectHostname = null;

                ConnectRequest connectRequest = null;

                //Client wants to create a secure tcp tunnel (probably its a HTTPS or Websocket request)
                if (await HttpHelper.IsConnectMethod(clientStream) == 1)
                {
                    //read the first line HTTP command
                    string httpCmd = await clientStreamReader.ReadLineAsync();

                    if (string.IsNullOrEmpty(httpCmd))
                    {
                        return;
                    }

                    Request.ParseRequestLine(httpCmd, out string _, out string httpUrl, out var version);

                    var httpRemoteUri = new Uri("http://" + httpUrl);
                    connectHostname = httpRemoteUri.Host;

                    //filter out excluded host names
                    bool excluded = false;

                    if (endPoint.BeforeTunnelConnect != null)
                    {
                        excluded = await endPoint.BeforeTunnelConnect(connectHostname);
                    }

                    connectRequest = new ConnectRequest
                    {
                        RequestUri  = httpRemoteUri,
                        OriginalUrl = httpUrl,
                        HttpVersion = version,
                    };

                    await HeaderParser.ReadHeaders(clientStreamReader, connectRequest.Headers);

                    var connectArgs = new TunnelConnectSessionEventArgs(BufferSize, endPoint, connectRequest, ExceptionFunc);
                    connectArgs.ProxyClient.TcpClient    = tcpClient;
                    connectArgs.ProxyClient.ClientStream = clientStream;

                    await endPoint.InvokeTunnectConnectRequest(this, connectArgs, ExceptionFunc);


                    if (await CheckAuthorization(clientStreamWriter, connectArgs) == false)
                    {
                        await endPoint.InvokeTunnectConnectResponse(this, connectArgs, ExceptionFunc);

                        return;
                    }

                    //write back successfull CONNECT response
                    var response = ConnectResponse.CreateSuccessfullConnectResponse(version);
                    response.Headers.FixProxyHeaders();
                    connectArgs.WebSession.Response = response;

                    await clientStreamWriter.WriteResponseAsync(response);

                    var clientHelloInfo = await SslTools.PeekClientHello(clientStream);

                    bool isClientHello = clientHelloInfo != null;
                    if (isClientHello)
                    {
                        connectRequest.ClientHelloInfo = clientHelloInfo;
                    }

                    await endPoint.InvokeTunnectConnectResponse(this, connectArgs, ExceptionFunc, isClientHello);

                    if (!excluded && isClientHello)
                    {
                        connectRequest.RequestUri = new Uri("https://" + httpUrl);

                        SslStream sslStream = null;

                        try
                        {
                            sslStream = new SslStream(clientStream);

                            string certName = HttpHelper.GetWildCardDomainName(connectHostname);

                            var certificate = endPoint.GenericCertificate ?? await CertificateManager.CreateCertificateAsync(certName);

                            //Successfully managed to authenticate the client using the fake certificate
                            await sslStream.AuthenticateAsServerAsync(certificate, false, SupportedSslProtocols, false);

                            //HTTPS server created - we can now decrypt the client's traffic
                            clientStream = new CustomBufferedStream(sslStream, BufferSize);

                            clientStreamReader.Dispose();
                            clientStreamReader = new CustomBinaryReader(clientStream, BufferSize);
                            clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize);
                        }
                        catch
                        {
                            sslStream?.Dispose();
                            return;
                        }

                        if (await HttpHelper.IsConnectMethod(clientStream) == -1)
                        {
                            // It can be for example some Google (Cloude Messaging for Chrome) magic
                            excluded = true;
                        }
                    }

                    //Hostname is excluded or it is not an HTTPS connect
                    if (excluded || !isClientHello)
                    {
                        //create new connection
                        using (var connection = await GetServerConnection(connectArgs, true))
                        {
                            if (isClientHello)
                            {
                                int available = clientStream.Available;
                                if (available > 0)
                                {
                                    //send the buffered data
                                    var data = BufferPool.GetBuffer(BufferSize);

                                    try
                                    {
                                        // clientStream.Available sbould be at most BufferSize because it is using the same buffer size
                                        await clientStream.ReadAsync(data, 0, available);

                                        await connection.StreamWriter.WriteAsync(data, 0, available, true);
                                    }
                                    finally
                                    {
                                        BufferPool.ReturnBuffer(data);
                                    }
                                }

                                var serverHelloInfo = await SslTools.PeekServerHello(connection.Stream);

                                ((ConnectResponse)connectArgs.WebSession.Response).ServerHelloInfo = serverHelloInfo;
                            }

                            await TcpHelper.SendRaw(clientStream, connection.Stream, BufferSize,
                                                    (buffer, offset, count) => { connectArgs.OnDataSent(buffer, offset, count); },
                                                    (buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); },
                                                    ExceptionFunc);
                        }

                        return;
                    }
                }

                //Now create the request
                await HandleHttpSessionRequest(tcpClient, clientStream, clientStreamReader, clientStreamWriter, connectHostname, endPoint, connectRequest);
            }
            catch (ProxyHttpException e)
            {
                ExceptionFunc(e);
            }
            catch (IOException e)
            {
                ExceptionFunc(new Exception("Connection was aborted", e));
            }
            catch (SocketException e)
            {
                ExceptionFunc(new Exception("Could not connect", e));
            }
            catch (Exception e)
            {
                ExceptionFunc(new Exception("Error occured in whilst handling the client", e));
            }
            finally
            {
                clientStreamReader.Dispose();
                clientStream.Dispose();
            }
        }
Exemplo n.º 6
0
        public async Task TestChallengeRequestDNSWildcard()
        {
            var testStr = Guid.NewGuid().ToString().Substring(0, 6);

            PrimaryTestDomain = $"test-{testStr}." + PrimaryTestDomain;
            var wildcardDomain       = "*.test." + PrimaryTestDomain;
            var testWildcardSiteName = "TestWildcard_" + testStr;

            if (await iisManager.SiteExists(testWildcardSiteName))
            {
                await iisManager.DeleteSite(testWildcardSiteName);
            }

            var site = await iisManager.CreateSite(testWildcardSiteName, "test" + testStr + "." + PrimaryTestDomain, PrimaryIISRoot, "DefaultAppPool", port : testSiteHttpPort);

            ManagedCertificate managedCertificate = null;
            X509Certificate2   certInfo           = null;

            try
            {
                managedCertificate = new ManagedCertificate
                {
                    Id             = Guid.NewGuid().ToString(),
                    Name           = testWildcardSiteName,
                    GroupId        = site.Id.ToString(),
                    UseStagingMode = true,
                    RequestConfig  = new CertRequestConfig
                    {
                        PrimaryDomain                    = wildcardDomain,
                        PerformAutoConfig                = true,
                        PerformAutomatedCertBinding      = true,
                        PerformChallengeFileCopy         = true,
                        PerformExtensionlessConfigChecks = true,
                        WebsiteRootPath                  = testSitePath,
                        Challenges = new ObservableCollection <CertRequestChallengeConfig>
                        {
                            new CertRequestChallengeConfig {
                                ChallengeType          = SupportedChallengeTypes.CHALLENGE_TYPE_DNS,
                                ChallengeProvider      = "DNS01.API.Cloudflare",
                                ChallengeCredentialKey = _testCredStorageKey,
                                ZoneId = ConfigSettings["Cloudflare_ZoneId"]
                            }
                        }
                    },
                    ItemType = ManagedCertificateType.SSL_ACME
                };

                var result = await certifyManager.PerformCertificateRequest(_log, managedCertificate);

                //ensure cert request was successful
                Assert.IsTrue(result.IsSuccess, "Certificate Request Not Completed");

                //check details of cert, subject alternative name should include domain and expiry must be great than 89 days in the future
                var managedCertificates = await certifyManager.GetManagedCertificates();

                managedCertificate = managedCertificates.FirstOrDefault(m => m.Id == managedCertificate.Id);

                //emsure we have a new managed site
                Assert.IsNotNull(managedCertificate);

                //have cert file details
                Assert.IsNotNull(managedCertificate.CertificatePath);

                var fileExists = System.IO.File.Exists(managedCertificate.CertificatePath);
                Assert.IsTrue(fileExists);

                //check cert is correct
                certInfo = CertificateManager.LoadCertificate(managedCertificate.CertificatePath);
                Assert.IsNotNull(certInfo);

                var isRecentlyCreated = Math.Abs((DateTime.UtcNow - certInfo.NotBefore).TotalDays) < 2;
                Assert.IsTrue(isRecentlyCreated);

                var expiresInFuture = (certInfo.NotAfter - DateTime.UtcNow).TotalDays >= 89;
                Assert.IsTrue(expiresInFuture);
            }
            finally
            {
                // remove IIS site
                await iisManager.DeleteSite(testWildcardSiteName);

                // remove managed site
                if (managedCertificate != null)
                {
                    await certifyManager.DeleteManagedCertificate(managedCertificate.Id);
                }

                // cleanup certificate
                if (certInfo != null)
                {
                    CertificateManager.RemoveCertificate(certInfo);
                }
            }
        }
Exemplo n.º 7
0
        public async Task TestChallengeRequestDNS()
        {
            var site = await iisManager.GetIISSiteById(_siteId);

            Assert.AreEqual(site.Name, testSiteName);

            var dummyManagedCertificate = new ManagedCertificate
            {
                Id             = Guid.NewGuid().ToString(),
                Name           = testSiteName,
                GroupId        = site.Id.ToString(),
                UseStagingMode = true,
                RequestConfig  = new CertRequestConfig
                {
                    PrimaryDomain                    = testSiteDomain,
                    PerformAutoConfig                = true,
                    PerformAutomatedCertBinding      = true,
                    PerformChallengeFileCopy         = true,
                    PerformExtensionlessConfigChecks = true,
                    WebsiteRootPath                  = testSitePath,
                    Challenges = new ObservableCollection <CertRequestChallengeConfig> {
                        new CertRequestChallengeConfig {
                            ChallengeType          = "dns-01",
                            ChallengeProvider      = "DNS01.API.Cloudflare",
                            ChallengeCredentialKey = _testCredStorageKey,
                            Parameters             = new ObservableCollection <Models.Config.ProviderParameter> {
                                new Models.Config.ProviderParameter {
                                    Key = "propagationdelay", Value = "10"
                                }
                            },
                            ZoneId = ConfigSettings["Cloudflare_ZoneId"]
                        }
                    },
                    DeploymentSiteOption = DeploymentOption.SingleSite
                },
                ItemType = ManagedCertificateType.SSL_ACME
            };

            var result = await certifyManager.PerformCertificateRequest(_log, dummyManagedCertificate);

            //ensure cert request was successful
            Assert.IsTrue(result.IsSuccess, "Certificate Request Not Completed");

            //check details of cert, subject alternative name should include domain and expiry must be great than 89 days in the future
            var managedCertificates = await certifyManager.GetManagedCertificates();

            var managedCertificate = managedCertificates.FirstOrDefault(m => m.Id == dummyManagedCertificate.Id);

            //emsure we have a new managed site
            Assert.IsNotNull(managedCertificate);

            //have cert file details
            Assert.IsNotNull(managedCertificate.CertificatePath);

            var fileExists = System.IO.File.Exists(managedCertificate.CertificatePath);

            Assert.IsTrue(fileExists);

            //check cert is correct
            var certInfo = CertificateManager.LoadCertificate(managedCertificate.CertificatePath);

            Assert.IsNotNull(certInfo);

            var isRecentlyCreated = Math.Abs((DateTime.UtcNow - certInfo.NotBefore).TotalDays) < 2;

            Assert.IsTrue(isRecentlyCreated);

            var expiresInFuture = (certInfo.NotAfter - DateTime.UtcNow).TotalDays >= 89;

            Assert.IsTrue(expiresInFuture);

            // remove managed site
            await certifyManager.DeleteManagedCertificate(managedCertificate.Id);

            // cleanup certificate
            CertificateManager.RemoveCertificate(certInfo);
        }
Exemplo n.º 8
0
    // Acquires the peer trust certificate from the service utility endpoint and
    // attempts to install it into the our custom keychain store.  All failures are
    // propagated back to the caller.
    private static X509Certificate2 InstallOSXPeerCertificateFromServer()
    {
        X509Certificate2 peerCertificate = new X509Certificate2(GetResourceFromServiceAsByteArray(PeerCertificateResource), "test", X509KeyStorageFlags.DefaultKeySet);

        return(CertificateManager.InstallCertificateToOSXKeychainStore(peerCertificate));
    }
Exemplo n.º 9
0
        /// <summary>
        ///     This is called when client is aware of proxy
        ///     So for HTTPS requests client would send CONNECT header to negotiate a secure tcp tunnel via proxy
        /// </summary>
        /// <param name="endPoint">The explicit endpoint.</param>
        /// <param name="clientConnection">The client connection.</param>
        /// <returns>The task.</returns>
        internal async Task handleClient(ExplicitProxyEndPoint endPoint, RequestStateBase state)
        {
            TcpClientConnection clientConnection = state.ClientConnection;
            var cancellationTokenSource          = new CancellationTokenSource();
            var cancellationToken = cancellationTokenSource.Token;

            var clientStream = new HttpClientStream(clientConnection, clientConnection.GetStream(), BufferPool);

            Task <TcpServerConnection>?prefetchConnectionTask = null;
            bool closeServerConnection = false;
            bool calledRequestHandler  = false;

            SslStream?sslStream = null;

            try
            {
                TunnelConnectSessionEventArgs?connectArgs = null;

                var method = await HttpHelper.GetMethod(clientStream, BufferPool, cancellationToken);

                if (clientStream.IsClosed)
                {
                    return;
                }

                // Client wants to create a secure tcp tunnel (probably its a HTTPS or Websocket request)
                if (method == KnownMethod.Connect)
                {
                    // read the first line HTTP command
                    var requestLine = await clientStream.ReadRequestLine(cancellationToken);

                    if (requestLine.IsEmpty())
                    {
                        return;
                    }

                    var connectRequest = new ConnectRequest(requestLine.RequestUri)
                    {
                        RequestUriString8 = requestLine.RequestUri,
                        HttpVersion       = requestLine.Version
                    };

                    await HeaderParser.ReadHeaders(clientStream, connectRequest.Headers, cancellationToken);

                    connectArgs = new TunnelConnectSessionEventArgs(state, endPoint, connectRequest,
                                                                    clientConnection, clientStream, cancellationTokenSource);
                    clientStream.DataRead  += (o, args) => connectArgs.OnDataSent(args.Buffer, args.Offset, args.Count);
                    clientStream.DataWrite += (o, args) => connectArgs.OnDataReceived(args.Buffer, args.Offset, args.Count);

                    await endPoint.InvokeBeforeTunnelConnectRequest(this, connectArgs, ExceptionFunc);

                    // filter out excluded host names
                    bool decryptSsl  = endPoint.DecryptSsl && connectArgs.DecryptSsl;
                    bool sendRawData = !decryptSsl;

                    if (connectArgs.DenyConnect)
                    {
                        if (connectArgs.HttpClient.Response.StatusCode == 0)
                        {
                            connectArgs.HttpClient.Response = new Response
                            {
                                HttpVersion       = HttpHeader.Version11,
                                StatusCode        = (int)HttpStatusCode.Forbidden,
                                StatusDescription = "Forbidden"
                            };
                        }

                        // send the response
                        await clientStream.WriteResponseAsync(connectArgs.HttpClient.Response, cancellationToken);

                        return;
                    }

                    if (await checkAuthorization(connectArgs) == false)
                    {
                        await endPoint.InvokeBeforeTunnelConnectResponse(this, connectArgs, ExceptionFunc);

                        // send the response
                        await clientStream.WriteResponseAsync(connectArgs.HttpClient.Response, cancellationToken);

                        return;
                    }

                    // write back successful CONNECT response
                    var response = ConnectResponse.CreateSuccessfulConnectResponse(requestLine.Version);

                    // Set ContentLength explicitly to properly handle HTTP 1.0
                    response.ContentLength = 0;
                    response.Headers.FixProxyHeaders();
                    connectArgs.HttpClient.Response = response;

                    await clientStream.WriteResponseAsync(response, cancellationToken);

                    var clientHelloInfo = await SslTools.PeekClientHello(clientStream, BufferPool, cancellationToken);

                    if (clientStream.IsClosed)
                    {
                        return;
                    }

                    bool isClientHello = clientHelloInfo != null;
                    if (clientHelloInfo != null)
                    {
                        connectRequest.TunnelType      = TunnelType.Https;
                        connectRequest.ClientHelloInfo = clientHelloInfo;
                    }

                    await endPoint.InvokeBeforeTunnelConnectResponse(this, connectArgs, ExceptionFunc, isClientHello);

                    if (decryptSsl && clientHelloInfo != null)
                    {
                        connectRequest.IsHttps = true; // todo: move this line to the previous "if"
                        clientStream.Connection.SslProtocol = clientHelloInfo.SslProtocol;

                        bool http2Supported = false;

                        if (EnableHttp2)
                        {
                            var alpn = clientHelloInfo.GetAlpn();
                            if (alpn != null && alpn.Contains(SslApplicationProtocol.Http2))
                            {
                                // test server HTTP/2 support
                                try
                                {
                                    // todo: this is a hack, because Titanium does not support HTTP protocol changing currently
                                    var connection = await tcpConnectionFactory.GetServerConnection(state,
                                                                                                    true, SslExtensions.Http2ProtocolAsList,
                                                                                                    true, cancellationToken);

                                    http2Supported = connection.NegotiatedApplicationProtocol ==
                                                     SslApplicationProtocol.Http2;

                                    // release connection back to pool instead of closing when connection pool is enabled.
                                    await tcpConnectionFactory.Release(connection, true);
                                }
                                catch (Exception)
                                {
                                    // ignore
                                }
                            }
                        }

                        if (EnableTcpServerConnectionPrefetch)
                        {
                            IPAddress[]? ipAddresses = null;
                            try
                            {
                                // make sure the host can be resolved before creating the prefetch task
                                ipAddresses = await Dns.GetHostAddressesAsync(connectArgs.HttpClient.Request.RequestUri.Host);
                            }
                            catch (SocketException) { }

                            if (ipAddresses != null && ipAddresses.Length > 0)
                            {
                                // don't pass cancellation token here
                                // it could cause floating server connections when client exits
                                prefetchConnectionTask = tcpConnectionFactory.GetServerConnection(state,
                                                                                                  true, null, false,
                                                                                                  CancellationToken.None);
                            }
                        }

                        string connectHostname = requestLine.RequestUri.GetString();
                        int    idx             = connectHostname.IndexOf(":");
                        if (idx >= 0)
                        {
                            connectHostname = connectHostname.Substring(0, idx);
                        }

                        X509Certificate2?certificate = null;
                        try
                        {
                            sslStream = new SslStream(clientStream, false);

                            string certName = HttpHelper.GetWildCardDomainName(connectHostname);
                            certificate = endPoint.GenericCertificate ??
                                          await CertificateManager.CreateServerCertificate(certName);

                            // Successfully managed to authenticate the client using the fake certificate
                            var options = new SslServerAuthenticationOptions();
                            if (EnableHttp2 && http2Supported)
                            {
                                options.ApplicationProtocols = clientHelloInfo.GetAlpn();
                                if (options.ApplicationProtocols == null || options.ApplicationProtocols.Count == 0)
                                {
                                    options.ApplicationProtocols = SslExtensions.Http11ProtocolAsList;
                                }
                            }

                            options.ServerCertificate              = certificate;
                            options.ClientCertificateRequired      = false;
                            options.EnabledSslProtocols            = SupportedSslProtocols;
                            options.CertificateRevocationCheckMode = X509RevocationMode.NoCheck;
                            await sslStream.AuthenticateAsServerAsync(options, cancellationToken);

#if NETSTANDARD2_1
                            clientStream.Connection.NegotiatedApplicationProtocol = sslStream.NegotiatedApplicationProtocol;
#endif

                            // HTTPS server created - we can now decrypt the client's traffic
                            clientStream = new HttpClientStream(clientStream.Connection, sslStream, BufferPool);
                            sslStream    = null; // clientStream was created, no need to keep SSL stream reference

                            clientStream.DataRead  += (o, args) => connectArgs.OnDecryptedDataSent(args.Buffer, args.Offset, args.Count);
                            clientStream.DataWrite += (o, args) => connectArgs.OnDecryptedDataReceived(args.Buffer, args.Offset, args.Count);
                        }
                        catch (Exception e)
                        {
                            var certName = certificate?.GetNameInfo(X509NameType.SimpleName, false);
                            throw new ProxyConnectException(
                                      $"Couldn't authenticate host '{connectHostname}' with certificate '{certName}'.", e, connectArgs);
                        }

                        method = await HttpHelper.GetMethod(clientStream, BufferPool, cancellationToken);

                        if (clientStream.IsClosed)
                        {
                            return;
                        }

                        if (method == KnownMethod.Invalid)
                        {
                            sendRawData = true;
                            await tcpConnectionFactory.Release(prefetchConnectionTask, true);

                            prefetchConnectionTask = null;
                        }
                    }
                    else if (clientHelloInfo == null)
                    {
                        method = await HttpHelper.GetMethod(clientStream, BufferPool, cancellationToken);

                        if (clientStream.IsClosed)
                        {
                            return;
                        }
                    }

                    if (cancellationTokenSource.IsCancellationRequested)
                    {
                        throw new Exception("Session was terminated by user.");
                    }

                    if (method == KnownMethod.Invalid)
                    {
                        sendRawData = true;
                    }

                    // Hostname is excluded or it is not an HTTPS connect
                    if (sendRawData)
                    {
                        // create new connection to server.
                        // If we detected that client tunnel CONNECTs without SSL by checking for empty client hello then
                        // this connection should not be HTTPS.
                        var connection = await tcpConnectionFactory.GetServerConnection(state,
                                                                                        true, SslExtensions.Http2ProtocolAsList,
                                                                                        true, cancellationToken);

                        try
                        {
                            if (isClientHello)
                            {
                                int available = clientStream.Available;
                                if (available > 0)
                                {
                                    // send the buffered data
                                    var data = BufferPool.GetBuffer();

                                    try
                                    {
                                        // clientStream.Available should be at most BufferSize because it is using the same buffer size
                                        int read = await clientStream.ReadAsync(data, 0, available, cancellationToken);

                                        if (read != available)
                                        {
                                            throw new Exception("Internal error.");
                                        }

                                        await connection.Stream.WriteAsync(data, 0, available, true, cancellationToken);
                                    }
                                    finally
                                    {
                                        BufferPool.ReturnBuffer(data);
                                    }
                                }

                                var serverHelloInfo = await SslTools.PeekServerHello(connection.Stream, BufferPool, cancellationToken);

                                ((ConnectResponse)connectArgs.HttpClient.Response).ServerHelloInfo = serverHelloInfo;
                            }

                            if (!clientStream.IsClosed && !connection.Stream.IsClosed)
                            {
                                await TcpHelper.SendRaw(clientStream, connection.Stream, BufferPool,
                                                        null, null, connectArgs.CancellationTokenSource, ExceptionFunc);
                            }
                        }
                        finally
                        {
                            await tcpConnectionFactory.Release(connection, true);
                        }

                        return;
                    }
                }

                if (connectArgs != null && method == KnownMethod.Pri)
                {
                    // todo
                    string?httpCmd = await clientStream.ReadLineAsync(cancellationToken);

                    if (httpCmd == "PRI * HTTP/2.0")
                    {
                        connectArgs.HttpClient.ConnectRequest !.TunnelType = TunnelType.Http2;

                        // HTTP/2 Connection Preface
                        string?line = await clientStream.ReadLineAsync(cancellationToken);

                        if (line != string.Empty)
                        {
                            throw new Exception($"HTTP/2 Protocol violation. Empty string expected, '{line}' received");
                        }

                        line = await clientStream.ReadLineAsync(cancellationToken);

                        if (line != "SM")
                        {
                            throw new Exception($"HTTP/2 Protocol violation. 'SM' expected, '{line}' received");
                        }

                        line = await clientStream.ReadLineAsync(cancellationToken);

                        if (line != string.Empty)
                        {
                            throw new Exception($"HTTP/2 Protocol violation. Empty string expected, '{line}' received");
                        }

                        var connection = await tcpConnectionFactory.GetServerConnection(state,
                                                                                        true, SslExtensions.Http2ProtocolAsList,
                                                                                        true, cancellationToken);

                        try
                        {
#if NETSTANDARD2_1
                            var connectionPreface = new ReadOnlyMemory <byte>(Http2Helper.ConnectionPreface);
                            await connection.Stream.WriteAsync(connectionPreface, cancellationToken);

                            await Http2Helper.SendHttp2(clientStream, connection.Stream,
                                                        () => new SessionEventArgs(state, endPoint, clientStream, connectArgs?.HttpClient.ConnectRequest, cancellationTokenSource)
                            {
                                UserData = connectArgs?.UserData
                            },
                                                        async args => { await onBeforeRequest(args); },
                                                        async args => { await onBeforeResponse(args); },
                                                        connectArgs.CancellationTokenSource, clientStream.Connection.Id, ExceptionFunc);
#endif
                        }
                        finally
                        {
                            await tcpConnectionFactory.Release(connection, true);
                        }
                    }
                }

                calledRequestHandler = true;

                // Now create the request
                await handleHttpSessionRequest(endPoint, state, clientStream, cancellationTokenSource, connectArgs, prefetchConnectionTask);
            }
            catch (ProxyException e)
            {
                closeServerConnection = true;
                onException(clientStream, e);
            }
            catch (IOException e)
            {
                closeServerConnection = true;
                onException(clientStream, new Exception("Connection was aborted", e));
            }
            catch (SocketException e)
            {
                closeServerConnection = true;
                onException(clientStream, new Exception("Could not connect", e));
            }
            catch (Exception e)
            {
                closeServerConnection = true;
                onException(clientStream, new Exception("Error occured in whilst handling the client", e));
            }
            finally
            {
                if (!calledRequestHandler)
                {
                    await tcpConnectionFactory.Release(prefetchConnectionTask, closeServerConnection);
                }

                sslStream?.Dispose();
                clientStream.Dispose();
            }
        }
        public static ActionResult __Uninstall(Session session)
        {
            ActionResult result;

            var methodName =
                MethodBase.GetCurrentMethod().Name;

            session.Log("{0}: BEGIN", methodName);

            try
            {
                var filePath =
                    session.CustomActionData["SessionData"];

                var sessionData =
                    SessionManager.Load(filePath);

                session.Log("{0}: Product Version = {1}", methodName, sessionData.InstallerVersion);

                var providerConfig =
                    ConfigManager.GetConfiguration(sessionData.Application);

                var port =
                    providerConfig.ListenPort;

                StoreName storeName;

                var certificate =
                    CertificateManager.GetBindedCertificate(providerConfig.ListenPort, out storeName);

                session.Log("{0}: PORT = {1}", methodName, port);

                CertificateManager.UnbindCertificate(port);

                if (certificate != null)
                {
                    session.Log("{0}: THUMBPRINT = {1}", methodName, certificate.Thumbprint);

                    CertificateManager.DeleteCertificate(certificate.Thumbprint, storeName);
                }

                try
                {
                    var vimData =
                        SessionManager.Load(VimDataKeyName, VimDataValueName);

                    session.Log("{0}: VCENTERSERVER = {1}", methodName, vimData.vCenterServer);

                    session.Log("{0}: VCENTERUSERNAME = {1}", methodName, vimData.vCenterUserName);

                    session.Log("{0}: PROVIDERUNIQUEID = {1}", methodName, vimData.ProviderUniqueId);

                    RegistrationManager.UnregisterProvider(vimData.ProviderUniqueId, vimData.vCenterServer, vimData.vCenterUserName, vimData.vCenterPassword);
                }
                catch (Exception e)
                {
                    session.Log("{0}: UnregisterProvider failed: {1}", methodName, e.Message);
                }

                result = ActionResult.Success;
            }
            catch (Exception e)
            {
                session.Log("{0}", e);

                result = ActionResult.Failure;
            }

            session.Log("{0}: RESULT = {1}", methodName, result);

            session.Log("{0}: END", methodName);

            return(result);
        }
        public static ActionResult RegisterProvider(Session session)
        {
            ActionResult result;

            var methodName =
                MethodBase.GetCurrentMethod().Name;

            session.Log("{0}: BEGIN", methodName);

            try
            {
                var filePath =
                    session.CustomActionData["SessionData"];

                var sessionData =
                    SessionManager.Load(filePath);

                session.Log("{0}: Product Version = {1}", methodName, sessionData.InstallerVersion);

                session.Log("{0}: VCENTERSERVER = {1}", methodName, sessionData.vCenterServer);

                session.Log("{0}: VCENTERUSERNAME = {1}", methodName, sessionData.vCenterUserName);

                session.Log("{0}: THUMBPRINT = {1}", methodName, sessionData.Certificate);

                var providerConfig =
                    ConfigManager.GetConfiguration(sessionData.Application);

                providerConfig.Id = Host.Fqdn;

                providerConfig.Name = String.Format(Properties.Resource.VasaProviderNameTemplate, Host.Fqdn);

                if (providerConfig.Name.Length > 80)
                {
                    providerConfig.Name = providerConfig.Name.Substring(0, 80);
                }

                var credentials =
                    providerConfig.Credentials;

                credentials.Login =
                    Identifier.GenerateIdentifier(6);

                credentials.Password =
                    Identifier.GenerateIdentifier(8);

                ConfigManager.SaveConfiguration(providerConfig, sessionData.Application);

                var certificate =
                    CertificateManager.GetCertificate(sessionData.Certificate, StoreName.My);

                var provider =
                    (VasaProvider)RegistrationManager.RegisterProvider(providerConfig, certificate, sessionData.vCenterServer, sessionData.vCenterUserName, sessionData.vCenterPassword);

                session.Log("{0}: provider UniqueId: {1}", methodName, provider.UniqueId);
                session.Log("{0}: provider name: {1}", methodName, provider.Name);
                session.Log("{0}: provider description: {1}", methodName, provider.Description);
                session.Log("{0}: provider version: {1}", methodName, provider.Version);
                session.Log("{0}: provider ProviderId: {1}", methodName, provider.ProviderId);
                session.Log("{0}: provider url: {1}", methodName, provider.Url);

                sessionData.ProviderUniqueId = provider.UniqueId;

                sessionData.ProviderRegistered = true;

                SessionManager.Save(filePath, sessionData);

                try
                {
                    SessionManager.Save(VimDataKeyName, VimDataValueName, sessionData);
                }
                catch (Exception e)
                {
                    session.Log("{0}: SaveVimData failed: {1}", methodName, e.Message);
                }

                result = ActionResult.Success;
            }
            catch (Exception e)
            {
                session.Log("{0}", e);

                result = ActionResult.Failure;
            }

            session.Log("{0}: RESULT = {1}", methodName, result);

            session.Log("{0}: END", methodName);

            return(result);
        }
Exemplo n.º 12
0
        private static int EnsureHttpsCertificate(CommandOption exportPath, CommandOption password, CommandOption trust, IReporter reporter)
        {
            var now     = DateTimeOffset.Now;
            var manager = new CertificateManager();

            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && trust?.HasValue() == true)
            {
                reporter.Warn("Trusting the HTTPS development certificate was requested. If the certificate is not " +
                              "already trusted we will run the following command:" + Environment.NewLine +
                              "'sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain <<certificate>>'" +
                              Environment.NewLine + "This command might prompt you for your password to install the certificate " +
                              "on the system keychain.");
            }

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && trust?.HasValue() == true)
            {
                reporter.Warn("Trusting the HTTPS development certificate was requested. A confirmation prompt will be displayed " +
                              "if the certificate was not previously trusted. Click yes on the prompt to trust the certificate.");
            }

            var result = manager.EnsureAspNetCoreHttpsDevelopmentCertificate(
                now,
                now.Add(HttpsCertificateValidity),
                exportPath.Value(),
                trust == null ? false : trust.HasValue(),
                password.HasValue(),
                password.Value());

            reporter.Verbose(string.Join(Environment.NewLine, result.Diagnostics.Messages));

            switch (result.ResultCode)
            {
            case EnsureCertificateResult.Succeeded:
                reporter.Output("The HTTPS developer certificate was generated successfully.");
                if (exportPath.Value() != null)
                {
                    reporter.Verbose($"The certificate was exported to {Path.GetFullPath(exportPath.Value())}");
                }
                return(Success);

            case EnsureCertificateResult.ValidCertificatePresent:
                reporter.Output("A valid HTTPS certificate is already present.");
                if (exportPath.Value() != null)
                {
                    reporter.Verbose($"The certificate was exported to {Path.GetFullPath(exportPath.Value())}");
                }
                return(Success);

            case EnsureCertificateResult.ErrorCreatingTheCertificate:
                reporter.Error("There was an error creating the HTTPS developer certificate.");
                return(ErrorCreatingTheCertificate);

            case EnsureCertificateResult.ErrorSavingTheCertificateIntoTheCurrentUserPersonalStore:
                reporter.Error("There was an error saving the HTTPS developer certificate to the current user personal certificate store.");
                return(ErrorSavingTheCertificate);

            case EnsureCertificateResult.ErrorExportingTheCertificate:
                reporter.Warn("There was an error exporting HTTPS developer certificate to a file.");
                return(ErrorExportingTheCertificate);

            case EnsureCertificateResult.FailedToTrustTheCertificate:
                reporter.Warn("There was an error trusting HTTPS developer certificate.");
                return(ErrorTrustingTheCertificate);

            case EnsureCertificateResult.UserCancelledTrustStep:
                reporter.Warn("The user cancelled the trust step.");
                return(ErrorUserCancelledTrustPrompt);

            default:
                reporter.Error("Something went wrong. The HTTPS developer certificate could not be created.");
                return(CriticalError);
            }
        }
        /// <summary>
        ///     This is called when this proxy acts as a reverse proxy (like a real http server).
        ///     So for HTTPS requests we would start SSL negotiation right away without expecting a CONNECT request from client
        /// </summary>
        /// <param name="endPoint">The transparent endpoint.</param>
        /// <param name="clientConnection">The client connection.</param>
        /// <returns></returns>
        private async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClientConnection clientConnection)
        {
            var cancellationTokenSource = new CancellationTokenSource();
            var cancellationToken       = cancellationTokenSource.Token;

            var clientStream = new CustomBufferedStream(clientConnection.GetStream(), BufferSize);

            var clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize);

            try
            {
                var clientHelloInfo = await SslTools.PeekClientHello(clientStream, cancellationToken);

                bool   isHttps       = clientHelloInfo != null;
                string httpsHostName = null;

                if (isHttps)
                {
                    httpsHostName = clientHelloInfo.GetServerName() ?? endPoint.GenericCertificateName;

                    var args = new BeforeSslAuthenticateEventArgs(cancellationTokenSource)
                    {
                        SniHostName = httpsHostName
                    };

                    await endPoint.InvokeBeforeSslAuthenticate(this, args, ExceptionFunc);

                    if (cancellationTokenSource.IsCancellationRequested)
                    {
                        throw new Exception("Session was terminated by user.");
                    }

                    if (endPoint.DecryptSsl && args.DecryptSsl)
                    {
                        SslStream sslStream = null;

                        try
                        {
                            sslStream = new SslStream(clientStream);

                            string certName    = HttpHelper.GetWildCardDomainName(httpsHostName);
                            var    certificate = await CertificateManager.CreateCertificateAsync(certName);

                            // Successfully managed to authenticate the client using the fake certificate
                            await sslStream.AuthenticateAsServerAsync(certificate, false, SslProtocols.Tls, false);

                            // HTTPS server created - we can now decrypt the client's traffic
                            clientStream = new CustomBufferedStream(sslStream, BufferSize);

                            clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize);
                        }
                        catch (Exception e)
                        {
                            sslStream?.Dispose();
                            throw new ProxyConnectException(
                                      $"Could'nt authenticate client '{httpsHostName}' with fake certificate.", e, null);
                        }
                    }
                    else
                    {
                        // create new connection
                        var connection = new TcpClient(UpStreamEndPoint);
                        await connection.ConnectAsync(httpsHostName, endPoint.Port);

                        connection.ReceiveTimeout = ConnectionTimeOutSeconds * 1000;
                        connection.SendTimeout    = ConnectionTimeOutSeconds * 1000;

                        using (connection)
                        {
                            var serverStream = connection.GetStream();

                            int available = clientStream.Available;
                            if (available > 0)
                            {
                                // send the buffered data
                                var data = BufferPool.GetBuffer(BufferSize);

                                try
                                {
                                    // clientStream.Available sbould be at most BufferSize because it is using the same buffer size
                                    await clientStream.ReadAsync(data, 0, available, cancellationToken);

                                    await serverStream.WriteAsync(data, 0, available, cancellationToken);

                                    await serverStream.FlushAsync(cancellationToken);
                                }
                                finally
                                {
                                    BufferPool.ReturnBuffer(data);
                                }
                            }

                            ////var serverHelloInfo = await SslTools.PeekServerHello(serverStream);

                            await TcpHelper.SendRaw(clientStream, serverStream, BufferSize,
                                                    null, null, cancellationTokenSource, ExceptionFunc);
                        }
                    }
                }

                // HTTPS server created - we can now decrypt the client's traffic
                // Now create the request
                await HandleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter,
                                               cancellationTokenSource, isHttps?httpsHostName : null, null);
            }
            catch (ProxyException e)
            {
                OnException(clientStream, e);
            }
            catch (IOException e)
            {
                OnException(clientStream, new Exception("Connection was aborted", e));
            }
            catch (SocketException e)
            {
                OnException(clientStream, new Exception("Could not connect", e));
            }
            catch (Exception e)
            {
                OnException(clientStream, new Exception("Error occured in whilst handling the client", e));
            }
            finally
            {
                clientStream.Dispose();
                if (!cancellationTokenSource.IsCancellationRequested)
                {
                    cancellationTokenSource.Cancel();
                }
            }
        }
Exemplo n.º 14
0
        // Requests a certificate to be generated by the Bridge
        // If the certificate requested is for the local machine, for example if
        // server hostname is: foo.bar.com
        // local address is considered to be: 127.0.0.1, localhost, foo, foo.bar.com
        // Then we also install the certificate to the local machine, because it means we are about to run an HTTPS/SSL test against
        // this machine.
        // Otherwise, don't bother installing as the cert is for a remote machine.
        public override ResourceResponse Put(ResourceRequestContext context)
        {
            X509Certificate2 certificate;

            string subject;

            if (!context.Properties.TryGetValue(subjectKeyName, out subject) || string.IsNullOrWhiteSpace(subject))
            {
                throw new ArgumentException("When PUTting to this resource, specify an non-empty 'subject'", "context.Properties");
            }

            string subjectAlternativeNamesString;

            string[] subjectAlternativeNames;
            if (context.Properties.TryGetValue(subjectAlternativeNamesKeyName, out subjectAlternativeNamesString) && !string.IsNullOrWhiteSpace(subjectAlternativeNamesString))
            {
                // Subject Alt Names specified here
                subjectAlternativeNames = subjectAlternativeNamesString.Split(',');
            }
            else
            {
                // If no SAN is specified, then we want to by default set the SAN to the subject
                subjectAlternativeNames = new string[1] {
                    subject
                };
            }

            bool isLocal = IsLocalMachineResource(subject);

            lock (s_certificateResourceLock)
            {
                if (!s_createdCertsBySubject.TryGetValue(subject, out certificate))
                {
                    CertificateGenerator generator = CertificateResourceHelpers.GetCertificateGeneratorInstance(context.BridgeConfiguration);

                    if (isLocal)
                    {
                        // If we're PUTting a cert that refers to a hostname local to the bridge,
                        // return the Local Machine cert that CertificateManager caches and add it to the collection
                        //
                        // If we are receiving a PUT to the same endpoint address as the bridge server, it means that
                        // a test is going to be run on this box
                        //
                        // In keeping with the semantic of these classes, we must PUT before we can GET a cert
                        certificate = CertificateManager.CreateAndInstallLocalMachineCertificates(generator);
                    }
                    else
                    {
                        CertificateCreationSettings certificateCreationSettings = new CertificateCreationSettings()
                        {
                            FriendlyName            = "WCF Bridge - MachineCertificateResource",
                            Subject                 = subject,
                            SubjectAlternativeNames = subjectAlternativeNames
                        };
                        certificate = generator.CreateMachineCertificate(certificateCreationSettings).Certificate;
                    }

                    X509Certificate2 dummy;
                    if (!isLocal || !s_createdCertsByThumbprint.TryGetValue(certificate.Thumbprint, out dummy))
                    {
                        // when isLocal, it's possible for there to be > 1 subject sharing the same thumbprint
                        // in this case, we only cache the first isLocal subject, the rest we don't cache
                        s_createdCertsBySubject.Add(subject, certificate);
                        s_createdCertsByThumbprint.Add(certificate.Thumbprint, certificate);
                    }
                }
            }

            ResourceResponse response = new ResourceResponse();

            response.Properties.Add(thumbprintKeyName, certificate.Thumbprint);
            response.Properties.Add(isLocalKeyName, isLocal.ToString());

            return(response);
        }
 private string CreateCertificate(long userid, string password, string doc1, string doc2, string doc3)
 {
     string ret = string.Empty;
     using (CertificateManager mgr = new CertificateManager(userid, password))
     {
         if (!string.IsNullOrEmpty(doc1))
             mgr.AddDocument(doc1);
         if (!string.IsNullOrEmpty(doc2))
             mgr.AddDocument(doc2);
         if (!string.IsNullOrEmpty(doc3))
             mgr.AddDocument(doc3);
         mgr.CreateCertificate(string.Format("ID{0:D10}.cer", userid));
         ret = mgr.CertificateFilename;
     }
     return ret;
 }
Exemplo n.º 16
0
        /// <summary>
        /// This is called when client is aware of proxy
        /// So for HTTPS requests client would send CONNECT header to negotiate a secure tcp tunnel via proxy
        /// </summary>
        /// <param name="endPoint"></param>
        /// <param name="tcpClient"></param>
        /// <returns></returns>
        private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClient tcpClient)
        {
            var disposed = false;

            var clientStream = new CustomBufferedStream(tcpClient.GetStream(), BufferSize);

            var clientStreamReader = new CustomBinaryReader(clientStream, BufferSize);
            var clientStreamWriter = new StreamWriter(clientStream)
            {
                NewLine = ProxyConstants.NewLine
            };

            Uri httpRemoteUri;

            try
            {
                //read the first line HTTP command
                var httpCmd = await clientStreamReader.ReadLineAsync();

                if (string.IsNullOrEmpty(httpCmd))
                {
                    return;
                }

                //break up the line into three components (method, remote URL & Http Version)
                var httpCmdSplit = httpCmd.Split(ProxyConstants.SpaceSplit, 3);

                //Find the request Verb
                var httpVerb = httpCmdSplit[0].ToUpper();

                httpRemoteUri = httpVerb == "CONNECT" ? new Uri("http://" + httpCmdSplit[1]) : new Uri(httpCmdSplit[1]);

                //parse the HTTP version
                var version = HttpHeader.Version11;
                if (httpCmdSplit.Length == 3)
                {
                    var httpVersion = httpCmdSplit[2].Trim();

                    if (string.Equals(httpVersion, "HTTP/1.0", StringComparison.OrdinalIgnoreCase))
                    {
                        version = HttpHeader.Version10;
                    }
                }

                //filter out excluded host names
                bool excluded = false;

                if (endPoint.ExcludedHttpsHostNameRegex != null)
                {
                    excluded = endPoint.ExcludedHttpsHostNameRegexList.Any(x => x.IsMatch(httpRemoteUri.Host));
                }

                if (endPoint.IncludedHttpsHostNameRegex != null)
                {
                    excluded = !endPoint.IncludedHttpsHostNameRegexList.Any(x => x.IsMatch(httpRemoteUri.Host));
                }

                List <HttpHeader> connectRequestHeaders = null;

                //Client wants to create a secure tcp tunnel (its a HTTPS request)
                if (httpVerb == "CONNECT" && !excluded &&
                    endPoint.RemoteHttpsPorts.Contains(httpRemoteUri.Port))
                {
                    httpRemoteUri         = new Uri("https://" + httpCmdSplit[1]);
                    connectRequestHeaders = new List <HttpHeader>();
                    string tmpLine;
                    while (!string.IsNullOrEmpty(tmpLine = await clientStreamReader.ReadLineAsync()))
                    {
                        var header = tmpLine.Split(ProxyConstants.ColonSplit, 2);

                        var newHeader = new HttpHeader(header[0], header[1]);
                        connectRequestHeaders.Add(newHeader);
                    }

                    if (await CheckAuthorization(clientStreamWriter, connectRequestHeaders) == false)
                    {
                        return;
                    }

                    await WriteConnectResponse(clientStreamWriter, version);

                    SslStream sslStream = null;

                    try
                    {
                        sslStream = new SslStream(clientStream);

                        var certName = HttpHelper.GetWildCardDomainName(httpRemoteUri.Host);

                        var certificate = endPoint.GenericCertificate ??
                                          CertificateManager.CreateCertificate(certName, false);

                        //Successfully managed to authenticate the client using the fake certificate
                        await sslStream.AuthenticateAsServerAsync(certificate, false,
                                                                  SupportedSslProtocols, false);

                        //HTTPS server created - we can now decrypt the client's traffic
                        clientStream = new CustomBufferedStream(sslStream, BufferSize);

                        clientStreamReader.Dispose();
                        clientStreamReader = new CustomBinaryReader(clientStream, BufferSize);
                        clientStreamWriter = new StreamWriter(clientStream)
                        {
                            NewLine = ProxyConstants.NewLine
                        };
                    }
                    catch
                    {
                        sslStream?.Dispose();
                        return;
                    }

                    //Now read the actual HTTPS request line
                    httpCmd = await clientStreamReader.ReadLineAsync();
                }
                //Sorry cannot do a HTTPS request decrypt to port 80 at this time
                else if (httpVerb == "CONNECT")
                {
                    //Siphon out CONNECT request headers
                    await clientStreamReader.ReadAndIgnoreAllLinesAsync();

                    //write back successfull CONNECT response
                    await WriteConnectResponse(clientStreamWriter, version);

                    await TcpHelper.SendRaw(this,
                                            httpRemoteUri.Host, httpRemoteUri.Port,
                                            null, version, null,
                                            false,
                                            clientStream, tcpConnectionFactory);

                    return;
                }

                //Now create the request
                disposed = await HandleHttpSessionRequest(tcpClient, httpCmd, clientStream, clientStreamReader, clientStreamWriter,
                                                          httpRemoteUri.Scheme == Uri.UriSchemeHttps?httpRemoteUri.Host : null, endPoint,
                                                          connectRequestHeaders);
            }
            catch (Exception e)
            {
                ExceptionFunc(new Exception("Error whilst authorizing request", e));
            }
            finally
            {
                if (!disposed)
                {
                    Dispose(clientStream, clientStreamReader, clientStreamWriter, null);
                }
            }
        }
Exemplo n.º 17
0
        public async Task TestCertCleanupAtExpiry()
        {
            // create and store a number of test certificates
            var cert1 = CreateAndStoreTestCertificate("cert-test1.example.com", new DateTime(1935, 01, 01), new DateTime(1935, 03, 01));
            var cert2 = CreateAndStoreTestCertificate("cert-test2.example.com", new DateTime(1934, 01, 01), new DateTime(1934, 03, 01));
            var cert3 = CreateAndStoreTestCertificate("cert-test3.example.com", new DateTime(1936, 01, 01), new DateTime(1936, 07, 01));
            var cert4 = CreateAndStoreTestCertificate("cert-test4.example.com", new DateTime(1936, 01, 01), new DateTime(1936, 05, 15));

            // create test site for bindings, add bindings
            var iisManager = new ServerProviderIIS();

            var testSiteDomain = "cert-test.example.com";

            if (await iisManager.SiteExists(testSiteDomain))
            {
                await iisManager.DeleteSite(testSiteDomain);
            }
            var site = await iisManager.CreateSite(testSiteDomain, testSiteDomain, PrimaryIISRoot, "DefaultAppPool");

            await iisManager.AddOrUpdateSiteBinding(
                new Models.BindingInfo
            {
                SiteId           = site.Id.ToString(),
                Host             = testSiteDomain,
                CertificateHash  = cert2.Thumbprint,
                CertificateStore = "MY",
                IsSNIEnabled     = false,
                Port             = 443,
                Protocol         = "https"
            }, addNew : true
                );

            // run cleanup process, removes certs which have expired for over a month and have
            // [Certify] in the friendly name
            CertificateManager.PerformCertificateStoreCleanup(Models.CertificateCleanupMode.AfterExpiry, new DateTime(1936, 06, 01), null, null);

            // check the correct certificates have been removed
            try
            {
                // check cert test 1 removed (expired)
                Assert.IsFalse(CertificateManager.IsCertificateInStore(cert1), "Cert 1 Should Be Removed");

                // check cert test 2 removed (expired)
                Assert.IsFalse(CertificateManager.IsCertificateInStore(cert2), "Cert 2 Should Be Removed");

                // check cert test 3 exists (not expired)
                Assert.IsTrue(CertificateManager.IsCertificateInStore(cert3), "Cert 3 Should Not Be Removed");

                // check cert test 4 removed (expired, but for less than 1 month)
                Assert.IsFalse(CertificateManager.IsCertificateInStore(cert4), "Cert 4 Should  Be Removed");
            }
            finally
            {
                // clean up after test
                await iisManager.DeleteSite(site.Name);

                CertificateManager.RemoveCertificate(cert1);
                CertificateManager.RemoveCertificate(cert2);
                CertificateManager.RemoveCertificate(cert3);
                CertificateManager.RemoveCertificate(cert4);
            }
        }
Exemplo n.º 18
0
        public async Task TestChallengeRequestHttp01IDN()
        {
            var testIDNDomain = "å🤔." + PrimaryTestDomain;

            var testSANList = new string[]
            {
                "xyå." + PrimaryTestDomain,
                "xyå.xyå" + PrimaryTestDomain
            };

            if (await iisManager.SiteExists(testIDNDomain))
            {
                await iisManager.DeleteSite(testIDNDomain);
            }

            var dummyManagedCertificate = new ManagedCertificate
            {
                Id             = Guid.NewGuid().ToString(),
                Name           = testIDNDomain,
                UseStagingMode = true,
                DomainOptions  = new ObservableCollection <DomainOption> {
                    new DomainOption {
                        Domain = testIDNDomain, IsManualEntry = true, IsPrimaryDomain = true, IsSelected = true
                    }
                },
                RequestConfig = new CertRequestConfig
                {
                    PrimaryDomain = testIDNDomain,
                    Challenges    = new ObservableCollection <CertRequestChallengeConfig>(
                        new List <CertRequestChallengeConfig>
                    {
                        new CertRequestChallengeConfig {
                            ChallengeType = "http-01"
                        }
                    }),
                    PerformAutoConfig                = true,
                    PerformAutomatedCertBinding      = true,
                    PerformChallengeFileCopy         = true,
                    PerformExtensionlessConfigChecks = true,
                    WebsiteRootPath = testSitePath
                },
                ItemType = ManagedCertificateType.SSL_ACME
            };


            try
            {
                var site = await iisManager.CreateSite(testIDNDomain, testIDNDomain, testSitePath, "DefaultAppPool", port : testSiteHttpPort);

                dummyManagedCertificate.GroupId = site.Id.ToString();

                Assert.AreEqual(site.Name, testIDNDomain);


                var result = await certifyManager.PerformCertificateRequest(_log, dummyManagedCertificate);

                //ensure cert request was successful
                Assert.IsTrue(result.IsSuccess, "Certificate Request Not Completed. Ensure http site is accessible.");

                //have cert file details
                Assert.IsNotNull(dummyManagedCertificate.CertificatePath);

                var fileExists = System.IO.File.Exists(dummyManagedCertificate.CertificatePath);
                Assert.IsTrue(fileExists);

                //check cert is correct
                var certInfo = CertificateManager.LoadCertificate(dummyManagedCertificate.CertificatePath);
                Assert.IsNotNull(certInfo);

                var isRecentlyCreated = Math.Abs((DateTime.UtcNow - certInfo.NotBefore).TotalDays) < 2;
                Assert.IsTrue(isRecentlyCreated);

                var expiresInFuture = (certInfo.NotAfter - DateTime.UtcNow).TotalDays >= 89;
                Assert.IsTrue(expiresInFuture);
            }
            finally
            {
                await certifyManager.DeleteManagedCertificate(dummyManagedCertificate.Id);

                await iisManager.DeleteSite(testIDNDomain);
            }
        }
Exemplo n.º 19
0
        public async Task TestCertCleanupByThumbprint()
        {
            // create and store a number of test certificates
            var cert1 = CreateAndStoreTestCertificate("cert-test1.example.com", new DateTime(1935, 01, 01), new DateTime(1935, 03, 01));
            var cert2 = CreateAndStoreTestCertificate("cert-test2.example.com", new DateTime(1934, 01, 01), new DateTime(1934, 03, 01));
            var cert3 = CreateAndStoreTestCertificate("cert-test2.example.com", new DateTime(1936, 01, 01), new DateTime(1938, 03, 01));

            // create test site for bindings, add bindings
            var iisManager = new ServerProviderIIS();

            var testSiteDomain = "cert-test.example.com";

            if (await iisManager.SiteExists(testSiteDomain))
            {
                await iisManager.DeleteSite(testSiteDomain);
            }
            var site = await iisManager.CreateSite(testSiteDomain, testSiteDomain, PrimaryIISRoot, "DefaultAppPool");

            await iisManager.AddOrUpdateSiteBinding(
                new Models.BindingInfo
            {
                SiteId           = site.Id.ToString(),
                Host             = testSiteDomain,
                CertificateHash  = cert2.Thumbprint,
                CertificateStore = "MY",
                IsSNIEnabled     = false,
                Port             = 443,
                Protocol         = "https"
            }, addNew : true
                );

            // run cleanup process, removes certs by name, excluding the given thumbprints
            CertificateManager.PerformCertificateStoreCleanup(
                Models.CertificateCleanupMode.AfterRenewal,
                new DateTime(1936, 06, 01),
                matchingName: "cert-test2.example.com",
                excludedThumbprints: new List <string> {
                cert3.Thumbprint
            }
                );

            // check the correct certificates have been removed
            try
            {
                // check cert test 1 not removed (does not match)
                Assert.IsTrue(CertificateManager.IsCertificateInStore(cert1), "Cert 1 Should Not Be Removed");

                // check cert test 2 removed (does match)
                Assert.IsFalse(CertificateManager.IsCertificateInStore(cert2), "Cert 2 Should Be Removed");

                // check cert test 3 exists (matches but is excluded by thumbprint)
                Assert.IsTrue(CertificateManager.IsCertificateInStore(cert3), "Cert 3 Should Not Be Removed");
            }
            finally
            {
                // clean up after test
                await iisManager.DeleteSite(site.Name);

                CertificateManager.RemoveCertificate(cert1);
                CertificateManager.RemoveCertificate(cert2);
                CertificateManager.RemoveCertificate(cert3);
            }
        }
Exemplo n.º 20
0
        public async Task TestRequestWithRenewal()
        {
            var site = await iisManager.GetIISSiteById(_siteId);

            Assert.AreEqual(site.Name, testSiteName);

            var testDomain     = Guid.NewGuid().ToString().Substring(0, 6) + "." + PrimaryTestDomain;
            var newManagedCert = new ManagedCertificate
            {
                Id                 = Guid.NewGuid().ToString(),
                Name               = testSiteName,
                GroupId            = site.Id.ToString(),
                UseStagingMode     = true,
                IncludeInAutoRenew = true,
                RequestConfig      = new CertRequestConfig
                {
                    PrimaryDomain                    = testDomain,
                    PerformAutoConfig                = true,
                    PerformAutomatedCertBinding      = true,
                    PerformChallengeFileCopy         = true,
                    PerformExtensionlessConfigChecks = true,
                    WebsiteRootPath                  = testSitePath,
                    Challenges = new ObservableCollection <CertRequestChallengeConfig> {
                        new CertRequestChallengeConfig {
                            ChallengeType          = "dns-01",
                            ChallengeProvider      = "DNS01.API.Cloudflare",
                            ChallengeCredentialKey = _testCredStorageKey,
                            ZoneId = ConfigSettings["Cloudflare_ZoneId"]
                        }
                    },
                    DeploymentSiteOption = DeploymentOption.NoDeployment
                },
                ItemType = ManagedCertificateType.SSL_ACME
            };

            var result = await certifyManager.PerformCertificateRequest(_log, newManagedCert);

            //ensure cert request was successful
            Assert.IsTrue(result.IsSuccess, "Certificate Request Not Completed");

            //check details of cert, subject alternative name should include domain and expiry must be great than 89 days in the future
            var managedCertificate = await certifyManager.GetManagedCertificate(newManagedCert.Id);

            //emsure we have a new managed site
            Assert.IsNotNull(managedCertificate);

            //have cert file details
            Assert.IsNotNull(managedCertificate.CertificatePath);

            var fileExists = System.IO.File.Exists(managedCertificate.CertificatePath);

            Assert.IsTrue(fileExists);

            //check cert is correct
            var certInfo = CertificateManager.LoadCertificate(managedCertificate.CertificatePath);

            Assert.IsNotNull(certInfo);

            var isRecentlyCreated = Math.Abs((DateTime.UtcNow - certInfo.NotBefore).TotalDays) < 2;

            Assert.IsTrue(isRecentlyCreated);

            var expiresInFuture = (certInfo.NotAfter - DateTime.UtcNow).TotalDays >= 89;

            Assert.IsTrue(expiresInFuture);


            // test a renewal for this managed cert

            var targets = new List <string> {
                managedCertificate.Id
            };

            var results = await certifyManager.PerformRenewalAllManagedCertificates(
                new RenewalSettings
            {
                TargetManagedCertificates = targets,
                Mode = RenewalMode.All
            }
                , null);

            Assert.AreEqual(1, results.Count);

            Assert.IsTrue(results.All(r => r.IsSuccess), "All results should be success");

            // remove managed site
            await certifyManager.DeleteManagedCertificate(managedCertificate.Id);

            // cleanup certificate
            CertificateManager.RemoveCertificate(certInfo);
        }
Exemplo n.º 21
0
        public async Task TestBindingMatch()
        {
            // create test site with mix of hostname and IP only bindings
            var testStr = "abc123";

            PrimaryTestDomain = $"test-{testStr}." + PrimaryTestDomain;

            string testBindingSiteName = "TestAllBinding_" + testStr;

            var testSiteDomain = "test" + testStr + "." + PrimaryTestDomain;

            if (await iisManager.SiteExists(testBindingSiteName))
            {
                await iisManager.DeleteSite(testBindingSiteName);
            }

            // create site with IP all unassigned, no hostname
            var site = await iisManager.CreateSite(testBindingSiteName, "", PrimaryIISRoot, "DefaultAppPool", port : testSiteHttpPort);

            // add another hostname binding (matching cert and not matching cert)
            List <string> testDomains = new List <string> {
                testSiteDomain, "label1." + testSiteDomain, "nested.label." + testSiteDomain
            };
            await iisManager.AddSiteBindings(site.Id.ToString(), testDomains, testSiteHttpPort);

            // get fresh instance of site since updates
            site = await iisManager.GetIISSiteById(site.Id.ToString());

            var bindingsBeforeApply = site.Bindings.ToList();

            Assert.AreEqual(site.Name, testBindingSiteName);

            var dummyCertPath      = Environment.CurrentDirectory + "\\Assets\\dummycert.pfx";
            var managedCertificate = new ManagedCertificate
            {
                Id            = Guid.NewGuid().ToString(),
                Name          = testSiteName,
                ServerSiteId  = site.Id.ToString(),
                RequestConfig = new CertRequestConfig
                {
                    PrimaryDomain = testSiteDomain,
                    Challenges    = new ObservableCollection <CertRequestChallengeConfig>(
                        new List <CertRequestChallengeConfig>
                    {
                        new CertRequestChallengeConfig {
                            ChallengeType = "http-01"
                        }
                    }),
                    PerformAutoConfig                = true,
                    PerformAutomatedCertBinding      = true,
                    PerformChallengeFileCopy         = true,
                    PerformExtensionlessConfigChecks = true,
                    WebsiteRootPath                  = testSitePath,
                    DeploymentSiteOption             = DeploymentOption.SingleSite,
                    DeploymentBindingMatchHostname   = true,
                    DeploymentBindingBlankHostname   = true,
                    DeploymentBindingReplacePrevious = true,
                    SubjectAlternativeNames          = new string[] { testSiteDomain, "label1." + testSiteDomain }
                },
                ItemType        = ManagedCertificateType.SSL_LetsEncrypt_LocalIIS,
                CertificatePath = dummyCertPath
            };

            var actions = await new BindingDeploymentManager().StoreAndDeployManagedCertificate(
                iisManager.GetDeploymentTarget(),
                managedCertificate, dummyCertPath,
                false,
                false);

            foreach (var a in actions)
            {
                System.Console.WriteLine(a.Description);
            }
            // get cert info to compare hash
            var certInfo = CertificateManager.LoadCertificate(managedCertificate.CertificatePath);

            // check IIS site bindings
            site = await iisManager.GetIISSiteById(site.Id.ToString());

            var finalBindings = site.Bindings.ToList();

            Assert.IsTrue(bindingsBeforeApply.Count < finalBindings.Count, "Should have new bindings");

            try
            {
                // check we have the new bindings we expected

                // blank hostname binding
                var testBinding = finalBindings.FirstOrDefault(b => b.Host == "" && b.Protocol == "https");
                Assert.IsTrue(IsCertHashEqual(testBinding.CertificateHash, certInfo.GetCertHash()), "Blank hostname binding should be added and have certificate set");

                // TODO: testDomains includes matches and not matches to test
                foreach (var d in testDomains)
                {
                    // check san domain now has an https binding
                    testBinding = finalBindings.FirstOrDefault(b => b.Host == d && b.Protocol == "https");
                    if (!d.StartsWith("nested."))
                    {
                        Assert.IsNotNull(testBinding);
                        Assert.IsTrue(IsCertHashEqual(testBinding.CertificateHash, certInfo.GetCertHash()), "hostname binding should be added and have certificate set");
                    }
                    else
                    {
                        Assert.IsNull(testBinding, "nested binding should be null");
                    }
                }

                // check existing bindings have been updated as expected

                /*foreach (var b in finalBindings)
                 * {
                 *  if (b.Protocol == "https")
                 *  {
                 *      // check this item is one we should have included (is matching domain or has
                 *      // no hostname)
                 *      bool shouldBeIncluded = false;
                 *
                 *      if (!String.IsNullOrEmpty(b.Host))
                 *      {
                 *          if (testDomains.Contains(b.Host))
                 *          {
                 *              shouldBeIncluded = true;
                 *          }
                 *      }
                 *      else
                 *      {
                 *          shouldBeIncluded = true;
                 *      }
                 *
                 *      bool isCertMatch = StructuralComparisons.StructuralEqualityComparer.Equals(b.CertificateHash, certInfo.GetCertHash());
                 *
                 *      if (shouldBeIncluded)
                 *      {
                 *          Assert.IsTrue(isCertMatch, "Binding should have been updated with cert hash but was not.");
                 *      }
                 *      else
                 *      {
                 *          Assert.IsFalse(isCertMatch, "Binding should not have been updated with cert hash but was.");
                 *      }
                 *  }
                 * }*/
            }
            finally
            {
                // clean up IIS either way
                await iisManager.DeleteSite(testBindingSiteName);

                if (certInfo != null)
                {
                    CertificateManager.RemoveCertificate(certInfo);
                }
            }
        }
Exemplo n.º 22
0
        public async Task TestChallengeRequestHttp01()
        {
            var site = await iisManager.GetIISSiteById(_siteId);

            Assert.AreEqual(site.Name, testSiteName);

            var dummyManagedCertificate = new ManagedCertificate
            {
                Id             = Guid.NewGuid().ToString(),
                Name           = testSiteName,
                GroupId        = site.Id.ToString(),
                UseStagingMode = true,
                RequestConfig  = new CertRequestConfig
                {
                    PrimaryDomain = testSiteDomain,
                    Challenges    = new ObservableCollection <CertRequestChallengeConfig>(
                        new List <CertRequestChallengeConfig>
                    {
                        new CertRequestChallengeConfig {
                            ChallengeType = "http-01"
                        }
                    }),
                    PerformAutoConfig                = true,
                    PerformAutomatedCertBinding      = true,
                    PerformChallengeFileCopy         = true,
                    PerformExtensionlessConfigChecks = true,
                    WebsiteRootPath = testSitePath
                },
                ItemType = ManagedCertificateType.SSL_ACME
            };

            var result = await certifyManager.PerformCertificateRequest(null, dummyManagedCertificate);

            //ensure cert request was successful
            Assert.IsTrue(result.IsSuccess, "Certificate Request Not Completed");

            //check details of cert, subject alternative name should include domain and expiry must be great than 89 days in the future
            var managedCertificates = await certifyManager.GetManagedCertificates();

            var managedCertificate = managedCertificates.FirstOrDefault(m => m.Id == dummyManagedCertificate.Id);

            //emsure we have a new managed site
            Assert.IsNotNull(managedCertificate);

            //have cert file details
            Assert.IsNotNull(managedCertificate.CertificatePath);

            var fileExists = System.IO.File.Exists(managedCertificate.CertificatePath);

            Assert.IsTrue(fileExists);

            //check cert is correct
            var certInfo = CertificateManager.LoadCertificate(managedCertificate.CertificatePath);

            Assert.IsNotNull(certInfo);

            var isRecentlyCreated = Math.Abs((DateTime.UtcNow - certInfo.NotBefore).TotalDays) < 2;

            Assert.IsTrue(isRecentlyCreated);

            var expiresInFuture = (certInfo.NotAfter - DateTime.UtcNow).TotalDays >= 89;

            Assert.IsTrue(expiresInFuture);

            // remove managed site
            await certifyManager.DeleteManagedCertificate(managedCertificate.Id);
        }
Exemplo n.º 23
0
 public FileService(IStorage storage)
 {
     _storage      = storage;
     _certificator = new CertificateManager();
 }
Exemplo n.º 24
0
        /// <summary>
        ///     This is called when client is aware of proxy
        ///     So for HTTPS requests client would send CONNECT header to negotiate a secure tcp tunnel via proxy
        /// </summary>
        /// <param name="endPoint">The explicit endpoint.</param>
        /// <param name="clientConnection">The client connection.</param>
        /// <returns>The task.</returns>
        private async Task handleClient(ExplicitProxyEndPoint endPoint, TcpClientConnection clientConnection)
        {
            var cancellationTokenSource = new CancellationTokenSource();
            var cancellationToken       = cancellationTokenSource.Token;

            var clientStream       = new CustomBufferedStream(clientConnection.GetStream(), BufferPool, BufferSize);
            var clientStreamWriter = new HttpResponseWriter(clientStream, BufferPool, BufferSize);

            Task <TcpServerConnection> prefetchConnectionTask = null;
            bool closeServerConnection = false;
            bool calledRequestHandler  = false;

            SslStream sslStream = null;

            try
            {
                string connectHostname = null;
                TunnelConnectSessionEventArgs connectArgs = null;

                // Client wants to create a secure tcp tunnel (probably its a HTTPS or Websocket request)
                if (await HttpHelper.IsConnectMethod(clientStream, BufferPool, BufferSize, cancellationToken) == 1)
                {
                    // read the first line HTTP command
                    string httpCmd = await clientStream.ReadLineAsync(cancellationToken);

                    if (string.IsNullOrEmpty(httpCmd))
                    {
                        return;
                    }

                    Request.ParseRequestLine(httpCmd, out string _, out string httpUrl, out var version);

                    var httpRemoteUri = new Uri("http://" + httpUrl);
                    connectHostname = httpRemoteUri.Host;

                    var connectRequest = new ConnectRequest
                    {
                        RequestUri  = httpRemoteUri,
                        OriginalUrl = httpUrl,
                        HttpVersion = version
                    };

                    await HeaderParser.ReadHeaders(clientStream, connectRequest.Headers, cancellationToken);

                    connectArgs = new TunnelConnectSessionEventArgs(this, endPoint, connectRequest,
                                                                    cancellationTokenSource);
                    connectArgs.ProxyClient.Connection   = clientConnection;
                    connectArgs.ProxyClient.ClientStream = clientStream;

                    await endPoint.InvokeBeforeTunnelConnectRequest(this, connectArgs, ExceptionFunc);

                    // filter out excluded host names
                    bool decryptSsl = endPoint.DecryptSsl && connectArgs.DecryptSsl;

                    if (connectArgs.DenyConnect)
                    {
                        if (connectArgs.HttpClient.Response.StatusCode == 0)
                        {
                            connectArgs.HttpClient.Response = new Response
                            {
                                HttpVersion       = HttpHeader.Version11,
                                StatusCode        = (int)HttpStatusCode.Forbidden,
                                StatusDescription = "Forbidden"
                            };
                        }

                        // send the response
                        await clientStreamWriter.WriteResponseAsync(connectArgs.HttpClient.Response,
                                                                    cancellationToken : cancellationToken);

                        return;
                    }

                    if (await checkAuthorization(connectArgs) == false)
                    {
                        await endPoint.InvokeBeforeTunnelConnectResponse(this, connectArgs, ExceptionFunc);

                        // send the response
                        await clientStreamWriter.WriteResponseAsync(connectArgs.HttpClient.Response,
                                                                    cancellationToken : cancellationToken);

                        return;
                    }

                    // write back successful CONNECT response
                    var response = ConnectResponse.CreateSuccessfulConnectResponse(version);

                    // Set ContentLength explicitly to properly handle HTTP 1.0
                    response.ContentLength = 0;
                    response.Headers.FixProxyHeaders();
                    connectArgs.HttpClient.Response = response;

                    await clientStreamWriter.WriteResponseAsync(response, cancellationToken : cancellationToken);

                    var clientHelloInfo = await SslTools.PeekClientHello(clientStream, BufferPool, cancellationToken);

                    bool isClientHello = clientHelloInfo != null;
                    if (isClientHello)
                    {
                        connectRequest.TunnelType      = TunnelType.Https;
                        connectRequest.ClientHelloInfo = clientHelloInfo;
                    }

                    await endPoint.InvokeBeforeTunnelConnectResponse(this, connectArgs, ExceptionFunc, isClientHello);

                    if (decryptSsl && isClientHello)
                    {
                        connectRequest.RequestUri = new Uri("https://" + httpUrl);

                        bool http2Supported = false;

                        var alpn = clientHelloInfo.GetAlpn();
                        if (alpn != null && alpn.Contains(SslApplicationProtocol.Http2))
                        {
                            // test server HTTP/2 support
                            try
                            {
                                // todo: this is a hack, because Titanium does not support HTTP protocol changing currently
                                var connection = await tcpConnectionFactory.GetServerConnection(this, connectArgs,
                                                                                                isConnect : true, applicationProtocols : SslExtensions.Http2ProtocolAsList,
                                                                                                noCache : true, cancellationToken : cancellationToken);

                                http2Supported = connection.NegotiatedApplicationProtocol ==
                                                 SslApplicationProtocol.Http2;
                                //release connection back to pool instead of closing when connection pool is enabled.
                                await tcpConnectionFactory.Release(connection, true);
                            }
                            catch (Exception)
                            {
                                // ignore
                            }
                        }

                        if (EnableTcpServerConnectionPrefetch)
                        {
                            IPAddress[] ipAddresses = null;
                            try
                            {
                                //make sure the host can be resolved before creating the prefetch task
                                ipAddresses = await Dns.GetHostAddressesAsync(connectArgs.HttpClient.Request.RequestUri.Host);
                            }
                            catch (SocketException) { }

                            if (ipAddresses != null && ipAddresses.Length > 0)
                            {
                                //don't pass cancellation token here
                                //it could cause floating server connections when client exits
                                prefetchConnectionTask = tcpConnectionFactory.GetServerConnection(this, connectArgs,
                                                                                                  isConnect: true, applicationProtocols: null, noCache: false,
                                                                                                  cancellationToken: CancellationToken.None);
                            }
                        }

                        X509Certificate2 certificate = null;
                        try
                        {
                            sslStream = new MySslStream(clientStream, false);

                            string certName = HttpHelper.GetWildCardDomainName(connectHostname);
                            certificate = endPoint.GenericCertificate ??
                                          await CertificateManager.CreateServerCertificate(certName);

                            // Successfully managed to authenticate the client using the fake certificate
                            var options = new SslServerAuthenticationOptions();
                            if (EnableHttp2 && http2Supported)
                            {
                                options.ApplicationProtocols = clientHelloInfo.GetAlpn();
                                if (options.ApplicationProtocols == null || options.ApplicationProtocols.Count == 0)
                                {
                                    options.ApplicationProtocols = SslExtensions.Http11ProtocolAsList;
                                }
                            }

                            options.ServerCertificate              = certificate;
                            options.ClientCertificateRequired      = false;
                            options.EnabledSslProtocols            = SupportedSslProtocols;
                            options.CertificateRevocationCheckMode = X509RevocationMode.NoCheck;
                            await sslStream.AuthenticateAsServerAsync(options, cancellationToken);

#if NETCOREAPP2_1
                            clientConnection.NegotiatedApplicationProtocol = sslStream.NegotiatedApplicationProtocol;
#endif

                            // HTTPS server created - we can now decrypt the client's traffic
                            clientStream       = new CustomBufferedStream(new StreamWrapper(sslStream), BufferPool, BufferSize);
                            clientStreamWriter = new HttpResponseWriter(clientStream, BufferPool, BufferSize);
                        }
                        catch (Exception e)
                        {
                            var certName = certificate?.GetNameInfo(X509NameType.SimpleName, false);
                            throw new ProxyConnectException(
                                      $"Couldn't authenticate host '{connectHostname}' with certificate '{certName}'.", e, connectArgs);
                        }

                        if (await HttpHelper.IsConnectMethod(clientStream, BufferPool, BufferSize, cancellationToken) == -1)
                        {
                            decryptSsl = false;
                        }

                        if (!decryptSsl)
                        {
                            await tcpConnectionFactory.Release(prefetchConnectionTask, true);

                            prefetchConnectionTask = null;
                        }
                    }

                    if (cancellationTokenSource.IsCancellationRequested)
                    {
                        throw new Exception("Session was terminated by user.");
                    }

                    // Hostname is excluded or it is not an HTTPS connect
                    if (!decryptSsl || !isClientHello)
                    {
                        if (!isClientHello)
                        {
                            connectRequest.TunnelType = TunnelType.Websocket;
                        }

                        // create new connection to server.
                        // If we detected that client tunnel CONNECTs without SSL by checking for empty client hello then
                        // this connection should not be HTTPS.
                        var connection = await tcpConnectionFactory.GetServerConnection(this, connectArgs,
                                                                                        isConnect : true, applicationProtocols : SslExtensions.Http2ProtocolAsList,
                                                                                        noCache : true, cancellationToken : cancellationToken);

                        try
                        {
                            if (isClientHello)
                            {
                                int available = clientStream.Available;
                                if (available > 0)
                                {
                                    // send the buffered data
                                    var data = BufferPool.GetBuffer(BufferSize);

                                    try
                                    {
                                        // clientStream.Available should be at most BufferSize because it is using the same buffer size
                                        await clientStream.ReadAsync(data, 0, available, cancellationToken);

                                        await connection.StreamWriter.WriteAsync(data, 0, available, true, cancellationToken);
                                    }
                                    finally
                                    {
                                        BufferPool.ReturnBuffer(data);
                                    }
                                }

                                var serverHelloInfo = await SslTools.PeekServerHello(connection.Stream, BufferPool, cancellationToken);

                                ((ConnectResponse)connectArgs.HttpClient.Response).ServerHelloInfo = serverHelloInfo;
                            }

                            if (!clientStream.IsClosed && !connection.Stream.IsClosed)
                            {
                                await TcpHelper.SendRaw(clientStream, connection.Stream, BufferPool, BufferSize,
                                                        (buffer, offset, count) => { connectArgs.OnDataSent(buffer, offset, count); },
                                                        (buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); },
                                                        connectArgs.CancellationTokenSource, ExceptionFunc);
                            }
                        }
                        finally
                        {
                            await tcpConnectionFactory.Release(connection, true);
                        }

                        return;
                    }
                }

                if (connectArgs != null && await HttpHelper.IsPriMethod(clientStream, BufferPool, BufferSize, cancellationToken) == 1)
                {
                    // todo
                    string httpCmd = await clientStream.ReadLineAsync(cancellationToken);

                    if (httpCmd == "PRI * HTTP/2.0")
                    {
                        connectArgs.HttpClient.ConnectRequest.TunnelType = TunnelType.Http2;

                        // HTTP/2 Connection Preface
                        string line = await clientStream.ReadLineAsync(cancellationToken);

                        if (line != string.Empty)
                        {
                            throw new Exception($"HTTP/2 Protocol violation. Empty string expected, '{line}' received");
                        }

                        line = await clientStream.ReadLineAsync(cancellationToken);

                        if (line != "SM")
                        {
                            throw new Exception($"HTTP/2 Protocol violation. 'SM' expected, '{line}' received");
                        }

                        line = await clientStream.ReadLineAsync(cancellationToken);

                        if (line != string.Empty)
                        {
                            throw new Exception($"HTTP/2 Protocol violation. Empty string expected, '{line}' received");
                        }

                        var connection = await tcpConnectionFactory.GetServerConnection(this, connectArgs,
                                                                                        isConnect : true, applicationProtocols : SslExtensions.Http2ProtocolAsList,
                                                                                        noCache : true, cancellationToken : cancellationToken);

                        try
                        {
                            await connection.StreamWriter.WriteLineAsync("PRI * HTTP/2.0", cancellationToken);

                            await connection.StreamWriter.WriteLineAsync(cancellationToken);

                            await connection.StreamWriter.WriteLineAsync("SM", cancellationToken);

                            await connection.StreamWriter.WriteLineAsync(cancellationToken);

#if NETCOREAPP2_1
                            await Http2Helper.SendHttp2(clientStream, connection.Stream, BufferSize,
                                                        (buffer, offset, count) => { connectArgs.OnDataSent(buffer, offset, count); },
                                                        (buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); },
                                                        () => new SessionEventArgs(this, endPoint, cancellationTokenSource)
                            {
                                ProxyClient = { Connection = clientConnection },
                                HttpClient  = { ConnectRequest = connectArgs?.HttpClient.ConnectRequest },
                                UserData    = connectArgs?.UserData
                            },
                                                        async args => { await invokeBeforeRequest(args); },
                                                        async args => { await invokeBeforeResponse(args); },
                                                        connectArgs.CancellationTokenSource, clientConnection.Id, ExceptionFunc);
#endif
                        }
                        finally
                        {
                            await tcpConnectionFactory.Release(connection, true);
                        }
                    }
                }

                calledRequestHandler = true;
                // Now create the request
                await handleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter,
                                               cancellationTokenSource, connectHostname, connectArgs, prefetchConnectionTask);
            }
            catch (ProxyException e)
            {
                closeServerConnection = true;
                onException(clientStream, e);
            }
            catch (IOException e)
            {
                closeServerConnection = true;
                onException(clientStream, new Exception("Connection was aborted", e));
            }
            catch (SocketException e)
            {
                closeServerConnection = true;
                onException(clientStream, new Exception("Could not connect", e));
            }
            catch (Exception e)
            {
                closeServerConnection = true;
                onException(clientStream, new Exception("Error occured in whilst handling the client", e));
            }
            finally
            {
                if (!calledRequestHandler)
                {
                    await tcpConnectionFactory.Release(prefetchConnectionTask, closeServerConnection);
                }

                sslStream?.Dispose();
                clientStream.Dispose();

                if (!cancellationTokenSource.IsCancellationRequested)
                {
                    cancellationTokenSource.Cancel();
                }
            }
        }
Exemplo n.º 25
0
        public CertFixture()
        {
            Manager = new CertificateManager();

            CleanupCertificates();
        }
Exemplo n.º 26
0
    // Tries to ensure that the client certificate is installed into
    // the local store.  It obtains the client certificate from the service
    // utility endpoint and either installs it or verifies that a matching
    // one is already installed.  InvalidOperationException will be thrown
    // if an error occurred attempting to install the certificate.  This
    // method may be called multiple times but will attempt the installation
    // once only.
    public static void EnsureClientCertificateInstalled()
    {
        if (!s_clientCertAvailabilityChecked)
        {
            lock (s_certLock)
            {
                if (!s_clientCertAvailabilityChecked)
                {
                    X509Certificate2 clientCertificate = null;
                    string           thumbprint        = null;

                    // To be valid, the client certificate also requires the root certificate
                    // to be installed.  But even if the root certificate installation fails,
                    // it is still possible to verify or install the client certificate for
                    // scenarios that don't require chain validation.
                    try
                    {
                        EnsureRootCertificateInstalled();
                    }
                    catch
                    {
                        // Exceptions installing the root certificate are captured and
                        // will be reported if it is requested.  But allow the attempt
                        // to install the client certificate to succeed or fail independently.
                    }

                    try
                    {
                        // Once only, we interrogate the service utility endpoint
                        // for the client certificate and install it locally if it
                        // is not already in the store.
                        clientCertificate = InstallClientCertificateFromServer();

                        // If we had a certificate from the service endpoint, verify it was installed
                        // by retrieving it from the store by thumbprint.
                        if (clientCertificate != null)
                        {
                            thumbprint        = clientCertificate.Thumbprint;
                            clientCertificate = CertificateManager.ClientCertificateFromThumprint(thumbprint, validOnly: false);
                            if (clientCertificate != null)
                            {
                                System.Console.WriteLine(String.Format("Using client certificate:{0}{1}",
                                                                       Environment.NewLine, clientCertificate));
                            }
                            else
                            {
                                s_clientCertInstallErrorMessage =
                                    String.Format("Failed to find a client certificate matching thumbprint '{0}'", thumbprint);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        s_clientCertInstallErrorMessage = ex.ToString();
                    }

                    s_clientCertificate             = clientCertificate;
                    s_clientCertAvailabilityChecked = true;
                }
            }
        }

        // If the installation failed, throw an exception everytime
        // this method is called.
        ThrowIfClientCertificateInstallationError();
    }
Exemplo n.º 27
0
        public async Task <List <ActionResult> > Execute(DeploymentTaskExecutionParams execParams)
        {
            var results = new List <ActionResult>();

            var managedCert = ManagedCertificate.GetManagedCertificate(execParams.Subject);

            // check settings are valid before proceeding
            var validationResults = await Validate(execParams);

            if (validationResults.Any())
            {
                return(validationResults);
            }

            var requestedStore = execParams.Settings.Parameters.FirstOrDefault(p => p.Key == "storetype")?.Value?.Trim().ToLower();
            var friendlyName   = execParams.Settings.Parameters.FirstOrDefault(p => p.Key == "friendlyname")?.Value?.Trim();

            //store cert against primary domain, optionally with custom friendly name
            var certStoreName = CertificateManager.DEFAULT_STORE_NAME;

            if (requestedStore != "default")
            {
                certStoreName = requestedStore;
            }
            else
            {
                certStoreName = CertificateManager.DEFAULT_STORE_NAME;
            }

            X509Certificate2 storedCert = null;

            var certPwd = "";

            if (!string.IsNullOrWhiteSpace(managedCert.CertificatePasswordCredentialId))
            {
                var cred = await execParams.CredentialsManager.GetUnlockedCredentialsDictionary(managedCert.CertificatePasswordCredentialId);

                if (cred != null)
                {
                    certPwd = cred["password"];
                }
            }

            if (!execParams.IsPreviewOnly)
            {
                try
                {
                    storedCert = await CertificateManager.StoreCertificate(
                        managedCert.RequestConfig.PrimaryDomain,
                        managedCert.CertificatePath,
                        isRetry : false,
                        enableRetryBehaviour : _enableCertDoubleImportBehaviour,
                        storeName : certStoreName,
                        customFriendlyName : friendlyName,
                        certPwd
                        );

                    if (storedCert != null)
                    {
                        // certHash = storedCert.GetCertHash();

                        results.Add(new ActionResult("Certificate stored OK", true));
                    }
                }
                catch (Exception exp)
                {
                    results.Add(new ActionResult("Error storing certificate :: " + exp.Message, false));
                }
            }
            else
            {
                results.Add(new ActionResult($"Would store certificate in Local Certificate Store [{certStoreName}]", true));
            }

            return(results);
        }
Exemplo n.º 28
0
    // Acquires the peer trust certificate from the service utility endpoint and
    // attempts to install it into the TrustedPeople store.  All failures are
    // propagated back to the caller.
    private static X509Certificate2 InstallPeerCertificateFromServer()
    {
        X509Certificate2 peerCertificate = new X509Certificate2(GetResourceFromServiceAsByteArray(PeerCertificateResource), "test", X509KeyStorageFlags.PersistKeySet);

        return(CertificateManager.InstallCertificateToTrustedPeopleStore(peerCertificate));
    }
Exemplo n.º 29
0
        /// <summary>
        /// Run general diagnostics, optionally fixing binding deployment
        /// </summary>
        /// <param name="autoFix">Attempt to re-apply current certificate</param>
        /// <param name="forceAutoDeploy">Change all deployment modes to Auto</param>
        public void RunCertDiagnostics(bool autoFix = false, bool forceAutoDeploy = false)
        {
            string stripNonNumericFromString(string input)
            {
                return(new string(input.Where(c => char.IsDigit(c)).ToArray()));
            }

            bool isNumeric(string input)
            {
                return(int.TryParse(input, out _));
            }

            var managedCertificates = _certifyClient.GetManagedCertificates(new ManagedCertificateFilter()).Result;

            Console.ForegroundColor = ConsoleColor.White;
#if BINDING_CHECKS
            Console.WriteLine("Checking existing bindings..");

            var bindingConfig = Certify.Utils.Networking.GetCertificateBindings().Where(b => b.Port == 443);

            foreach (var b in bindingConfig)
            {
                Console.WriteLine($"{b.IP}:{b.Port}");
            }

            var dupeBindings = bindingConfig.GroupBy(x => x.IP + ":" + x.Port)
                               .Where(g => g.Count() > 1)
                               .Select(y => y.Key)
                               .ToList();

            if (dupeBindings.Any())
            {
                foreach (var d in dupeBindings)
                {
                    Console.WriteLine($"Duplicate binding will fail:  {d}");
                }
            }
            else
            {
                Console.WriteLine("No duplicate IP:Port bindings identified.");
            }
#endif
            Console.WriteLine("Running cert diagnostics..");

            var countSiteIdsFixed         = 0;
            var countBindingRedeployments = 0;


            foreach (var site in managedCertificates)
            {
                var redeployRequired = false;

                if (autoFix)
                {
                    redeployRequired = true;
                }

                if ((site.GroupId != site.ServerSiteId) || !isNumeric(site.ServerSiteId))
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("\t WARNING: managed cert has invalid ServerSiteID: " + site.Name);
                    Console.ForegroundColor = ConsoleColor.White;

                    redeployRequired = true;

                    if (autoFix)
                    {
                        site.ServerSiteId = stripNonNumericFromString(site.ServerSiteId);
                        site.GroupId      = site.ServerSiteId;
                        //update managed site
                        Console.WriteLine("\t Auto fixing managed cert ServerSiteID: " + site.Name);

                        var update = _certifyClient.UpdateManagedCertificate(site);
                        update.ConfigureAwait(true);
                        update.Wait();

                        countSiteIdsFixed++;
                    }
                }

                if (autoFix && forceAutoDeploy)
                {
                    redeployRequired = true;

                    if (site.RequestConfig.DeploymentSiteOption != DeploymentOption.Auto && site.RequestConfig.DeploymentSiteOption != DeploymentOption.AllSites)
                    {
                        Console.WriteLine("\t Auto fixing managed cert deployment mode: " + site.Name);
                        site.RequestConfig.DeploymentSiteOption = DeploymentOption.Auto;

                        var update = _certifyClient.UpdateManagedCertificate(site);
                        update.ConfigureAwait(true);
                        update.Wait();
                    }
                }

                if (!string.IsNullOrEmpty(site.CertificatePath) && System.IO.File.Exists(site.CertificatePath))
                {
                    Console.WriteLine($"{site.Name}");
                    var fileCert = CertificateManager.LoadCertificate(site.CertificatePath);

                    if (fileCert != null)
                    {
                        try
                        {
                            var storedCert = CertificateManager.GetCertificateByThumbprint(site.CertificateThumbprintHash);
                            if (storedCert != null)
                            {
                                // cert in store, check permissions
                                Console.WriteLine($"Stored cert :: " + storedCert.FriendlyName);
                                var test = fileCert.PrivateKey.KeyExchangeAlgorithm;
                                Console.WriteLine(test.ToString());

                                var access = CertificateManager.GetUserAccessInfoForCertificatePrivateKey(storedCert);
                                foreach (System.Security.AccessControl.AuthorizationRule a in access.GetAccessRules(true, false, typeof(System.Security.Principal.NTAccount)))
                                {
                                    Console.WriteLine("\t Access: " + a.IdentityReference.Value.ToString());
                                }
                            }

                            // re-deploy certificate if possible
                            if (redeployRequired && autoFix)
                            {
                                //re-apply current certificate file to store and bindings
                                if (!string.IsNullOrEmpty(site.CertificateThumbprintHash))
                                {
                                    var bindingApply = _certifyClient.ReapplyCertificateBindings(site.Id, false);
                                    bindingApply.ConfigureAwait(true);
                                    bindingApply.Wait();

                                    countBindingRedeployments++;

                                    var result = bindingApply.Result;
                                    if (!result.IsSuccess)
                                    {
                                        Console.ForegroundColor = ConsoleColor.Red;
                                        Console.WriteLine("\t Error: Failed to re-applying certificate bindings:" + site.Name);
                                        Console.ForegroundColor = ConsoleColor.White;
                                    }
                                    else
                                    {
                                        Console.ForegroundColor = ConsoleColor.Green;
                                        Console.WriteLine("\t Info: re-applied certificate bindings:" + site.Name);
                                        Console.ForegroundColor = ConsoleColor.White;
                                    }

                                    System.Threading.Thread.Sleep(5000);
                                }
                                else
                                {
                                    Console.ForegroundColor = ConsoleColor.DarkYellow;
                                    Console.WriteLine($"Warning: {site.Name} :: No certificate information, bindings cannot be redeployed");
                                    Console.ForegroundColor = ConsoleColor.White;
                                }
                            }
                        }
                        catch (Exception exp)
                        {
                            Console.WriteLine(exp.ToString());
                        }
                    }
                    else
                    {
                        //Console.WriteLine($"{site.Name} certificate file does not exist: {site.CertificatePath}");
                        if (redeployRequired)
                        {
                            Console.WriteLine($"{site.Name} has no current certificate and requires manual verification/redeploy of cert.");
                        }
                    }
                }
            }

            // TODO: get refresh of managed certs and for each current cert thumbprint, verify binding thumbprint match

            Console.WriteLine("-----------");
        }
Exemplo n.º 30
0
        public void EnsureCreateHttpsCertificate_CreatesACertificate_WhenThereAreNoHttpsCertificates()
        {
            try
            {
                // Arrange
                const string CertificateName = nameof(EnsureCreateHttpsCertificate_CreatesACertificate_WhenThereAreNoHttpsCertificates) + ".cer";
                var          manager         = new CertificateManager();

                manager.RemoveAllCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, TestCertificateSubject);
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    manager.RemoveAllCertificates(CertificatePurpose.HTTPS, StoreName.Root, StoreLocation.CurrentUser, TestCertificateSubject);
                }

                // Act
                DateTimeOffset now = DateTimeOffset.UtcNow;
                now = new DateTimeOffset(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, 0, now.Offset);
                var result = manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1), CertificateName, trust: false, subject: TestCertificateSubject);

                // Assert
                Assert.Equal(EnsureCertificateResult.Succeeded, result);
                Assert.True(File.Exists(CertificateName));

                var exportedCertificate = new X509Certificate2(File.ReadAllBytes(CertificateName));
                Assert.NotNull(exportedCertificate);
                Assert.False(exportedCertificate.HasPrivateKey);

                var httpsCertificates = manager.ListCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, isValid: false);
                var httpsCertificate  = Assert.Single(httpsCertificates, c => c.Subject == TestCertificateSubject);
                Assert.True(httpsCertificate.HasPrivateKey);
                Assert.Equal(TestCertificateSubject, httpsCertificate.Subject);
                Assert.Equal(TestCertificateSubject, httpsCertificate.Issuer);
                Assert.Equal("sha256RSA", httpsCertificate.SignatureAlgorithm.FriendlyName);
                Assert.Equal("1.2.840.113549.1.1.11", httpsCertificate.SignatureAlgorithm.Value);

                Assert.Equal(now.LocalDateTime, httpsCertificate.NotBefore);
                Assert.Equal(now.AddYears(1).LocalDateTime, httpsCertificate.NotAfter);
                Assert.Contains(
                    httpsCertificate.Extensions.OfType <X509Extension>(),
                    e => e is X509BasicConstraintsExtension basicConstraints &&
                    basicConstraints.Critical == true &&
                    basicConstraints.CertificateAuthority == false &&
                    basicConstraints.HasPathLengthConstraint == false &&
                    basicConstraints.PathLengthConstraint == 0);

                Assert.Contains(
                    httpsCertificate.Extensions.OfType <X509Extension>(),
                    e => e is X509KeyUsageExtension keyUsage &&
                    keyUsage.Critical == true &&
                    keyUsage.KeyUsages == X509KeyUsageFlags.KeyEncipherment);

                Assert.Contains(
                    httpsCertificate.Extensions.OfType <X509Extension>(),
                    e => e is X509EnhancedKeyUsageExtension enhancedKeyUsage &&
                    enhancedKeyUsage.Critical == true &&
                    enhancedKeyUsage.EnhancedKeyUsages.OfType <Oid>().Single() is Oid keyUsage &&
                    keyUsage.Value == "1.3.6.1.5.5.7.3.1");

                // Subject alternative name
                Assert.Contains(
                    httpsCertificate.Extensions.OfType <X509Extension>(),
                    e => e.Critical == true &&
                    e.Oid.Value == "2.5.29.17");

                // ASP.NET HTTPS Development certificate extension
                Assert.Contains(
                    httpsCertificate.Extensions.OfType <X509Extension>(),
                    e => e.Critical == false &&
                    e.Oid.Value == "1.3.6.1.4.1.311.84.1.1" &&
                    Encoding.ASCII.GetString(e.RawData) == "ASP.NET Core HTTPS development certificate");

                Assert.Equal(httpsCertificate.GetCertHashString(), exportedCertificate.GetCertHashString());
            }
            catch (Exception e)
            {
                Output.WriteLine(e.Message);
                ListCertificates(Output);
                throw;
            }
        }
Exemplo n.º 31
0
        private async Task handleClient(TransparentBaseProxyEndPoint endPoint, TcpClientConnection clientConnection,
                                        int port, CancellationTokenSource cancellationTokenSource, CancellationToken cancellationToken)
        {
            bool isHttps      = false;
            var  clientStream = new HttpClientStream(clientConnection, clientConnection.GetStream(), BufferPool, cancellationToken);

            try
            {
                var clientHelloInfo = await SslTools.PeekClientHello(clientStream, BufferPool, cancellationToken);

                if (clientHelloInfo != null)
                {
                    var httpsHostName = clientHelloInfo.GetServerName() ?? endPoint.GenericCertificateName;

                    var args = new BeforeSslAuthenticateEventArgs(clientConnection, cancellationTokenSource, httpsHostName);

                    await endPoint.InvokeBeforeSslAuthenticate(this, args, ExceptionFunc);

                    if (cancellationTokenSource.IsCancellationRequested)
                    {
                        throw new Exception("Session was terminated by user.");
                    }

                    if (endPoint.DecryptSsl && args.DecryptSsl)
                    {
                        clientStream.Connection.SslProtocol = clientHelloInfo.SslProtocol;

                        // do client authentication using certificate
                        X509Certificate2?certificate = null;
                        SslStream?       sslStream   = null;
                        try
                        {
                            sslStream = new SslStream(clientStream, false);

                            string certName = HttpHelper.GetWildCardDomainName(httpsHostName);
                            certificate = endPoint.GenericCertificate ??
                                          await CertificateManager.CreateServerCertificate(certName);

                            // Successfully managed to authenticate the client using the certificate
                            await sslStream.AuthenticateAsServerAsync(certificate, false, SslProtocols.Tls, false);

                            // HTTPS server created - we can now decrypt the client's traffic
                            clientStream = new HttpClientStream(clientStream.Connection, sslStream, BufferPool, cancellationToken);
                            sslStream    = null; // clientStream was created, no need to keep SSL stream reference
                            isHttps      = true;
                        }
                        catch (Exception e)
                        {
                            sslStream?.Dispose();

                            var certName = certificate?.GetNameInfo(X509NameType.SimpleName, false);
                            var session  = new SessionEventArgs(this, endPoint, clientStream, null, cancellationTokenSource);
                            throw new ProxyConnectException(
                                      $"Couldn't authenticate host '{httpsHostName}' with certificate '{certName}'.", e, session);
                        }
                    }
                    else
                    {
                        var sessionArgs = new SessionEventArgs(this, endPoint, clientStream, null, cancellationTokenSource);
                        var connection  = await tcpConnectionFactory.GetServerConnection(this, httpsHostName, port,
                                                                                         HttpHeader.VersionUnknown, false, null,
                                                                                         true, sessionArgs, UpStreamEndPoint,
                                                                                         UpStreamHttpsProxy, true, cancellationToken);

                        try
                        {
                            int available = clientStream.Available;

                            if (available > 0)
                            {
                                // send the buffered data
                                var data = BufferPool.GetBuffer();
                                try
                                {
                                    // clientStream.Available should be at most BufferSize because it is using the same buffer size
                                    await clientStream.ReadAsync(data, 0, available, cancellationToken);

                                    await connection.Stream.WriteAsync(data, 0, available, true, cancellationToken);
                                }
                                finally
                                {
                                    BufferPool.ReturnBuffer(data);
                                }
                            }

                            if (!clientStream.IsClosed && !connection.Stream.IsClosed)
                            {
                                await TcpHelper.SendRaw(clientStream, connection.Stream, BufferPool,
                                                        null, null, cancellationTokenSource, ExceptionFunc);
                            }
                        }
                        finally
                        {
                            await tcpConnectionFactory.Release(connection, true);
                        }

                        return;
                    }
                }

                // HTTPS server created - we can now decrypt the client's traffic
                // Now create the request
                await handleHttpSessionRequest(endPoint, clientStream, cancellationTokenSource, isHttps : isHttps);
            }
            catch (ProxyException e)
            {
                onException(clientStream, e);
            }
            catch (IOException e)
            {
                onException(clientStream, new Exception("Connection was aborted", e));
            }
            catch (SocketException e)
            {
                onException(clientStream, new Exception("Could not connect", e));
            }
            catch (Exception e)
            {
                onException(clientStream, new Exception("Error occured in whilst handling the client", e));
            }
            finally
            {
                clientStream.Dispose();
            }
        }
 private string CreateCertificate(long userid, string password, string doc1, string doc2, string doc3, string isrcCode, string trackName, CoopArtistList coopArtists)
 {
     string ret = string.Empty;
     using (CertificateManager mgr = new CertificateManager(userid, password))
     {
         mgr.AddTrackName(trackName);
         if (!string.IsNullOrEmpty(doc1))
             mgr.AddDocument(doc1);
         if (!string.IsNullOrEmpty(doc2))
             mgr.AddDocument(doc2);
         if (!string.IsNullOrEmpty(doc3))
             mgr.AddDocument(doc3);
         if (!string.IsNullOrEmpty(isrcCode))
             mgr.AddIsrcCode(isrcCode);
         foreach (CoopArtist coop in coopArtists)
             mgr.AddCoopArtist(coop.Artist, coop.Role);
         mgr.CreateCertificate(string.Format("{0}.cer", DateTime.UtcNow.ToString("yyyyMMddHHmmss")));
         ret = mgr.CertificateFilename;
     }
     return ret;
 }
Exemplo n.º 33
0
        /// <summary>
        /// This is called when client is aware of proxy
        /// So for HTTPS requests client would send CONNECT header to negotiate a secure tcp tunnel via proxy
        /// </summary>
        /// <param name="endPoint"></param>
        /// <param name="tcpClient"></param>
        /// <returns></returns>
        private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClient tcpClient)
        {
            bool disposed = false;

            var clientStream = new CustomBufferedStream(tcpClient.GetStream(), BufferSize);

            var clientStreamReader = new CustomBinaryReader(clientStream, BufferSize);
            var clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize);

            Uri httpRemoteUri;

            try
            {
                //read the first line HTTP command
                string httpCmd = await clientStreamReader.ReadLineAsync();

                if (string.IsNullOrEmpty(httpCmd))
                {
                    return;
                }

                string  httpMethod;
                string  httpUrl;
                Version version;
                Request.ParseRequestLine(httpCmd, out httpMethod, out httpUrl, out version);

                httpRemoteUri = httpMethod == "CONNECT" ? new Uri("http://" + httpUrl) : new Uri(httpUrl);

                //filter out excluded host names
                bool excluded = false;

                if (endPoint.ExcludedHttpsHostNameRegex != null)
                {
                    excluded = endPoint.ExcludedHttpsHostNameRegexList.Any(x => x.IsMatch(httpRemoteUri.Host));
                }

                if (endPoint.IncludedHttpsHostNameRegex != null)
                {
                    excluded = !endPoint.IncludedHttpsHostNameRegexList.Any(x => x.IsMatch(httpRemoteUri.Host));
                }

                ConnectRequest connectRequest = null;

                //Client wants to create a secure tcp tunnel (probably its a HTTPS or Websocket request)
                if (httpMethod == "CONNECT")
                {
                    connectRequest = new ConnectRequest
                    {
                        RequestUri  = httpRemoteUri,
                        OriginalUrl = httpUrl,
                        HttpVersion = version,
                    };

                    await HeaderParser.ReadHeaders(clientStreamReader, connectRequest.Headers);

                    var connectArgs = new TunnelConnectSessionEventArgs(BufferSize, endPoint, connectRequest);
                    connectArgs.ProxyClient.TcpClient    = tcpClient;
                    connectArgs.ProxyClient.ClientStream = clientStream;

                    if (TunnelConnectRequest != null)
                    {
                        await TunnelConnectRequest.InvokeParallelAsync(this, connectArgs, ExceptionFunc);
                    }

                    if (!excluded && await CheckAuthorization(clientStreamWriter, connectArgs) == false)
                    {
                        if (TunnelConnectResponse != null)
                        {
                            await TunnelConnectResponse.InvokeParallelAsync(this, connectArgs, ExceptionFunc);
                        }

                        return;
                    }

                    //write back successfull CONNECT response
                    connectArgs.WebSession.Response = ConnectResponse.CreateSuccessfullConnectResponse(version);
                    await clientStreamWriter.WriteResponseAsync(connectArgs.WebSession.Response);

                    var clientHelloInfo = await SslTools.PeekClientHello(clientStream);

                    bool isClientHello = clientHelloInfo != null;
                    if (isClientHello)
                    {
                        connectRequest.ClientHelloInfo = clientHelloInfo;
                    }

                    if (TunnelConnectResponse != null)
                    {
                        connectArgs.IsHttpsConnect = isClientHello;
                        await TunnelConnectResponse.InvokeParallelAsync(this, connectArgs, ExceptionFunc);
                    }

                    if (!excluded && isClientHello)
                    {
                        httpRemoteUri             = new Uri("https://" + httpUrl);
                        connectRequest.RequestUri = httpRemoteUri;

                        SslStream sslStream = null;

                        try
                        {
                            sslStream = new SslStream(clientStream);

                            string certName = HttpHelper.GetWildCardDomainName(httpRemoteUri.Host);

                            var certificate = endPoint.GenericCertificate ?? CertificateManager.CreateCertificate(certName, false);

                            //Successfully managed to authenticate the client using the fake certificate
                            await sslStream.AuthenticateAsServerAsync(certificate, false, SupportedSslProtocols, false);

                            //HTTPS server created - we can now decrypt the client's traffic
                            clientStream = new CustomBufferedStream(sslStream, BufferSize);

                            clientStreamReader.Dispose();
                            clientStreamReader = new CustomBinaryReader(clientStream, BufferSize);
                            clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize);
                        }
                        catch
                        {
                            sslStream?.Dispose();
                            return;
                        }

                        //Now read the actual HTTPS request line
                        httpCmd = await clientStreamReader.ReadLineAsync();
                    }
                    //Hostname is excluded or it is not an HTTPS connect
                    else
                    {
                        //create new connection
                        using (var connection = await GetServerConnection(connectArgs, true))
                        {
                            try
                            {
                                if (isClientHello)
                                {
                                    if (clientStream.Available > 0)
                                    {
                                        //send the buffered data
                                        var data = new byte[clientStream.Available];
                                        await clientStream.ReadAsync(data, 0, data.Length);

                                        await connection.Stream.WriteAsync(data, 0, data.Length);

                                        await connection.Stream.FlushAsync();
                                    }

                                    var serverHelloInfo = await SslTools.PeekServerHello(connection.Stream);

                                    ((ConnectResponse)connectArgs.WebSession.Response).ServerHelloInfo = serverHelloInfo;
                                }

                                await TcpHelper.SendRaw(clientStream, connection.Stream, BufferSize,
                                                        (buffer, offset, count) => { connectArgs.OnDataSent(buffer, offset, count); }, (buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); });
                            }
                            finally
                            {
                                UpdateServerConnectionCount(false);
                            }
                        }

                        return;
                    }
                }

                //Now create the request
                disposed = await HandleHttpSessionRequest(tcpClient, httpCmd, clientStream, clientStreamReader, clientStreamWriter,
                                                          httpRemoteUri.Scheme == UriSchemeHttps?httpRemoteUri.Host : null, endPoint, connectRequest);
            }
            catch (Exception e)
            {
                ExceptionFunc(new Exception("Error whilst authorizing request", e));
            }
            finally
            {
                if (!disposed)
                {
                    Dispose(clientStream, clientStreamReader, clientStreamWriter, null);
                }
            }
        }
 private string CreateCertificate(long userid, string doc1, string doc2, string doc3, string isrcCode, string trackName, CoopArtistList coopArtists)
 {
     ClientInfo ci = null;
     using (Database db = new MySqlDatabase())
     {
         ci = db.GetClientInfo(Util.UserId);
     }
     string ret = string.Empty;
     using (CertificateManager mgr = new CertificateManager(userid, string.Empty))
     {
         mgr.AddTrackName(trackName);
         if (!string.IsNullOrEmpty(doc1))
             mgr.AddDocument(doc1);
         if (!string.IsNullOrEmpty(doc2))
             mgr.AddDocument(doc2);
         if (!string.IsNullOrEmpty(doc3))
             mgr.AddDocument(doc3);
         if (!string.IsNullOrEmpty(isrcCode))
             mgr.AddIsrcCode(isrcCode);
         foreach (CoopArtist coop in coopArtists)
             mgr.AddCoopArtist(coop.Artist, coop.Role);
         if (ci != null)
             mgr.Agent = ci.GetFullName();
         mgr.CreateCertificate(string.Format("{0}.cer", DateTime.UtcNow.ToString("yyyyMMddHHmmss")));
         ret = mgr.CertificateFilename;
     }
     return ret;
 }
 private static X509Certificate2 GetSamlTokenSigningCertificate()
 {
     var certificateManager = new CertificateManager();
     var samlTokenSigningCertificate = certificateManager.GetCertificate();
     return samlTokenSigningCertificate;
 }