private Byte[] GetBinaryRequestProperty(ref CCertServerExit server, string name) { // https://blogs.msdn.microsoft.com/alejacma/2008/08/04/how-to-modify-an-interop-assembly-to-change-the-return-type-of-a-method-vb-net/ IntPtr variantObjectPtr = Marshal.AllocHGlobal(2048); try { IntPtr bstrPtr; int bstrLen; // Get VARIANT containing certificate bytes // Read ANSI BSTR information from the VARIANT as we know RawCertificate property is ANSI BSTR. server.GetRequestProperty(name, (int)PropertyType.PROPTYPE_BINARY, variantObjectPtr); bstrPtr = Marshal.ReadIntPtr(variantObjectPtr, 8); bstrLen = Marshal.ReadInt32(bstrPtr, -4); byte[] result = new byte[bstrLen]; Marshal.Copy(bstrPtr, result, 0, bstrLen); return(result); } catch { return(null); } finally { VariantClear(variantObjectPtr); Marshal.FreeHGlobal(variantObjectPtr); } }
private int GetLongRequestProperty(ref CCertServerExit server, string name) { IntPtr variantObjectPtr = Marshal.AllocHGlobal(2048); try { server.GetRequestProperty(name, (int)PropertyType.PROPTYPE_LONG, variantObjectPtr); var result = (int)(Marshal.GetObjectForNativeVariant(variantObjectPtr)); return(result); } catch { return(0); } finally { VariantClear(variantObjectPtr); Marshal.FreeHGlobal(variantObjectPtr); } }
private DateTime GetDateCertificateProperty(ref CCertServerExit server, string name) { IntPtr variantObjectPtr = Marshal.AllocHGlobal(2048); try { server.GetCertificateProperty(name, (int)PropertyType.PROPTYPE_DATE, variantObjectPtr); var result = (DateTime)(Marshal.GetObjectForNativeVariant(variantObjectPtr)); return(result); } catch { return(new DateTime()); } finally { VariantClear(variantObjectPtr); Marshal.FreeHGlobal(variantObjectPtr); } }
private string GetStringCertificateProperty(ref CCertServerExit server, string name) { IntPtr variantObjectPtr = Marshal.AllocHGlobal(2048); try { server.GetCertificateProperty(name, (int)PropertyType.PROPTYPE_STRING, variantObjectPtr); var result = (string)(Marshal.GetObjectForNativeVariant(variantObjectPtr)); return(result); } catch { return(null); } finally { VariantClear(variantObjectPtr); Marshal.FreeHGlobal(variantObjectPtr); } }
public void Notify(int ExitEvent, int Context) { switch (ExitEvent) { case (int)ExitEvents.CertIssued: var CertServer = new CCertServerExit(); var CertificateInfo = new IssuedCertificate(); // Retrieving CA Properties // The context must be zero to read any of these properties. The context is set to zero when the ICertServerExit object is initially created. // It can also be set to zero by invoking the SetContext method. CertServer.SetContext(0); CertificateInfo.Issuer = GetStringCertificateProperty(ref CertServer, "SanitizedCAName"); // Must be called before querying Certificate properties // https://docs.microsoft.com/en-us/windows/win32/api/certif/nf-certif-icertserverexit-setcontext CertServer.SetContext(Context); // Retrieving Certificate Properties // https://docs.microsoft.com/en-us/windows/win32/api/certif/nf-certif-icertserverexit-getcertificateproperty CertificateInfo.RawCertificate = Convert.ToBase64String( GetBinaryCertificateProperty(ref CertServer, "RawCertificate"), Base64FormattingOptions.None ); CertificateInfo.RequestId = GetLongCertificateProperty(ref CertServer, "RequestId"); CertificateInfo.SerialNumber = GetStringCertificateProperty(ref CertServer, "SerialNumber"); CertificateInfo.Subject = GetStringCertificateProperty(ref CertServer, "DistinguishedName"); CertificateInfo.NotBefore = GetDateCertificateProperty(ref CertServer, "NotBefore"); CertificateInfo.NotAfter = GetDateCertificateProperty(ref CertServer, "NotAfter"); // Retrieving Request Properties // https://docs.microsoft.com/de-de/windows/win32/api/certif/nf-certif-icertserverexit-getrequestproperty CertificateInfo.RawRequest = Convert.ToBase64String( GetBinaryRequestProperty(ref CertServer, "RawRequest"), Base64FormattingOptions.None ); CertificateInfo.RequesterName = GetStringRequestProperty(ref CertServer, "RequesterName"); CertificateInfo.RequestType = GetLongRequestProperty(ref CertServer, "RequestType"); // TODO: Can we access the "Name Properties" here, and should we, in Terms of accessing the CA Database...? // https://docs.microsoft.com/en-us/windows/win32/seccrypto/name-properties // Serialize to XML var OutputXmlSerializer = new XmlSerializer(typeof(IssuedCertificate)); var OutputFileName = CertificateInfo.RequestId.ToString() + ".xml"; /* * OutputFileName.Replace("%1", CertificateInfo.RequestId.ToString()); * OutputFileName.Replace("%2", CertificateInfo.Issuer); * OutputFileName.Replace("%3", CertificateInfo.SerialNumber); */ using (var OutputStringWriter = new StringWriter()) { using (XmlWriter OutputXmlWriter = XmlWriter.Create(OutputStringWriter)) { OutputXmlSerializer.Serialize(OutputXmlWriter, CertificateInfo); if (OutputDirectory != null) { System.IO.File.WriteAllText( OutputDirectory + @"\" + OutputFileName, PrettyXml(OutputStringWriter.ToString()) ); } } } break; } }