Esempio n. 1
0
        //
        // Get certificate_authorities list, according to RFC 5246, Section 7.4.4.
        // Used only by client SSL code, never returns null.
        //
        private string[] GetRequestCertificateAuthorities()
        {
            string[] issuers = Array.Empty <string>();

            if (IsValidContext)
            {
                issuers = CertificateValidationPal.GetRequestCertificateAuthorities(_securityContext);
            }
            return(issuers);
        }
Esempio n. 2
0
        private static SecurityStatusPal HandshakeInternal(
            SafeFreeCredentials credential,
            ref SafeDeleteSslContext?context,
            ReadOnlySpan <byte> inputBuffer,
            ref byte[]?outputBuffer,
            SslAuthenticationOptions sslAuthenticationOptions)
        {
            Debug.Assert(!credential.IsInvalid);

            try
            {
                SafeDeleteSslContext?sslContext = ((SafeDeleteSslContext?)context);

                if ((null == context) || context.IsInvalid)
                {
                    sslContext = new SafeDeleteSslContext((credential as SafeFreeSslCredentials) !, sslAuthenticationOptions);
                    context    = sslContext;

                    if (!string.IsNullOrEmpty(sslAuthenticationOptions.TargetHost) && !sslAuthenticationOptions.IsServer)
                    {
                        Interop.AppleCrypto.SslSetTargetName(sslContext.SslContext, sslAuthenticationOptions.TargetHost);
                    }

                    if (sslAuthenticationOptions.CertificateContext == null && sslAuthenticationOptions.CertSelectionDelegate != null)
                    {
                        // certificate was not provided but there is user callback. We can break handshake if server asks for certificate
                        // and we can try to get it based on remote certificate and trusted issuers.
                        Interop.AppleCrypto.SslBreakOnCertRequested(sslContext.SslContext, true);
                    }

                    if (sslAuthenticationOptions.IsServer && sslAuthenticationOptions.RemoteCertRequired)
                    {
                        Interop.AppleCrypto.SslSetAcceptClientCert(sslContext.SslContext);
                    }
                }

                if (inputBuffer.Length > 0)
                {
                    sslContext !.Write(inputBuffer);
                }

                SafeSslHandle     sslHandle = sslContext !.SslContext;
                SecurityStatusPal status    = PerformHandshake(sslHandle);
                if (status.ErrorCode == SecurityStatusPalErrorCode.CredentialsNeeded)
                {
                    // we should not be here if CertSelectionDelegate is null but better check before dereferencing..
                    if (sslAuthenticationOptions.CertSelectionDelegate != null)
                    {
                        X509Certificate2?remoteCert = null;
                        try
                        {
                            string[] issuers = CertificateValidationPal.GetRequestCertificateAuthorities(context);
                            remoteCert = CertificateValidationPal.GetRemoteCertificate(context);
                            if (sslAuthenticationOptions.ClientCertificates == null)
                            {
                                sslAuthenticationOptions.ClientCertificates = new X509CertificateCollection();
                            }
                            X509Certificate2 clientCertificate = (X509Certificate2)sslAuthenticationOptions.CertSelectionDelegate(sslAuthenticationOptions.TargetHost !, sslAuthenticationOptions.ClientCertificates, remoteCert, issuers);
                            if (clientCertificate != null)
                            {
                                SafeDeleteSslContext.SetCertificate(sslContext.SslContext, SslStreamCertificateContext.Create(clientCertificate));
                            }
                        }
                        finally
                        {
                            remoteCert?.Dispose();
                        }
                    }

                    // We either got certificate or we can proceed without it. It is up to the server to decide if either is OK.
                    status = PerformHandshake(sslHandle);
                }

                outputBuffer = sslContext.ReadPendingWrites();
                return(status);
            }
            catch (Exception exc)
            {
                return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, exc));
            }
        }