Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
caf5ae19
Commit
caf5ae19
authored
Mar 22, 2023
by
Paul Gofman
Committed by
Alexandre Julliard
Mar 24, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
crypt32: Keep root certs cached in registry unless some are deleted on host.
parent
463bd7c3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
110 additions
and
18 deletions
+110
-18
crypt32_private.h
dlls/crypt32/crypt32_private.h
+2
-0
regstore.c
dlls/crypt32/regstore.c
+1
-1
rootstore.c
dlls/crypt32/rootstore.c
+107
-17
No files found.
dlls/crypt32/crypt32_private.h
View file @
caf5ae19
...
@@ -349,6 +349,8 @@ WINECRYPT_CERTSTORE *CRYPT_FileNameOpenStoreW(HCRYPTPROV hCryptProv,
...
@@ -349,6 +349,8 @@ WINECRYPT_CERTSTORE *CRYPT_FileNameOpenStoreW(HCRYPTPROV hCryptProv,
void
CRYPT_ImportSystemRootCertsToReg
(
void
)
DECLSPEC_HIDDEN
;
void
CRYPT_ImportSystemRootCertsToReg
(
void
)
DECLSPEC_HIDDEN
;
BOOL
CRYPT_SerializeContextsToReg
(
HKEY
key
,
DWORD
flags
,
const
WINE_CONTEXT_INTERFACE
*
contextInterface
,
BOOL
CRYPT_SerializeContextsToReg
(
HKEY
key
,
DWORD
flags
,
const
WINE_CONTEXT_INTERFACE
*
contextInterface
,
HCERTSTORE
memStore
)
DECLSPEC_HIDDEN
;
HCERTSTORE
memStore
)
DECLSPEC_HIDDEN
;
void
CRYPT_RegReadSerializedFromReg
(
HKEY
key
,
DWORD
contextType
,
HCERTSTORE
store
,
DWORD
disposition
)
DECLSPEC_HIDDEN
;
DWORD
CRYPT_IsCertificateSelfSigned
(
const
CERT_CONTEXT
*
cert
)
DECLSPEC_HIDDEN
;
DWORD
CRYPT_IsCertificateSelfSigned
(
const
CERT_CONTEXT
*
cert
)
DECLSPEC_HIDDEN
;
...
...
dlls/crypt32/regstore.c
View file @
caf5ae19
...
@@ -56,7 +56,7 @@ static void CRYPT_HashToStr(const BYTE *hash, LPWSTR asciiHash)
...
@@ -56,7 +56,7 @@ static void CRYPT_HashToStr(const BYTE *hash, LPWSTR asciiHash)
wsprintfW
(
asciiHash
+
i
*
2
,
L"%02X"
,
hash
[
i
]);
wsprintfW
(
asciiHash
+
i
*
2
,
L"%02X"
,
hash
[
i
]);
}
}
static
void
CRYPT_RegReadSerializedFromReg
(
HKEY
key
,
DWORD
contextType
,
HCERTSTORE
store
,
DWORD
disposition
)
void
CRYPT_RegReadSerializedFromReg
(
HKEY
key
,
DWORD
contextType
,
HCERTSTORE
store
,
DWORD
disposition
)
{
{
LONG
rc
;
LONG
rc
;
DWORD
index
=
0
;
DWORD
index
=
0
;
...
...
dlls/crypt32/rootstore.c
View file @
caf5ae19
...
@@ -98,7 +98,7 @@ static const char *get_cert_common_name(PCCERT_CONTEXT cert)
...
@@ -98,7 +98,7 @@ static const char *get_cert_common_name(PCCERT_CONTEXT cert)
return
name
;
return
name
;
}
}
static
void
check_and_store_certs
(
HCERTSTORE
from
,
HCERTSTORE
to
)
static
void
check_and_store_certs
(
HCERTSTORE
cached
,
HCERTSTORE
new
,
HCERTSTORE
to
)
{
{
DWORD
root_count
=
0
;
DWORD
root_count
=
0
;
CERT_CHAIN_ENGINE_CONFIG
chainEngineConfig
=
CERT_CHAIN_ENGINE_CONFIG
chainEngineConfig
=
...
@@ -114,14 +114,14 @@ static void check_and_store_certs(HCERTSTORE from, HCERTSTORE to)
...
@@ -114,14 +114,14 @@ static void check_and_store_certs(HCERTSTORE from, HCERTSTORE to)
PCCERT_CONTEXT
cert
=
NULL
;
PCCERT_CONTEXT
cert
=
NULL
;
do
{
do
{
cert
=
CertEnumCertificatesInStore
(
from
,
cert
);
cert
=
CertEnumCertificatesInStore
(
new
,
cert
);
if
(
cert
)
if
(
cert
)
{
{
CERT_CHAIN_PARA
chainPara
=
{
sizeof
(
chainPara
),
{
0
}
};
CERT_CHAIN_PARA
chainPara
=
{
sizeof
(
chainPara
),
{
0
}
};
PCCERT_CHAIN_CONTEXT
chain
;
PCCERT_CHAIN_CONTEXT
chain
;
BOOL
ret
;
BOOL
ret
;
ret
=
CertGetCertificateChain
(
engine
,
cert
,
NULL
,
from
,
ret
=
CertGetCertificateChain
(
engine
,
cert
,
NULL
,
cached
,
&
chainPara
,
CERT_CHAIN_CACHE_ONLY_URL_RETRIEVAL
,
NULL
,
&
chain
);
&
chainPara
,
CERT_CHAIN_CACHE_ONLY_URL_RETRIEVAL
,
NULL
,
&
chain
);
if
(
!
ret
)
if
(
!
ret
)
TRACE
(
"rejecting %s: %s
\n
"
,
get_cert_common_name
(
cert
),
TRACE
(
"rejecting %s: %s
\n
"
,
get_cert_common_name
(
cert
),
...
@@ -595,16 +595,28 @@ static const struct CONST_BLOB {
...
@@ -595,16 +595,28 @@ static const struct CONST_BLOB {
{
rootcertauthority2011
,
sizeof
(
rootcertauthority2011
)
},
{
rootcertauthority2011
,
sizeof
(
rootcertauthority2011
)
},
};
};
static
void
add_ms_root_certs
(
HCERTSTORE
to
)
static
void
add_ms_root_certs
(
HCERTSTORE
to
,
HCERTSTORE
cached
)
{
{
PCCERT_CONTEXT
cert
,
existing
;
DWORD
i
;
DWORD
i
;
TRACE
(
"
\n
"
);
TRACE
(
"
\n
"
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
msRootCerts
);
i
++
)
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
msRootCerts
);
i
++
)
{
if
(
!
CertAddEncodedCertificateToStore
(
to
,
X509_ASN_ENCODING
,
if
(
!
CertAddEncodedCertificateToStore
(
to
,
X509_ASN_ENCODING
,
msRootCerts
[
i
].
pb
,
msRootCerts
[
i
].
cb
,
CERT_STORE_ADD_NEW
,
NULL
))
msRootCerts
[
i
].
pb
,
msRootCerts
[
i
].
cb
,
CERT_STORE_ADD_NEW
,
&
cert
))
{
WARN
(
"adding root cert %ld failed: %08lx
\n
"
,
i
,
GetLastError
());
WARN
(
"adding root cert %ld failed: %08lx
\n
"
,
i
,
GetLastError
());
continue
;
}
if
((
existing
=
CertFindCertificateInStore
(
cached
,
X509_ASN_ENCODING
,
0
,
CERT_FIND_EXISTING
,
cert
,
NULL
)))
{
CertDeleteCertificateFromStore
(
existing
);
CertFreeCertificateContext
(
existing
);
}
CertFreeCertificateContext
(
cert
);
}
}
}
/* Reads certificates from the list of known locations into store. Stops when
/* Reads certificates from the list of known locations into store. Stops when
...
@@ -612,15 +624,29 @@ static void add_ms_root_certs(HCERTSTORE to)
...
@@ -612,15 +624,29 @@ static void add_ms_root_certs(HCERTSTORE to)
* adding redundant certificates, e.g. when both a certificate bundle and
* adding redundant certificates, e.g. when both a certificate bundle and
* individual certificates exist in the same directory.
* individual certificates exist in the same directory.
*/
*/
static
void
read_trusted_roots_from_known_locations
(
HCERTSTORE
store
)
static
void
read_trusted_roots_from_known_locations
(
HCERTSTORE
store
,
HCERTSTORE
cached
,
BOOL
*
delete
)
{
{
HCERTSTORE
new
;
HCERTSTORE
new
;
DWORD
needed
;
DWORD
needed
,
size
;
struct
enum_root_certs_params
params
=
{
NULL
,
2048
,
&
needed
};
struct
enum_root_certs_params
params
=
{
NULL
,
2048
,
&
needed
};
HCRYPTPROV
prov
;
HCRYPTHASH
hash
;
BYTE
hashval
[
20
];
DWORD
hashlen
;
CRYPT_HASH_BLOB
hash_blob
=
{
sizeof
(
hashval
),
hashval
};
CRYPT_DATA_BLOB
exists_blob
=
{
0
,
NULL
};
PCCERT_CONTEXT
cert
,
existing
;
unsigned
int
existing_count
=
0
,
new_count
=
0
;
unsigned
int
cached_count
=
0
;
new
=
CertOpenStore
(
CERT_STORE_PROV_MEMORY
,
X509_ASN_ENCODING
,
0
,
CERT_STORE_CREATE_NEW_FLAG
,
NULL
);
new
=
CertOpenStore
(
CERT_STORE_PROV_MEMORY
,
X509_ASN_ENCODING
,
0
,
CERT_STORE_CREATE_NEW_FLAG
,
NULL
);
if
(
!
new
)
return
;
if
(
!
new
)
return
;
existing
=
NULL
;
while
((
existing
=
CertEnumCertificatesInStore
(
cached
,
existing
)))
++
cached_count
;
CryptAcquireContextW
(
&
prov
,
NULL
,
NULL
,
PROV_RSA_FULL
,
CRYPT_VERIFYCONTEXT
);
params
.
buffer
=
CryptMemAlloc
(
params
.
size
);
params
.
buffer
=
CryptMemAlloc
(
params
.
size
);
while
(
!
CRYPT32_CALL
(
enum_root_certs
,
&
params
))
while
(
!
CRYPT32_CALL
(
enum_root_certs
,
&
params
))
{
{
...
@@ -631,24 +657,78 @@ static void read_trusted_roots_from_known_locations(HCERTSTORE store)
...
@@ -631,24 +657,78 @@ static void read_trusted_roots_from_known_locations(HCERTSTORE store)
params
.
size
=
needed
;
params
.
size
=
needed
;
continue
;
continue
;
}
}
CertAddEncodedCertificateToStore
(
new
,
X509_ASN_ENCODING
,
params
.
buffer
,
needed
,
CryptCreateHash
(
prov
,
CALG_SHA1
,
0
,
0
,
&
hash
);
CERT_STORE_ADD_NEW
,
NULL
);
CryptHashData
(
hash
,
params
.
buffer
,
needed
,
0
);
hashlen
=
sizeof
(
hashval
);
CryptGetHashParam
(
hash
,
HP_HASHVAL
,
hashval
,
&
hashlen
,
0
);
CryptDestroyHash
(
hash
);
if
((
existing
=
CertFindCertificateInStore
(
cached
,
X509_ASN_ENCODING
,
0
,
CERT_FIND_SHA1_HASH
,
&
hash_blob
,
NULL
)))
{
/* Skip certificate which is already cached. CERT_FIRST_USER_PROP_ID is set once the cached cert
* is found among host imports. */
if
(
!
CertGetCertificateContextProperty
(
existing
,
CERT_FIRST_USER_PROP_ID
,
NULL
,
&
size
))
{
if
(
!
CertSetCertificateContextProperty
(
existing
,
CERT_FIRST_USER_PROP_ID
,
0
,
&
exists_blob
))
ERR
(
"Failed to set property.
\n
"
);
++
existing_count
;
}
CertFreeCertificateContext
(
existing
);
continue
;
}
CertAddEncodedCertificateToStore
(
new
,
X509_ASN_ENCODING
,
params
.
buffer
,
needed
,
CERT_STORE_ADD_ALWAYS
,
&
cert
);
/* Add to cached so we can catch duplicates and check_and_store_certs() has the full chains. */
CertAddCertificateContextToStore
(
cached
,
cert
,
CERT_STORE_ADD_ALWAYS
,
NULL
);
if
(
!
CertSetCertificateContextProperty
(
cert
,
CERT_FIRST_USER_PROP_ID
,
0
,
&
exists_blob
))
ERR
(
"Failed to set property.
\n
"
);
CertFreeCertificateContext
(
cert
);
++
new_count
;
}
}
CryptMemFree
(
params
.
buffer
);
CryptMemFree
(
params
.
buffer
);
check_and_store_certs
(
new
,
store
);
CryptReleaseContext
(
prov
,
0
);
if
(
existing_count
<
cached_count
)
{
/* Some certs were removed on host. Clean up the cache and add all the certificates so cert chains
* get revalidated. The certs present on host are now in 'cached' store and are marked with
* CERT_FIRST_USER_PROP_ID property. */
TRACE
(
"Some keys were removed, reimporting, cached %u, existing %u, new %u.
\n
"
,
cached_count
,
existing_count
,
new_count
);
*
delete
=
TRUE
;
existing_count
=
0
;
existing
=
NULL
;
while
((
existing
=
CertEnumCertificatesInStore
(
cached
,
existing
)))
{
if
(
!
CertGetCertificateContextProperty
(
existing
,
CERT_FIRST_USER_PROP_ID
,
NULL
,
&
size
))
continue
;
CertAddCertificateContextToStore
(
new
,
existing
,
CERT_STORE_ADD_NEW
,
NULL
);
++
new_count
;
}
}
if
(
new_count
)
{
/* Clear custom property so it is not serialized and seen by apps. */
cert
=
NULL
;
while
((
cert
=
CertEnumCertificatesInStore
(
new
,
cert
)))
CertSetCertificateContextProperty
(
cert
,
CERT_FIRST_USER_PROP_ID
,
0
,
NULL
);
check_and_store_certs
(
cached
,
new
,
store
);
}
CertCloseStore
(
new
,
0
);
CertCloseStore
(
new
,
0
);
TRACE
(
"existing %u, new %u.
\n
"
,
existing_count
,
new_count
);
}
}
static
HCERTSTORE
create_root_store
(
void
)
static
HCERTSTORE
create_root_store
(
HCERTSTORE
cached
,
BOOL
*
delete
)
{
{
HCERTSTORE
memStore
=
CertOpenStore
(
CERT_STORE_PROV_MEMORY
,
HCERTSTORE
memStore
=
CertOpenStore
(
CERT_STORE_PROV_MEMORY
,
X509_ASN_ENCODING
,
0
,
CERT_STORE_CREATE_NEW_FLAG
,
NULL
);
X509_ASN_ENCODING
,
0
,
CERT_STORE_CREATE_NEW_FLAG
,
NULL
);
*
delete
=
FALSE
;
if
(
memStore
)
if
(
memStore
)
{
{
read_trusted_roots_from_known_locations
(
memStore
);
add_ms_root_certs
(
memStore
,
cached
);
add_ms_root_certs
(
memStor
e
);
read_trusted_roots_from_known_locations
(
memStore
,
cached
,
delet
e
);
}
}
TRACE
(
"returning %p
\n
"
,
memStore
);
TRACE
(
"returning %p
\n
"
,
memStore
);
...
@@ -657,10 +737,11 @@ static HCERTSTORE create_root_store(void)
...
@@ -657,10 +737,11 @@ static HCERTSTORE create_root_store(void)
void
CRYPT_ImportSystemRootCertsToReg
(
void
)
void
CRYPT_ImportSystemRootCertsToReg
(
void
)
{
{
HCERTSTORE
store
=
NULL
;
HCERTSTORE
store
=
NULL
,
reg
=
NULL
;
HKEY
key
=
NULL
;
HKEY
key
=
NULL
;
LONG
rc
;
LONG
rc
;
HANDLE
hsem
;
HANDLE
hsem
;
BOOL
delete
;
static
BOOL
root_certs_imported
=
FALSE
;
static
BOOL
root_certs_imported
=
FALSE
;
...
@@ -685,18 +766,27 @@ void CRYPT_ImportSystemRootCertsToReg(void)
...
@@ -685,18 +766,27 @@ void CRYPT_ImportSystemRootCertsToReg(void)
if
(
rc
)
if
(
rc
)
goto
done
;
goto
done
;
if
(
!
(
store
=
create_root_store
(
)))
if
(
!
(
reg
=
CertOpenStore
(
CERT_STORE_PROV_MEMORY
,
X509_ASN_ENCODING
,
0
,
CERT_STORE_CREATE_NEW_FLAG
,
NULL
)))
{
{
ERR
(
"Failed to create
root store
\n
"
);
ERR
(
"Failed to create
memory store.
\n
"
);
goto
done
;
goto
done
;
}
}
CRYPT_RegReadSerializedFromReg
(
key
,
CERT_STORE_CERTIFICATE_CONTEXT_FLAG
,
reg
,
CERT_STORE_ADD_ALWAYS
);
if
(
!
CRYPT_SerializeContextsToReg
(
key
,
REG_OPTION_VOLATILE
,
pCertInterface
,
store
))
if
(
!
(
store
=
create_root_store
(
reg
,
&
delete
)))
{
ERR
(
"Failed to create root store
\n
"
);
goto
done
;
}
if
(
delete
&&
RegDeleteTreeW
(
key
,
NULL
))
ERR
(
"Error deleting key.
\n
"
);
if
(
!
CRYPT_SerializeContextsToReg
(
key
,
0
,
pCertInterface
,
store
))
ERR
(
"Failed to import system certs into registry, %08lx
\n
"
,
GetLastError
());
ERR
(
"Failed to import system certs into registry, %08lx
\n
"
,
GetLastError
());
done:
done:
RegCloseKey
(
key
);
RegCloseKey
(
key
);
CertCloseStore
(
store
,
0
);
CertCloseStore
(
store
,
0
);
CertCloseStore
(
reg
,
0
);
root_certs_imported
=
TRUE
;
root_certs_imported
=
TRUE
;
ReleaseSemaphore
(
hsem
,
1
,
NULL
);
ReleaseSemaphore
(
hsem
,
1
,
NULL
);
CloseHandle
(
hsem
);
CloseHandle
(
hsem
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment