Esempio n. 1
0
        internal override int SetClientCertificate(SafeHandle ld, X509Certificate2 certificate)
        {
            const int verifyDepth = 6;
            var       certData    = MarshalUtils.ByteArrayToGnuTlsDatum(certificate.Export(X509ContentType.Cert));
            var       certs       = MarshalUtils.AllocHGlobalIntPtrArray(verifyDepth);

            var privateKey = (RSA)certificate.PrivateKey;

            var keyData = MarshalUtils.ByteArrayToGnuTlsDatum(privateKey.ToRsaPrivateKey());

            try
            {
                var max      = verifyDepth;
                var tlsCtx   = IntPtr.Zero;
                var isServer = 0;
                ThrowIfError(ld,
                             ldap_set_option(new LdapHandle(IntPtr.Zero), (int)Native.LdapOption.LDAP_OPT_X_TLS_NEWCTX,
                                             ref isServer), nameof(ldap_set_option));
                ThrowIfError(ld,
                             ldap_get_option(new LdapHandle(IntPtr.Zero), (int)Native.LdapOption.LDAP_OPT_X_TLS_CTX,
                                             ref tlsCtx),
                             nameof(ldap_set_option));

                var key  = IntPtr.Zero;
                var cred = Marshal.ReadIntPtr(tlsCtx);

                ThrowIfGnuTlsError(NativeMethodsLinux.gnutls_x509_privkey_init(ref key),
                                   nameof(NativeMethodsLinux.gnutls_x509_privkey_init));
                ThrowIfGnuTlsError(
                    NativeMethodsLinux.gnutls_x509_privkey_import(key, keyData,
                                                                  NativeMethodsLinux.GNUTLS_X509_FMT.GNUTLS_X509_FMT_DER),
                    nameof(NativeMethodsLinux.gnutls_x509_privkey_import));
                ThrowIfGnuTlsError(
                    NativeMethodsLinux.gnutls_x509_crt_list_import(certs, ref max, certData,
                                                                   NativeMethodsLinux.GNUTLS_X509_FMT.GNUTLS_X509_FMT_DER, 0),
                    nameof(NativeMethodsLinux.gnutls_x509_crt_list_import));

                var cert = Marshal.ReadIntPtr(certs);

                // If there's only one cert and it's not self-signed, then we have to build the cert chain.
                if (max == 1 && !IsSelfSigned(cert))
                {
                    for (var i = 1; i < verifyDepth; i++)
                    {
                        cert = Marshal.ReadIntPtr(certs, (i - 1) * IntPtr.Size);
                        var issuer = Marshal.ReadIntPtr(certs, i * IntPtr.Size);


                        if (NativeMethodsLinux.gnutls_certificate_get_issuer(cred, cert, ref issuer, 0) != 0)
                        {
                            break;
                        }

                        Marshal.WriteIntPtr(certs, i * IntPtr.Size, issuer);
                        max++;

                        if (IsSelfSigned(issuer))
                        {
                            break;
                        }
                    }
                }

                ThrowIfGnuTlsError(NativeMethodsLinux.gnutls_certificate_set_x509_key(cred, certs, max, key),
                                   nameof(NativeMethodsLinux.gnutls_certificate_set_x509_key));
                NativeMethodsLinux.gnutls_certificate_set_verify_flags(cred, 0);
                return(ldap_set_option(new LdapHandle(IntPtr.Zero), (int)Native.LdapOption.LDAP_OPT_X_TLS_CTX, tlsCtx));
            }
            finally
            {
                MarshalUtils.TlsDatumFree(certData);
                MarshalUtils.TlsDatumFree(keyData);
                if (certs != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(certs);
                }
            }
        }