예제 #1
0
 /// <summary>
 /// Called when timed shelve period expires.
 /// </summary>
 private void OnTimerExpired(object state)
 {
     try
     {
         if (OnTimedUnshelve != null)
         {
             OnTimedUnshelve((ISystemContext)state, this);
         }
         this.OnUnshelveTimeUpdate(state);
     }
     catch (Exception e)
     {
         Utils.LogError(e, "Unexpected error unshelving alarm.");
     }
 }
예제 #2
0
 /// <summary>
 /// Called when shelved state is not Unshelved to update the UnshelveTime value.
 /// </summary>
 private void OnUnshelveTimeUpdate(object state)
 {
     try
     {
         ISystemContext context            = (ISystemContext)state;
         object         unshelveTimeObject = new object();
         OnReadUnshelveTime(context, null, ref unshelveTimeObject);
         double unshelveTime = (double)unshelveTimeObject;
         if (unshelveTime != this.ShelvingState.UnshelveTime.Value)
         {
             this.ShelvingState.UnshelveTime.Value = unshelveTime;
             this.ClearChangeMasks(context, true);
         }
     }
     catch (Exception e)
     {
         Utils.LogError(e, "Unexpected error updating UnshelveTime.");
     }
 }
예제 #3
0
        public async Task <X509Certificate2Collection> GetCertificates()
        {
            X509Certificate2Collection collection = new X509Certificate2Collection();

            CertificateStoreIdentifier id = new CertificateStoreIdentifier();

            id.StoreType = this.StoreType;
            id.StorePath = this.StorePath;

            if (!String.IsNullOrEmpty(id.StorePath))
            {
                try
                {
                    ICertificateStore store = id.OpenStore();

                    try
                    {
                        collection = await store.Enumerate().ConfigureAwait(false);
                    }
                    finally
                    {
                        store.Close();
                    }
                }
                catch (Exception)
                {
                    // TODO check all StorePath references to not leak information
                    Utils.LogError("Could not load certificates from store: {0}.", this.StorePath);
                }
            }

            foreach (CertificateIdentifier trustedCertificate in TrustedCertificates)
            {
                X509Certificate2 certificate = await trustedCertificate.Find().ConfigureAwait(false);

                if (certificate != null)
                {
                    collection.Add(certificate);
                }
            }

            return(collection);
        }
예제 #4
0
        /// <summary>
        /// Finds a certificate in a store.
        /// </summary>
        /// <param name="needPrivateKey">if set to <c>true</c> the returned certificate must contain the private key.</param>
        /// <returns>An instance of the <see cref="X509Certificate2"/> that is embedded by this instance or find it in
        /// the selected store pointed out by the <see cref="StorePath"/> using selected <see cref="SubjectName"/>.</returns>
        public async Task <X509Certificate2> Find(bool needPrivateKey)
        {
            X509Certificate2 certificate = null;

            // check if the entire certificate has been specified.
            if (m_certificate != null && (!needPrivateKey || m_certificate.HasPrivateKey))
            {
                certificate = m_certificate;
            }
            else
            {
                // open store.
                using (ICertificateStore store = CertificateStoreIdentifier.CreateStore(StoreType))
                {
                    store.Open(StorePath);

                    X509Certificate2Collection collection = await store.Enumerate().ConfigureAwait(false);

                    certificate = Find(collection, m_thumbprint, m_subjectName, needPrivateKey);

                    if (certificate != null)
                    {
                        m_certificate = certificate;

                        if (needPrivateKey && this.StoreType == CertificateStoreType.Directory)
                        {
                            var message = new StringBuilder();
                            message.AppendLine("Loaded a certificate with private key from the directory store.");
                            message.AppendLine("Ensure to call LoadPrivateKeyEx with password provider before calling Find(true).");
                            Utils.LogError(message.ToString());
                        }
                    }
                }
            }

            // use the single instance in the certificate cache.
            if (needPrivateKey)
            {
                certificate = m_certificate = CertificateFactory.Load(certificate, true);
            }

            return(certificate);
        }
예제 #5
0
 public void Exception(Exception ex, string format, params object[] args)
 {
     if (IsEnabled())
     {
         var message = Utils.TraceExceptionMessage(ex, format, args).ToString();
         if (ex is ServiceResultException sre)
         {
             ServiceResultException((int)sre.StatusCode, message);
         }
         else
         {
             Exception(message);
         }
     }
     else
     {
         Utils.LogError(ex, format, args);
     }
 }
        /// <summary>
        /// Reports AuditProgramTransition event
        /// </summary>
        /// <param name="context"></param>
        /// <param name="causeMethod"></param>
        /// <param name="causeId"></param>
        /// <param name="inputArguments"></param>
        /// <param name="result"></param>
        protected virtual void ReportAuditProgramTransitionEvent(ISystemContext context,
                                                                 MethodState causeMethod,
                                                                 uint causeId,
                                                                 IList <object> inputArguments,
                                                                 ServiceResult result)
        {
            try
            {
                AuditProgramTransitionEventState e = new AuditProgramTransitionEventState(null);

                UpdateAuditEvent(context, causeMethod, inputArguments, causeId, e, result);

                e.SetChildValue(context, BrowseNames.TransitionNumber, LastTransition.Number.Value, false);

                ReportEvent(context, e);
            }
            catch (Exception ex)
            {
                Utils.LogError(ex, "Error while reporting AuditProgramTransitionEvent event.");
            }
        }
예제 #7
0
            /// <summary>
            /// Called when asynchronous operation completes.
            /// </summary>
            /// <param name="ar">The asynchronous result object.</param>
            public void OnOperationCompleted(IAsyncResult ar)
            {
                try
                {
                    // check if the begin operation has had a chance to complete.
                    lock (Lock)
                    {
                        if (InnerResult == null)
                        {
                            InnerResult = ar;
                        }
                    }

                    // signal that the operation is complete.
                    OperationCompleted();
                }
                catch (Exception e)
                {
                    Utils.LogError(e, "Unexpected exception invoking UaChannelAsyncResult callback function.");
                }
            }
예제 #8
0
        /// <summary>
        /// Encrypts the data using RSA PKCS#1 v1.5 or OAEP encryption.
        /// </summary>
        private static ArraySegment <byte> Encrypt(
            ArraySegment <byte> dataToEncrypt,
            RSA rsa,
            Padding padding,
            ArraySegment <byte> outputBuffer)
        {
            int inputBlockSize  = GetPlainTextBlockSize(rsa, padding);
            int outputBlockSize = GetCipherTextBlockSize(rsa, padding);

            // verify the input data is the correct block size.
            if (dataToEncrypt.Count % inputBlockSize != 0)
            {
                Utils.LogError("Message is not an integral multiple of the block size. Length = {0}, BlockSize = {1}.", dataToEncrypt.Count, inputBlockSize);
            }

            byte[] encryptedBuffer          = outputBuffer.Array;
            RSAEncryptionPadding rsaPadding = GetRSAEncryptionPadding(padding);

            using (MemoryStream ostrm = new MemoryStream(
                       encryptedBuffer,
                       outputBuffer.Offset,
                       outputBuffer.Count))
            {
                // encrypt body.
                byte[] input = new byte[inputBlockSize];

                for (int ii = dataToEncrypt.Offset; ii < dataToEncrypt.Offset + dataToEncrypt.Count; ii += inputBlockSize)
                {
                    Array.Copy(dataToEncrypt.Array, ii, input, 0, input.Length);
                    byte[] cipherText = rsa.Encrypt(input, rsaPadding);
                    ostrm.Write(cipherText, 0, cipherText.Length);
                }
            }

            // return buffer
            return(new ArraySegment <byte>(
                       encryptedBuffer,
                       outputBuffer.Offset,
                       (dataToEncrypt.Count / inputBlockSize) * outputBlockSize));
        }
예제 #9
0
        /// <summary>
        /// Reads the current contents of the directory from disk.
        /// </summary>
        private IDictionary <string, Entry> Load(string thumbprint)
        {
            lock (m_lock)
            {
                DateTime now = DateTime.UtcNow;

                // refresh the directories.
                if (m_certificateSubdir != null)
                {
                    m_certificateSubdir.Refresh();
                }

                if (!NoPrivateKeys)
                {
                    if (m_privateKeySubdir != null)
                    {
                        m_privateKeySubdir.Refresh();
                    }
                }

                // check if store exists.
                if (!m_certificateSubdir.Exists)
                {
                    m_certificates.Clear();
                    return(m_certificates);
                }

                // check if cache is still good.
                if ((m_certificateSubdir.LastWriteTimeUtc < m_lastDirectoryCheck) &&
                    (NoPrivateKeys || !m_privateKeySubdir.Exists || m_privateKeySubdir.LastWriteTimeUtc < m_lastDirectoryCheck))
                {
                    return(m_certificates);
                }

                m_certificates.Clear();
                m_lastDirectoryCheck = now;
                bool incompleteSearch = false;

                // check for public keys.
                foreach (FileInfo file in m_certificateSubdir.GetFiles("*.der"))
                {
                    try
                    {
                        Entry entry = new Entry();

                        entry.Certificate               = new X509Certificate2(file.FullName);
                        entry.CertificateFile           = file;
                        entry.PrivateKeyFile            = null;
                        entry.CertificateWithPrivateKey = null;

                        if (!NoPrivateKeys)
                        {
                            string fileRoot = file.Name.Substring(0, entry.CertificateFile.Name.Length - entry.CertificateFile.Extension.Length);

                            StringBuilder filePath = new StringBuilder();
                            filePath.Append(m_privateKeySubdir.FullName);
                            filePath.Append(Path.DirectorySeparatorChar);
                            filePath.Append(fileRoot);

                            entry.PrivateKeyFile = new FileInfo(filePath.ToString() + ".pfx");

                            // check for PFX file.
                            if (entry.PrivateKeyFile.Exists)
                            {
                                try
                                {
                                    X509Certificate2 certificate = new X509Certificate2(
                                        entry.PrivateKeyFile.FullName
                                        );

                                    if (certificate.HasPrivateKey)
                                    {
                                        entry.CertificateWithPrivateKey = certificate;
                                    }
                                }
                                catch (Exception e)
                                {
                                    Utils.LogError(e, "Could not load private key certificate from file: {0}", entry.PrivateKeyFile.Name);
                                }
                            }

                            // check for PEM file.
                            else
                            {
                                entry.PrivateKeyFile = new FileInfo(filePath.ToString() + ".pem");

                                if (!entry.PrivateKeyFile.Exists)
                                {
                                    entry.PrivateKeyFile = null;
                                }
                            }
                        }

                        m_certificates[entry.Certificate.Thumbprint] = entry;

                        if (!String.IsNullOrEmpty(thumbprint) && thumbprint == entry.Certificate.Thumbprint)
                        {
                            incompleteSearch = true;
                            break;
                        }
                    }
                    catch (Exception e)
                    {
                        Utils.LogError(e, "Could not load certificate from file: {0}", file.FullName);
                    }
                }

                if (incompleteSearch)
                {
                    m_lastDirectoryCheck = DateTime.MinValue;
                }

                return(m_certificates);
            }
        }
예제 #10
0
        /// <summary>
        /// Checks if issuer has revoked the certificate.
        /// </summary>
        public StatusCode IsRevoked(X509Certificate2 issuer, X509Certificate2 certificate)
        {
            if (issuer == null)
            {
                throw new ArgumentNullException(nameof(issuer));
            }

            if (certificate == null)
            {
                throw new ArgumentNullException(nameof(certificate));
            }

            // check for CRL.
            DirectoryInfo info = new DirectoryInfo(this.Directory.FullName + Path.DirectorySeparatorChar + "crl");

            if (info.Exists)
            {
                bool crlExpired = true;

                foreach (FileInfo file in info.GetFiles("*.crl"))
                {
                    X509CRL crl = null;

                    try
                    {
                        crl = new X509CRL(file.FullName);
                    }
                    catch (Exception e)
                    {
                        Utils.LogError(e, "Could not parse CRL file.");
                        continue;
                    }

                    if (!X509Utils.CompareDistinguishedName(crl.Issuer, issuer.Subject))
                    {
                        continue;
                    }

                    if (!crl.VerifySignature(issuer, false))
                    {
                        continue;
                    }

                    if (crl.IsRevoked(certificate))
                    {
                        return(StatusCodes.BadCertificateRevoked);
                    }

                    if (crl.ThisUpdate <= DateTime.UtcNow && (crl.NextUpdate == DateTime.MinValue || crl.NextUpdate >= DateTime.UtcNow))
                    {
                        crlExpired = false;
                    }
                }

                // certificate is fine.
                if (!crlExpired)
                {
                    return(StatusCodes.Good);
                }
            }

            // can't find a valid CRL.
            return(StatusCodes.BadCertificateRevocationUnknown);
        }
예제 #11
0
        /// <summary>
        /// Loads the private key from a PFX file in the certificate store.
        /// </summary>
        public X509Certificate2 LoadPrivateKey(string thumbprint, string subjectName, string password)
        {
            if (m_certificateSubdir == null || !m_certificateSubdir.Exists)
            {
                return(null);
            }

            if (string.IsNullOrEmpty(thumbprint) && string.IsNullOrEmpty(subjectName))
            {
                return(null);
            }

            foreach (FileInfo file in m_certificateSubdir.GetFiles("*.der"))
            {
                try
                {
                    X509Certificate2 certificate = new X509Certificate2(file.FullName);

                    if (!String.IsNullOrEmpty(thumbprint))
                    {
                        if (!string.Equals(certificate.Thumbprint, thumbprint, StringComparison.CurrentCultureIgnoreCase))
                        {
                            continue;
                        }
                    }

                    if (!String.IsNullOrEmpty(subjectName))
                    {
                        if (!X509Utils.CompareDistinguishedName(subjectName, certificate.Subject))
                        {
                            if (subjectName.Contains('='))
                            {
                                continue;
                            }

                            if (!X509Utils.ParseDistinguishedName(certificate.Subject).Any(s => s.Equals("CN=" + subjectName, StringComparison.OrdinalIgnoreCase)))
                            {
                                continue;
                            }
                        }
                    }

                    // skip if not RSA certificate
                    if (X509Utils.GetRSAPublicKeySize(certificate) < 0)
                    {
                        continue;
                    }

                    string fileRoot = file.Name.Substring(0, file.Name.Length - file.Extension.Length);

                    StringBuilder filePath = new StringBuilder()
                                             .Append(m_privateKeySubdir.FullName)
                                             .Append(Path.DirectorySeparatorChar)
                                             .Append(fileRoot);

                    X509KeyStorageFlags[] storageFlags =
                    {
                        X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet,
                        X509KeyStorageFlags.Exportable | X509KeyStorageFlags.UserKeySet
                    };

                    FileInfo privateKeyFile = new FileInfo(filePath.ToString() + ".pfx");
                    password = password ?? String.Empty;
                    foreach (var flag in storageFlags)
                    {
                        try
                        {
                            certificate = new X509Certificate2(
                                privateKeyFile.FullName,
                                password,
                                flag);
                            if (X509Utils.VerifyRSAKeyPair(certificate, certificate, true))
                            {
                                return(certificate);
                            }
                        }
                        catch (Exception)
                        {
                            certificate?.Dispose();
                            certificate = null;
                        }
                    }
                }
                catch (Exception e)
                {
                    Utils.LogError(e, "Could not load private key for certificate " + subjectName);
                }
            }

            return(null);
        }
        /// <summary>
        /// Loads the private key from a PFX/PEM file in the certificate store.
        /// </summary>
        public async Task <X509Certificate2> LoadPrivateKey(string thumbprint, string subjectName, string password)
        {
            if (NoPrivateKeys || m_certificateSubdir == null || !m_certificateSubdir.Exists)
            {
                return(null);
            }

            if (string.IsNullOrEmpty(thumbprint) && string.IsNullOrEmpty(subjectName))
            {
                return(null);
            }

            // on some platforms, specifically in virtualized environments,
            // reloading a previously created and saved private key may fail on the first attempt.
            const int retryDelay   = 100;
            int       retryCounter = 3;

            while (retryCounter-- > 0)
            {
                bool      certificateFound = false;
                Exception importException  = null;
                foreach (FileInfo file in m_certificateSubdir.GetFiles("*.der"))
                {
                    try
                    {
                        X509Certificate2 certificate = new X509Certificate2(file.FullName);

                        if (!String.IsNullOrEmpty(thumbprint))
                        {
                            if (!string.Equals(certificate.Thumbprint, thumbprint, StringComparison.OrdinalIgnoreCase))
                            {
                                continue;
                            }
                        }

                        if (!String.IsNullOrEmpty(subjectName))
                        {
                            if (!X509Utils.CompareDistinguishedName(subjectName, certificate.Subject))
                            {
                                if (subjectName.Contains('='))
                                {
                                    continue;
                                }

                                if (!X509Utils.ParseDistinguishedName(certificate.Subject).Any(s => s.Equals("CN=" + subjectName, StringComparison.Ordinal)))
                                {
                                    continue;
                                }
                            }
                        }

                        // skip if not RSA certificate
                        if (X509Utils.GetRSAPublicKeySize(certificate) < 0)
                        {
                            continue;
                        }

                        string fileRoot = file.Name.Substring(0, file.Name.Length - file.Extension.Length);

                        StringBuilder filePath = new StringBuilder()
                                                 .Append(m_privateKeySubdir.FullName)
                                                 .Append(Path.DirectorySeparatorChar)
                                                 .Append(fileRoot);

                        X509KeyStorageFlags[] storageFlags =
                        {
                            X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet,
                            X509KeyStorageFlags.Exportable | X509KeyStorageFlags.UserKeySet
                        };

                        FileInfo privateKeyFilePfx = new FileInfo(filePath + ".pfx");
                        FileInfo privateKeyFilePem = new FileInfo(filePath + ".pem");
                        password = password ?? String.Empty;
                        if (privateKeyFilePfx.Exists)
                        {
                            certificateFound = true;
                            foreach (var flag in storageFlags)
                            {
                                try
                                {
                                    certificate = new X509Certificate2(
                                        privateKeyFilePfx.FullName,
                                        password,
                                        flag);
                                    if (X509Utils.VerifyRSAKeyPair(certificate, certificate, true))
                                    {
                                        Utils.LogInfo(Utils.TraceMasks.Security, "Imported the PFX private key for [{0}].", certificate.Thumbprint);
                                        return(certificate);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    importException = ex;
                                    certificate?.Dispose();
                                }
                            }
                        }
                        // if PFX file doesn't exist, check for PEM file.
                        else if (privateKeyFilePem.Exists)
                        {
                            certificateFound = true;
                            try
                            {
                                byte[] pemDataBlob = File.ReadAllBytes(privateKeyFilePem.FullName);
                                certificate = CertificateFactory.CreateCertificateWithPEMPrivateKey(certificate, pemDataBlob, password);
                                if (X509Utils.VerifyRSAKeyPair(certificate, certificate, true))
                                {
                                    Utils.LogInfo(Utils.TraceMasks.Security, "Imported the PEM private key for [{0}].", certificate.Thumbprint);
                                    return(certificate);
                                }
                            }
                            catch (Exception exception)
                            {
                                certificate?.Dispose();
                                importException = exception;
                            }
                        }
                        else
                        {
                            Utils.LogError(Utils.TraceMasks.Security, "A private key for the certificate with thumbprint [{0}] does not exist.", certificate.Thumbprint);
                            continue;
                        }
                    }
                    catch (Exception e)
                    {
                        Utils.LogError(e, "Could not load private key for certificate {0}", subjectName);
                    }
                }

                // found a certificate, but some error occurred
                if (certificateFound)
                {
                    Utils.LogError(Utils.TraceMasks.Security, "The private key for the certificate with subject {0} failed to import.", subjectName);
                    if (importException != null)
                    {
                        Utils.LogError(importException, "Certificate import failed.");
                    }
                }
                else
                {
                    if (!String.IsNullOrEmpty(thumbprint))
                    {
                        Utils.LogError(Utils.TraceMasks.Security, "A Private key for the certificate with thumbpint {0} was not found.", thumbprint);
                    }
                    // if no private key was found, no need to retry
                    break;
                }

                // retry within a few ms
                if (retryCounter > 0)
                {
                    Utils.LogInfo(Utils.TraceMasks.Security, "Retry to import private key after {0} ms.", retryDelay);
                    await Task.Delay(retryDelay).ConfigureAwait(false);
                }
            }

            return(null);
        }