<commit_before>﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace OpenSSL
{
    public class PKCS12 : Base, IDisposable
    {
        #region PKCS12 structure

        [StructLayout(LayoutKind.Sequential)]
        struct _PKCS12
        {
            IntPtr version;     //ASN1_INTEGER *version;
            IntPtr mac;         //PKCS12_MAC_DATA *mac;
            IntPtr authsafes;   //PKCS7 *authsafes;
        }
        #endregion

        private CryptoKey privateKey;
        private X509Certificate certificate;
        private Stack<X509Certificate> caCertificates;
        private bool shouldDisposePrivateKey = true;
        private bool shouldDisposeCertificate = true;
        private bool shouldDisposeCACertificates = true;

        public PKCS12(IntPtr ptr, bool takeOwnership)
            : base(ptr, takeOwnership)
        {
        }

        public PKCS12(BIO bio, string password)
            : base(IntPtr.Zero, false)
        {
            IntPtr cert;
            IntPtr pkey;
            IntPtr cacerts;

            IntPtr ptr = Native.ExpectNonNull(Native.d2i_PKCS12_bio(bio.Handle, IntPtr.Zero));
            // set the base ptr
            this.ptr = ptr;
            this.owner = true;
            // Parse the PKCS12 object and get privatekey, cert, cacerts if available
            Native.ExpectSuccess(Native.PKCS12_parse(this.ptr, password, out pkey, out cert, out cacerts));
            if (pkey != IntPtr.Zero)
            {
                privateKey = new CryptoKey(pkey, true);
            }
            if (cert != IntPtr.Zero)
            {
                certificate = new X509Certificate(cert, true);
                if (privateKey != null)
                {
                    // We have a private key, assign it to the cert
                    certificate.PrivateKey = privateKey;
                }
            }
            if (cacerts != IntPtr.Zero)
            {
                caCertificates = new Stack<X509Certificate>(cacerts, true);
            }
        }

        public X509Certificate Certificate
        {
            get
            {
                shouldDisposeCertificate = false;
                return certificate;
            }
        }

        public CryptoKey PrivateKey
        {
            get
            {
                shouldDisposePrivateKey = false;
                return privateKey;
            }
        }

        public Stack<X509Certificate> CACertificates
        {
            get
            {
                shouldDisposeCACertificates = false;
                return caCertificates;
            }
        }

        public override void OnDispose()
        {
            if (certificate != null && ! shouldDisposeCertificate)
            {
                certificate.Dispose();
            }
            if (privateKey != null && ! shouldDisposePrivateKey)
            {
                privateKey.Dispose();
            }
            if (caCertificates != null && ! shouldDisposeCACertificates)
            {
                caCertificates.Dispose();
            }
            Native.PKCS12_free(this.ptr);
        }
    }
}<commit_msg>Fixed memory leaks with Certificates and Private keys in the PKCS12 class<commit_after>﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace OpenSSL
{
    public class PKCS12 : Base, IDisposable
    {
        #region PKCS12 structure

        [StructLayout(LayoutKind.Sequential)]
        struct _PKCS12
        {
            IntPtr version;     //ASN1_INTEGER *version;
            IntPtr mac;         //PKCS12_MAC_DATA *mac;
            IntPtr authsafes;   //PKCS7 *authsafes;
        }
        #endregion

        private CryptoKey privateKey;
        private X509Certificate certificate;
        private Stack<X509Certificate> caCertificates;
        private bool shouldDisposePrivateKey = true;
        private bool shouldDisposeCertificate = true;
        private bool shouldDisposeCACertificates = true;

        public PKCS12(IntPtr ptr, bool takeOwnership)
            : base(ptr, takeOwnership)
        {
        }

        public PKCS12(BIO bio, string password)
            : base(IntPtr.Zero, false)
        {
            IntPtr cert;
            IntPtr pkey;
            IntPtr cacerts;

            IntPtr ptr = Native.ExpectNonNull(Native.d2i_PKCS12_bio(bio.Handle, IntPtr.Zero));
            // set the base ptr
            this.ptr = ptr;
            this.owner = true;
            // Parse the PKCS12 object and get privatekey, cert, cacerts if available
            Native.ExpectSuccess(Native.PKCS12_parse(this.ptr, password, out pkey, out cert, out cacerts));
            if (pkey != IntPtr.Zero)
            {
                privateKey = new CryptoKey(pkey, true);
            }
            if (cert != IntPtr.Zero)
            {
                certificate = new X509Certificate(cert, true);
                if (privateKey != null)
                {
                    // We have a private key, assign it to the cert
                    privateKey.Addref();
                    CryptoKey key = new CryptoKey(privateKey.Handle, true);
                    certificate.PrivateKey = key;
                }
            }
            if (cacerts != IntPtr.Zero)
            {
                caCertificates = new Stack<X509Certificate>(cacerts, true);
            }
        }

        public X509Certificate Certificate
        {
            get
            {
                if (certificate != null)
                {
                    certificate.Addref();                    
                    X509Certificate cert = new X509Certificate(certificate.Handle, true);
                    if (privateKey != null)
                    {
                        privateKey.Addref();
                        CryptoKey key = new CryptoKey(privateKey.Handle, true);
                        cert.PrivateKey = key;
                    }
                    return cert;
                }
                return null;
            }
        }

        public CryptoKey PrivateKey
        {
            get
            {
                if (privateKey != null)
                {
                    privateKey.Addref();
                    CryptoKey key = new CryptoKey(privateKey.Handle, true);
                    return key;
                }
                return null;
            }
        }

        public Stack<X509Certificate> CACertificates
        {
            get
            {
                shouldDisposeCACertificates = false;
                return caCertificates;
            }
        }

        public override void OnDispose()
        {
            if (certificate != null)
            {
                certificate.Dispose();
            }
            if (privateKey != null)
            {
                privateKey.Dispose();
            }
            if (caCertificates != null)
            {
                caCertificates.Dispose();
            }
            Native.PKCS12_free(this.ptr);
        }
    }
}
{'fraction_non_alphanumeric': 0.07232306177008584, 'fraction_numerical': 0.01266357112705783, 'mean_word_length': 1.264415418923224, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2724934', 'n_tokens_mistral': 1871, 'n_tokens_neox': 1756, 'n_words': 415}