Module: wine
Branch: master
Commit: fd993b7d9dae06740d595443a9a262da8c787020
URL: http://source.winehq.org/git/wine.git/?a=commit;h=fd993b7d9dae06740d595443a…
Author: Vincent Povirk <vincent(a)codeweavers.com>
Date: Wed Oct 28 14:06:23 2009 -0500
ole32: Remove directory entries from the tree before we free them.
The directory entry should still be valid as long as it's in the tree.
---
dlls/ole32/storage32.c | 32 +++++++++-----------------------
1 files changed, 9 insertions(+), 23 deletions(-)
diff --git a/dlls/ole32/storage32.c b/dlls/ole32/storage32.c
index 89ae657..18ced72 100644
--- a/dlls/ole32/storage32.c
+++ b/dlls/ole32/storage32.c
@@ -1817,6 +1817,15 @@ static HRESULT WINAPI StorageImpl_DestroyElement(
parentPropertyId,
typeOfRelation);
+ /*
+ * Invalidate the property by zeroing its name member.
+ */
+ propertyToDelete.sizeOfNameString = 0;
+
+ StorageImpl_WriteProperty(This->base.ancestorStorage,
+ foundPropertyIndexToDelete,
+ &propertyToDelete);
+
return hr;
}
@@ -1936,15 +1945,6 @@ static HRESULT deleteStorageProperty(
} while ((hr == S_OK) && (destroyHr == S_OK));
- /*
- * Invalidate the property by zeroing its name member.
- */
- propertyToDelete.sizeOfNameString = 0;
-
- StorageImpl_WriteProperty(parentStorage->base.ancestorStorage,
- indexOfPropertyToDelete,
- &propertyToDelete);
-
IStorage_Release(childStorage);
IEnumSTATSTG_Release(elements);
@@ -1993,20 +1993,6 @@ static HRESULT deleteStreamProperty(
*/
IStream_Release(pis);
- /*
- * Invalidate the property by zeroing its name member.
- */
- propertyToDelete.sizeOfNameString = 0;
-
- /*
- * Here we should re-read the property so we get the updated pointer
- * but since we are here to zap it, I don't do it...
- */
- StorageImpl_WriteProperty(
- parentStorage->base.ancestorStorage,
- indexOfPropertyToDelete,
- &propertyToDelete);
-
return S_OK;
}
Module: wine
Branch: master
Commit: 07b735682bfcd5999b3306865e5158a56f7b21b5
URL: http://source.winehq.org/git/wine.git/?a=commit;h=07b735682bfcd5999b3306865…
Author: Juan Lang <juan.lang(a)gmail.com>
Date: Wed Oct 28 17:33:24 2009 -0700
crypt32: Check CA certificates for the enhanced key usage extension.
---
dlls/crypt32/chain.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 59 insertions(+), 0 deletions(-)
diff --git a/dlls/crypt32/chain.c b/dlls/crypt32/chain.c
index 0637646..90093ae 100644
--- a/dlls/crypt32/chain.c
+++ b/dlls/crypt32/chain.c
@@ -1173,6 +1173,58 @@ static BOOL CRYPT_KeyUsageValid(PCertificateChainEngine engine,
return ret;
}
+static BOOL CRYPT_ExtendedKeyUsageValidForCA(PCCERT_CONTEXT cert)
+{
+ PCERT_EXTENSION ext;
+ BOOL ret;
+
+ /* RFC 5280, section 4.2.1.12: "In general, this extension will only
+ * appear in end entity certificates." And, "If a certificate contains
+ * both a key usage extension and an extended key usage extension, then
+ * both extensions MUST be processed independently and the certificate MUST
+ * only be used for a purpose consistent with both extensions." This seems
+ * to imply that it should be checked if present, and ignored if not.
+ * Unfortunately some CAs, e.g. the Thawte SGC CA, don't include the code
+ * signing extended key usage, whereas they do include the keyCertSign
+ * key usage. Thus, when checking for a CA, we only require the
+ * code signing extended key usage if the extended key usage is critical.
+ */
+ ext = CertFindExtension(szOID_ENHANCED_KEY_USAGE,
+ cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension);
+ if (ext && ext->fCritical)
+ {
+ CERT_ENHKEY_USAGE *usage;
+ DWORD size;
+
+ ret = CryptDecodeObjectEx(cert->dwCertEncodingType,
+ X509_ENHANCED_KEY_USAGE, ext->Value.pbData, ext->Value.cbData,
+ CRYPT_DECODE_ALLOC_FLAG, NULL, &usage, &size);
+ if (ret)
+ {
+ DWORD i;
+
+ /* Explicitly require the code signing extended key usage for a CA
+ * with an extended key usage extension. That is, don't assume
+ * a cert is allowed to be a CA if it specifies the
+ * anyExtendedKeyUsage usage oid. See again RFC 5280, section
+ * 4.2.1.12: "Applications that require the presence of a
+ * particular purpose MAY reject certificates that include the
+ * anyExtendedKeyUsage OID but not the particular OID expected for
+ * the application."
+ */
+ ret = FALSE;
+ for (i = 0; !ret && i < usage->cUsageIdentifier; i++)
+ if (!strcmp(usage->rgpszUsageIdentifier[i],
+ szOID_PKIX_KP_CODE_SIGNING))
+ ret = TRUE;
+ LocalFree(usage);
+ }
+ }
+ else
+ ret = TRUE;
+ return ret;
+}
+
static BOOL CRYPT_CriticalExtensionsSupported(PCCERT_CONTEXT cert)
{
BOOL ret = TRUE;
@@ -1196,6 +1248,8 @@ static BOOL CRYPT_CriticalExtensionsSupported(PCCERT_CONTEXT cert)
ret = TRUE;
else if (!strcmp(oid, szOID_SUBJECT_ALT_NAME2))
ret = TRUE;
+ else if (!strcmp(oid, szOID_ENHANCED_KEY_USAGE))
+ ret = TRUE;
else
{
FIXME("unsupported critical extension %s\n",
@@ -1265,6 +1319,11 @@ static void CRYPT_CheckSimpleChain(PCertificateChainEngine engine,
constraints.fCA, i))
chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
CERT_TRUST_IS_NOT_VALID_FOR_USAGE;
+ if (i != 0)
+ if (!CRYPT_ExtendedKeyUsageValidForCA(
+ chain->rgpElement[i]->pCertContext))
+ chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
+ CERT_TRUST_IS_NOT_VALID_FOR_USAGE;
if (CRYPT_IsSimpleChainCyclic(chain))
{
/* If the chain is cyclic, then the path length constraints
Module: wine
Branch: master
Commit: 60770fb011b0a60d7862e7fe9c7a6d24d68ac0ad
URL: http://source.winehq.org/git/wine.git/?a=commit;h=60770fb011b0a60d7862e7fe9…
Author: Juan Lang <juan.lang(a)gmail.com>
Date: Wed Oct 28 17:32:39 2009 -0700
crypt32: Only permit v1 or v2 CA certificates without a key usage extension if they're installed locally.
---
dlls/crypt32/chain.c | 44 +++++++++++++++++++++++++-------------------
1 files changed, 25 insertions(+), 19 deletions(-)
diff --git a/dlls/crypt32/chain.c b/dlls/crypt32/chain.c
index 5802773..0637646 100644
--- a/dlls/crypt32/chain.c
+++ b/dlls/crypt32/chain.c
@@ -1082,8 +1082,8 @@ static void dump_element(PCCERT_CONTEXT cert)
dump_extension(&cert->pCertInfo->rgExtension[i]);
}
-static BOOL CRYPT_KeyUsageValid(PCCERT_CONTEXT cert, BOOL isRoot, BOOL isCA,
- DWORD index)
+static BOOL CRYPT_KeyUsageValid(PCertificateChainEngine engine,
+ PCCERT_CONTEXT cert, BOOL isCA, DWORD index)
{
PCERT_EXTENSION ext;
BOOL ret;
@@ -1121,20 +1121,33 @@ static BOOL CRYPT_KeyUsageValid(PCCERT_CONTEXT cert, BOOL isRoot, BOOL isCA,
{
if (!ext)
{
- /* MS appears to violate RFC 3280, section 4.2.1.3 (Key Usage)
+ /* MS appears to violate RFC 5280, section 4.2.1.3 (Key Usage)
* here. Quoting the RFC:
* "This [key usage] extension MUST appear in certificates that
* contain public keys that are used to validate digital signatures
* on other public key certificates or CRLs."
- * Most of the test chains' certs do not contain key usage
- * extensions, yet are allowed to be CA certs. This appears to
- * be common usage too: the root CA in a chain often does not have
- * the key usage extension. We are a little more restrictive:
- * root certs, which commonly do not have any extensions, are
- * allowed to sign certificates without the key usage extension.
+ * MS appears to accept certs that do not contain key usage
+ * extensions as CA certs. V1 and V2 certificates did not have
+ * extensions, and many root certificates are V1 certificates, so
+ * perhaps this is prudent. On the other hand, MS also accepts V3
+ * certs without key usage extensions. We are more restrictive:
+ * we accept locally installed V1 or V2 certs as CA certs.
*/
- WARN_(chain)("no key usage extension on a CA cert\n");
- ret = isRoot;
+ ret = FALSE;
+ if (cert->pCertInfo->dwVersion == CERT_V1 ||
+ cert->pCertInfo->dwVersion == CERT_V2)
+ {
+ PCCERT_CONTEXT localCert = CRYPT_FindCertInStore(
+ engine->hWorld, cert);
+
+ if (localCert)
+ {
+ CertFreeCertificateContext(localCert);
+ ret = TRUE;
+ }
+ }
+ if (!ret)
+ WARN_(chain)("no key usage extension on a CA cert\n");
}
else
{
@@ -1206,19 +1219,12 @@ static void CRYPT_CheckSimpleChain(PCertificateChainEngine engine,
chain->cElement, debugstr_w(filetime_to_str(time)));
for (i = chain->cElement - 1; i >= 0; i--)
{
- BOOL isRoot;
-
if (TRACE_ON(chain))
dump_element(chain->rgpElement[i]->pCertContext);
if (CertVerifyTimeValidity(time,
chain->rgpElement[i]->pCertContext->pCertInfo) != 0)
chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
CERT_TRUST_IS_NOT_TIME_VALID;
- if (i == chain->cElement - 1)
- isRoot = CRYPT_IsCertificateSelfSigned(
- chain->rgpElement[i]->pCertContext);
- else
- isRoot = FALSE;
if (i != 0)
{
/* Check the signature of the cert this issued */
@@ -1255,7 +1261,7 @@ static void CRYPT_CheckSimpleChain(PCertificateChainEngine engine,
chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
CERT_TRUST_INVALID_BASIC_CONSTRAINTS;
}
- if (!CRYPT_KeyUsageValid(chain->rgpElement[i]->pCertContext, isRoot,
+ if (!CRYPT_KeyUsageValid(engine, chain->rgpElement[i]->pCertContext,
constraints.fCA, i))
chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
CERT_TRUST_IS_NOT_VALID_FOR_USAGE;