/// <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."); } }
/// <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."); } }
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); }
/// <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); }
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."); } }
/// <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."); } }
/// <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)); }
/// <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); } }
/// <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); }
/// <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); }