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
0070d822
Commit
0070d822
authored
Aug 16, 2007
by
Juan Lang
Committed by
Alexandre Julliard
Aug 17, 2007
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
crypt32: Move registry stores to a separate file.
parent
131f1d20
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
548 additions
and
515 deletions
+548
-515
Makefile.in
dlls/crypt32/Makefile.in
+1
-0
crypt32_private.h
dlls/crypt32/crypt32_private.h
+3
-0
regstore.c
dlls/crypt32/regstore.c
+543
-0
store.c
dlls/crypt32/store.c
+1
-515
No files found.
dlls/crypt32/Makefile.in
View file @
0070d822
...
...
@@ -22,6 +22,7 @@ C_SRCS = \
proplist.c
\
protectdata.c
\
provstore.c
\
regstore.c
\
serialize.c
\
sip.c
\
store.c
\
...
...
dlls/crypt32/crypt32_private.h
View file @
0070d822
...
...
@@ -234,6 +234,7 @@ typedef struct WINE_CRYPTCERTSTORE
void
CRYPT_InitStore
(
WINECRYPT_CERTSTORE
*
store
,
HCRYPTPROV
hCryptProv
,
DWORD
dwFlags
,
CertStoreType
type
);
void
CRYPT_FreeStore
(
PWINECRYPT_CERTSTORE
store
);
void
CRYPT_EmptyStore
(
HCERTSTORE
store
);
PWINECRYPT_CERTSTORE
CRYPT_CollectionOpenStore
(
HCRYPTPROV
hCryptProv
,
DWORD
dwFlags
,
const
void
*
pvPara
);
...
...
@@ -243,6 +244,8 @@ PWINECRYPT_CERTSTORE CRYPT_ProvCreateStore(HCRYPTPROV hCryptProv,
PWINECRYPT_CERTSTORE
CRYPT_ProvOpenStore
(
LPCSTR
lpszStoreProvider
,
DWORD
dwEncodingType
,
HCRYPTPROV
hCryptProv
,
DWORD
dwFlags
,
const
void
*
pvPara
);
PWINECRYPT_CERTSTORE
CRYPT_RegOpenStore
(
HCRYPTPROV
hCryptProv
,
DWORD
dwFlags
,
const
void
*
pvPara
);
/* Helper function for store reading functions and
* CertAddSerializedElementToStore. Returns a context of the appropriate type
...
...
dlls/crypt32/regstore.c
0 → 100644
View file @
0070d822
/*
* Copyright 2004-2007 Juan Lang
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <assert.h>
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "wincrypt.h"
#include "winreg.h"
#include "winuser.h"
#include "wine/debug.h"
#include "wine/list.h"
#include "crypt32_private.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
crypt
);
typedef
struct
_WINE_HASH_TO_DELETE
{
BYTE
hash
[
20
];
struct
list
entry
;
}
WINE_HASH_TO_DELETE
,
*
PWINE_HASH_TO_DELETE
;
typedef
struct
_WINE_REGSTOREINFO
{
DWORD
dwOpenFlags
;
HCRYPTPROV
cryptProv
;
HCERTSTORE
memStore
;
HKEY
key
;
BOOL
dirty
;
CRITICAL_SECTION
cs
;
struct
list
certsToDelete
;
struct
list
crlsToDelete
;
}
WINE_REGSTOREINFO
,
*
PWINE_REGSTOREINFO
;
static
void
CRYPT_HashToStr
(
const
BYTE
*
hash
,
LPWSTR
asciiHash
)
{
static
const
WCHAR
fmt
[]
=
{
'%'
,
'0'
,
'2'
,
'X'
,
0
};
DWORD
i
;
assert
(
hash
);
assert
(
asciiHash
);
for
(
i
=
0
;
i
<
20
;
i
++
)
wsprintfW
(
asciiHash
+
i
*
2
,
fmt
,
hash
[
i
]);
}
static
const
WCHAR
CertsW
[]
=
{
'C'
,
'e'
,
'r'
,
't'
,
'i'
,
'f'
,
'i'
,
'c'
,
'a'
,
't'
,
'e'
,
's'
,
0
};
static
const
WCHAR
CRLsW
[]
=
{
'C'
,
'R'
,
'L'
,
's'
,
0
};
static
const
WCHAR
CTLsW
[]
=
{
'C'
,
'T'
,
'L'
,
's'
,
0
};
static
const
WCHAR
BlobW
[]
=
{
'B'
,
'l'
,
'o'
,
'b'
,
0
};
static
void
CRYPT_RegReadSerializedFromReg
(
const
WINE_REGSTOREINFO
*
store
,
HKEY
key
,
DWORD
contextType
)
{
LONG
rc
;
DWORD
index
=
0
;
WCHAR
subKeyName
[
MAX_PATH
];
do
{
DWORD
size
=
sizeof
(
subKeyName
)
/
sizeof
(
WCHAR
);
rc
=
RegEnumKeyExW
(
key
,
index
++
,
subKeyName
,
&
size
,
NULL
,
NULL
,
NULL
,
NULL
);
if
(
!
rc
)
{
HKEY
subKey
;
rc
=
RegOpenKeyExW
(
key
,
subKeyName
,
0
,
KEY_READ
,
&
subKey
);
if
(
!
rc
)
{
LPBYTE
buf
=
NULL
;
size
=
0
;
rc
=
RegQueryValueExW
(
subKey
,
BlobW
,
NULL
,
NULL
,
NULL
,
&
size
);
if
(
!
rc
)
buf
=
CryptMemAlloc
(
size
);
if
(
buf
)
{
rc
=
RegQueryValueExW
(
subKey
,
BlobW
,
NULL
,
NULL
,
buf
,
&
size
);
if
(
!
rc
)
{
const
void
*
context
;
DWORD
addedType
;
TRACE
(
"Adding cert with hash %s
\n
"
,
debugstr_w
(
subKeyName
));
context
=
CRYPT_ReadSerializedElement
(
buf
,
size
,
contextType
,
&
addedType
);
if
(
context
)
{
const
WINE_CONTEXT_INTERFACE
*
contextInterface
;
BYTE
hash
[
20
];
switch
(
addedType
)
{
case
CERT_STORE_CERTIFICATE_CONTEXT
:
contextInterface
=
pCertInterface
;
break
;
case
CERT_STORE_CRL_CONTEXT
:
contextInterface
=
pCRLInterface
;
break
;
case
CERT_STORE_CTL_CONTEXT
:
contextInterface
=
pCTLInterface
;
break
;
default:
contextInterface
=
NULL
;
}
if
(
contextInterface
)
{
size
=
sizeof
(
hash
);
if
(
contextInterface
->
getProp
(
context
,
CERT_HASH_PROP_ID
,
hash
,
&
size
))
{
WCHAR
asciiHash
[
20
*
2
+
1
];
CRYPT_HashToStr
(
hash
,
asciiHash
);
TRACE
(
"comparing %s
\n
"
,
debugstr_w
(
asciiHash
));
TRACE
(
"with %s
\n
"
,
debugstr_w
(
subKeyName
));
if
(
!
lstrcmpW
(
asciiHash
,
subKeyName
))
{
TRACE
(
"hash matches, adding
\n
"
);
contextInterface
->
addContextToStore
(
store
->
memStore
,
context
,
CERT_STORE_ADD_REPLACE_EXISTING
,
NULL
);
}
else
TRACE
(
"hash doesn't match, ignoring
\n
"
);
}
contextInterface
->
free
(
context
);
}
}
}
CryptMemFree
(
buf
);
}
RegCloseKey
(
subKey
);
}
/* Ignore intermediate errors, continue enumerating */
rc
=
ERROR_SUCCESS
;
}
}
while
(
!
rc
);
}
static
void
CRYPT_RegReadFromReg
(
const
WINE_REGSTOREINFO
*
store
)
{
static
const
WCHAR
*
const
subKeys
[]
=
{
CertsW
,
CRLsW
,
CTLsW
};
static
const
DWORD
contextFlags
[]
=
{
CERT_STORE_CERTIFICATE_CONTEXT_FLAG
,
CERT_STORE_CRL_CONTEXT_FLAG
,
CERT_STORE_CTL_CONTEXT_FLAG
};
DWORD
i
;
for
(
i
=
0
;
i
<
sizeof
(
subKeys
)
/
sizeof
(
subKeys
[
0
]);
i
++
)
{
HKEY
key
;
LONG
rc
;
rc
=
RegCreateKeyExW
(
store
->
key
,
subKeys
[
i
],
0
,
NULL
,
0
,
KEY_READ
,
NULL
,
&
key
,
NULL
);
if
(
!
rc
)
{
CRYPT_RegReadSerializedFromReg
(
store
,
key
,
contextFlags
[
i
]);
RegCloseKey
(
key
);
}
}
}
/* Hash is assumed to be 20 bytes in length (a SHA-1 hash) */
static
BOOL
CRYPT_WriteSerializedToReg
(
HKEY
key
,
const
BYTE
*
hash
,
const
BYTE
*
buf
,
DWORD
len
)
{
WCHAR
asciiHash
[
20
*
2
+
1
];
LONG
rc
;
HKEY
subKey
;
BOOL
ret
;
CRYPT_HashToStr
(
hash
,
asciiHash
);
rc
=
RegCreateKeyExW
(
key
,
asciiHash
,
0
,
NULL
,
0
,
KEY_ALL_ACCESS
,
NULL
,
&
subKey
,
NULL
);
if
(
!
rc
)
{
rc
=
RegSetValueExW
(
subKey
,
BlobW
,
0
,
REG_BINARY
,
buf
,
len
);
RegCloseKey
(
subKey
);
}
if
(
!
rc
)
ret
=
TRUE
;
else
{
SetLastError
(
rc
);
ret
=
FALSE
;
}
return
ret
;
}
static
BOOL
CRYPT_SerializeContextsToReg
(
HKEY
key
,
const
WINE_CONTEXT_INTERFACE
*
contextInterface
,
HCERTSTORE
memStore
)
{
const
void
*
context
=
NULL
;
BOOL
ret
;
do
{
context
=
contextInterface
->
enumContextsInStore
(
memStore
,
context
);
if
(
context
)
{
BYTE
hash
[
20
];
DWORD
hashSize
=
sizeof
(
hash
);
ret
=
contextInterface
->
getProp
(
context
,
CERT_HASH_PROP_ID
,
hash
,
&
hashSize
);
if
(
ret
)
{
DWORD
size
=
0
;
LPBYTE
buf
=
NULL
;
ret
=
contextInterface
->
serialize
(
context
,
0
,
NULL
,
&
size
);
if
(
size
)
buf
=
CryptMemAlloc
(
size
);
if
(
buf
)
{
ret
=
contextInterface
->
serialize
(
context
,
0
,
buf
,
&
size
);
if
(
ret
)
ret
=
CRYPT_WriteSerializedToReg
(
key
,
hash
,
buf
,
size
);
}
CryptMemFree
(
buf
);
}
}
else
ret
=
TRUE
;
}
while
(
ret
&&
context
!=
NULL
);
if
(
context
)
contextInterface
->
free
(
context
);
return
ret
;
}
static
BOOL
CRYPT_RegWriteToReg
(
PWINE_REGSTOREINFO
store
)
{
static
const
WCHAR
*
const
subKeys
[]
=
{
CertsW
,
CRLsW
,
CTLsW
};
const
WINE_CONTEXT_INTERFACE
*
const
interfaces
[]
=
{
pCertInterface
,
pCRLInterface
,
pCTLInterface
};
struct
list
*
listToDelete
[]
=
{
&
store
->
certsToDelete
,
&
store
->
crlsToDelete
,
NULL
};
BOOL
ret
=
TRUE
;
DWORD
i
;
for
(
i
=
0
;
ret
&&
i
<
sizeof
(
subKeys
)
/
sizeof
(
subKeys
[
0
]);
i
++
)
{
HKEY
key
;
LONG
rc
=
RegCreateKeyExW
(
store
->
key
,
subKeys
[
i
],
0
,
NULL
,
0
,
KEY_ALL_ACCESS
,
NULL
,
&
key
,
NULL
);
if
(
!
rc
)
{
if
(
listToDelete
[
i
])
{
PWINE_HASH_TO_DELETE
toDelete
,
next
;
WCHAR
asciiHash
[
20
*
2
+
1
];
EnterCriticalSection
(
&
store
->
cs
);
LIST_FOR_EACH_ENTRY_SAFE
(
toDelete
,
next
,
listToDelete
[
i
],
WINE_HASH_TO_DELETE
,
entry
)
{
LONG
rc
;
CRYPT_HashToStr
(
toDelete
->
hash
,
asciiHash
);
TRACE
(
"Removing %s
\n
"
,
debugstr_w
(
asciiHash
));
rc
=
RegDeleteKeyW
(
key
,
asciiHash
);
if
(
rc
!=
ERROR_SUCCESS
&&
rc
!=
ERROR_FILE_NOT_FOUND
)
{
SetLastError
(
rc
);
ret
=
FALSE
;
}
list_remove
(
&
toDelete
->
entry
);
CryptMemFree
(
toDelete
);
}
LeaveCriticalSection
(
&
store
->
cs
);
}
ret
=
CRYPT_SerializeContextsToReg
(
key
,
interfaces
[
i
],
store
->
memStore
);
RegCloseKey
(
key
);
}
else
{
SetLastError
(
rc
);
ret
=
FALSE
;
}
}
return
ret
;
}
/* If force is true or the registry store is dirty, writes the contents of the
* store to the registry.
*/
static
BOOL
CRYPT_RegFlushStore
(
PWINE_REGSTOREINFO
store
,
BOOL
force
)
{
BOOL
ret
;
TRACE
(
"(%p, %d)
\n
"
,
store
,
force
);
if
(
store
->
dirty
||
force
)
ret
=
CRYPT_RegWriteToReg
(
store
);
else
ret
=
TRUE
;
return
ret
;
}
static
void
WINAPI
CRYPT_RegCloseStore
(
HCERTSTORE
hCertStore
,
DWORD
dwFlags
)
{
PWINE_REGSTOREINFO
store
=
(
PWINE_REGSTOREINFO
)
hCertStore
;
TRACE
(
"(%p, %08x)
\n
"
,
store
,
dwFlags
);
if
(
dwFlags
)
FIXME
(
"Unimplemented flags: %08x
\n
"
,
dwFlags
);
CRYPT_RegFlushStore
(
store
,
FALSE
);
RegCloseKey
(
store
->
key
);
store
->
cs
.
DebugInfo
->
Spare
[
0
]
=
0
;
DeleteCriticalSection
(
&
store
->
cs
);
CryptMemFree
(
store
);
}
static
BOOL
WINAPI
CRYPT_RegWriteContext
(
PWINE_REGSTOREINFO
store
,
const
void
*
context
,
DWORD
dwFlags
)
{
BOOL
ret
;
if
(
dwFlags
&
CERT_STORE_PROV_WRITE_ADD_FLAG
)
{
store
->
dirty
=
TRUE
;
ret
=
TRUE
;
}
else
ret
=
FALSE
;
return
ret
;
}
static
BOOL
CRYPT_RegDeleteContext
(
PWINE_REGSTOREINFO
store
,
struct
list
*
deleteList
,
const
void
*
context
,
PCWINE_CONTEXT_INTERFACE
contextInterface
)
{
BOOL
ret
;
if
(
store
->
dwOpenFlags
&
CERT_STORE_READONLY_FLAG
)
{
SetLastError
(
ERROR_ACCESS_DENIED
);
ret
=
FALSE
;
}
else
{
PWINE_HASH_TO_DELETE
toDelete
=
CryptMemAlloc
(
sizeof
(
WINE_HASH_TO_DELETE
));
if
(
toDelete
)
{
DWORD
size
=
sizeof
(
toDelete
->
hash
);
ret
=
contextInterface
->
getProp
(
context
,
CERT_HASH_PROP_ID
,
toDelete
->
hash
,
&
size
);
if
(
ret
)
{
EnterCriticalSection
(
&
store
->
cs
);
list_add_tail
(
deleteList
,
&
toDelete
->
entry
);
LeaveCriticalSection
(
&
store
->
cs
);
}
else
{
CryptMemFree
(
toDelete
);
ret
=
FALSE
;
}
}
else
ret
=
FALSE
;
if
(
ret
)
store
->
dirty
=
TRUE
;
}
return
ret
;
}
static
BOOL
WINAPI
CRYPT_RegWriteCert
(
HCERTSTORE
hCertStore
,
PCCERT_CONTEXT
cert
,
DWORD
dwFlags
)
{
PWINE_REGSTOREINFO
store
=
(
PWINE_REGSTOREINFO
)
hCertStore
;
TRACE
(
"(%p, %p, %d)
\n
"
,
hCertStore
,
cert
,
dwFlags
);
return
CRYPT_RegWriteContext
(
store
,
cert
,
dwFlags
);
}
static
BOOL
WINAPI
CRYPT_RegDeleteCert
(
HCERTSTORE
hCertStore
,
PCCERT_CONTEXT
pCertContext
,
DWORD
dwFlags
)
{
PWINE_REGSTOREINFO
store
=
(
PWINE_REGSTOREINFO
)
hCertStore
;
TRACE
(
"(%p, %p, %08x)
\n
"
,
store
,
pCertContext
,
dwFlags
);
return
CRYPT_RegDeleteContext
(
store
,
&
store
->
certsToDelete
,
pCertContext
,
pCertInterface
);
}
static
BOOL
WINAPI
CRYPT_RegWriteCRL
(
HCERTSTORE
hCertStore
,
PCCRL_CONTEXT
crl
,
DWORD
dwFlags
)
{
PWINE_REGSTOREINFO
store
=
(
PWINE_REGSTOREINFO
)
hCertStore
;
TRACE
(
"(%p, %p, %d)
\n
"
,
hCertStore
,
crl
,
dwFlags
);
return
CRYPT_RegWriteContext
(
store
,
crl
,
dwFlags
);
}
static
BOOL
WINAPI
CRYPT_RegDeleteCRL
(
HCERTSTORE
hCertStore
,
PCCRL_CONTEXT
pCrlContext
,
DWORD
dwFlags
)
{
PWINE_REGSTOREINFO
store
=
(
PWINE_REGSTOREINFO
)
hCertStore
;
TRACE
(
"(%p, %p, %08x)
\n
"
,
store
,
pCrlContext
,
dwFlags
);
return
CRYPT_RegDeleteContext
(
store
,
&
store
->
crlsToDelete
,
pCrlContext
,
pCRLInterface
);
}
static
BOOL
WINAPI
CRYPT_RegControl
(
HCERTSTORE
hCertStore
,
DWORD
dwFlags
,
DWORD
dwCtrlType
,
void
const
*
pvCtrlPara
)
{
PWINE_REGSTOREINFO
store
=
(
PWINE_REGSTOREINFO
)
hCertStore
;
BOOL
ret
;
TRACE
(
"(%p, %08x, %d, %p)
\n
"
,
hCertStore
,
dwFlags
,
dwCtrlType
,
pvCtrlPara
);
switch
(
dwCtrlType
)
{
case
CERT_STORE_CTRL_RESYNC
:
CRYPT_RegFlushStore
(
store
,
FALSE
);
CRYPT_EmptyStore
(
store
->
memStore
);
CRYPT_RegReadFromReg
(
store
);
ret
=
TRUE
;
break
;
case
CERT_STORE_CTRL_COMMIT
:
ret
=
CRYPT_RegFlushStore
(
store
,
dwFlags
&
CERT_STORE_CTRL_COMMIT_FORCE_FLAG
);
break
;
default:
FIXME
(
"%d: stub
\n
"
,
dwCtrlType
);
ret
=
FALSE
;
}
return
ret
;
}
static
void
*
regProvFuncs
[]
=
{
CRYPT_RegCloseStore
,
NULL
,
/* CERT_STORE_PROV_READ_CERT_FUNC */
CRYPT_RegWriteCert
,
CRYPT_RegDeleteCert
,
NULL
,
/* CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC */
NULL
,
/* CERT_STORE_PROV_READ_CRL_FUNC */
CRYPT_RegWriteCRL
,
CRYPT_RegDeleteCRL
,
NULL
,
/* CERT_STORE_PROV_SET_CRL_PROPERTY_FUNC */
NULL
,
/* CERT_STORE_PROV_READ_CTL_FUNC */
NULL
,
/* CERT_STORE_PROV_WRITE_CTL_FUNC */
NULL
,
/* CERT_STORE_PROV_DELETE_CTL_FUNC */
NULL
,
/* CERT_STORE_PROV_SET_CTL_PROPERTY_FUNC */
CRYPT_RegControl
,
};
PWINECRYPT_CERTSTORE
CRYPT_RegOpenStore
(
HCRYPTPROV
hCryptProv
,
DWORD
dwFlags
,
const
void
*
pvPara
)
{
PWINECRYPT_CERTSTORE
store
=
NULL
;
TRACE
(
"(%ld, %08x, %p)
\n
"
,
hCryptProv
,
dwFlags
,
pvPara
);
if
(
dwFlags
&
CERT_STORE_DELETE_FLAG
)
{
DWORD
rc
=
RegDeleteTreeW
((
HKEY
)
pvPara
,
CertsW
);
if
(
rc
==
ERROR_SUCCESS
||
rc
==
ERROR_NO_MORE_ITEMS
)
rc
=
RegDeleteTreeW
((
HKEY
)
pvPara
,
CRLsW
);
if
(
rc
==
ERROR_SUCCESS
||
rc
==
ERROR_NO_MORE_ITEMS
)
rc
=
RegDeleteTreeW
((
HKEY
)
pvPara
,
CTLsW
);
if
(
rc
==
ERROR_NO_MORE_ITEMS
)
rc
=
ERROR_SUCCESS
;
SetLastError
(
rc
);
}
else
{
HKEY
key
;
if
(
DuplicateHandle
(
GetCurrentProcess
(),
(
HANDLE
)
pvPara
,
GetCurrentProcess
(),
(
LPHANDLE
)
&
key
,
dwFlags
&
CERT_STORE_READONLY_FLAG
?
KEY_READ
:
KEY_ALL_ACCESS
,
TRUE
,
0
))
{
PWINECRYPT_CERTSTORE
memStore
;
memStore
=
CertOpenStore
(
CERT_STORE_PROV_MEMORY
,
0
,
hCryptProv
,
CERT_STORE_CREATE_NEW_FLAG
,
NULL
);
if
(
memStore
)
{
PWINE_REGSTOREINFO
regInfo
=
CryptMemAlloc
(
sizeof
(
WINE_REGSTOREINFO
));
if
(
regInfo
)
{
CERT_STORE_PROV_INFO
provInfo
=
{
0
};
regInfo
->
dwOpenFlags
=
dwFlags
;
regInfo
->
cryptProv
=
hCryptProv
;
regInfo
->
memStore
=
memStore
;
regInfo
->
key
=
key
;
InitializeCriticalSection
(
&
regInfo
->
cs
);
regInfo
->
cs
.
DebugInfo
->
Spare
[
0
]
=
(
DWORD_PTR
)(
__FILE__
": PWINE_REGSTOREINFO->cs"
);
list_init
(
&
regInfo
->
certsToDelete
);
list_init
(
&
regInfo
->
crlsToDelete
);
CRYPT_RegReadFromReg
(
regInfo
);
regInfo
->
dirty
=
FALSE
;
provInfo
.
cbSize
=
sizeof
(
provInfo
);
provInfo
.
cStoreProvFunc
=
sizeof
(
regProvFuncs
)
/
sizeof
(
regProvFuncs
[
0
]);
provInfo
.
rgpvStoreProvFunc
=
regProvFuncs
;
provInfo
.
hStoreProv
=
regInfo
;
store
=
CRYPT_ProvCreateStore
(
hCryptProv
,
dwFlags
,
memStore
,
&
provInfo
);
}
}
}
}
TRACE
(
"returning %p
\n
"
,
store
);
return
store
;
}
dlls/crypt32/store.c
View file @
0070d822
...
...
@@ -93,24 +93,6 @@ typedef struct _WINE_MEMSTORE
struct
ContextList
*
crls
;
}
WINE_MEMSTORE
,
*
PWINE_MEMSTORE
;
typedef
struct
_WINE_HASH_TO_DELETE
{
BYTE
hash
[
20
];
struct
list
entry
;
}
WINE_HASH_TO_DELETE
,
*
PWINE_HASH_TO_DELETE
;
typedef
struct
_WINE_REGSTOREINFO
{
DWORD
dwOpenFlags
;
HCRYPTPROV
cryptProv
;
HCERTSTORE
memStore
;
HKEY
key
;
BOOL
dirty
;
CRITICAL_SECTION
cs
;
struct
list
certsToDelete
;
struct
list
crlsToDelete
;
}
WINE_REGSTOREINFO
,
*
PWINE_REGSTOREINFO
;
typedef
struct
_WINE_FILESTOREINFO
{
DWORD
dwOpenFlags
;
...
...
@@ -233,7 +215,7 @@ static BOOL CRYPT_MemDeleteCrl(PWINECRYPT_CERTSTORE store, void *pCrlContext)
return
TRUE
;
}
static
void
CRYPT_EmptyStore
(
HCERTSTORE
store
)
void
CRYPT_EmptyStore
(
HCERTSTORE
store
)
{
PCCERT_CONTEXT
cert
;
PCCRL_CONTEXT
crl
;
...
...
@@ -299,502 +281,6 @@ static WINECRYPT_CERTSTORE *CRYPT_MemOpenStore(HCRYPTPROV hCryptProv,
return
(
PWINECRYPT_CERTSTORE
)
store
;
}
static
void
CRYPT_HashToStr
(
const
BYTE
*
hash
,
LPWSTR
asciiHash
)
{
static
const
WCHAR
fmt
[]
=
{
'%'
,
'0'
,
'2'
,
'X'
,
0
};
DWORD
i
;
assert
(
hash
);
assert
(
asciiHash
);
for
(
i
=
0
;
i
<
20
;
i
++
)
wsprintfW
(
asciiHash
+
i
*
2
,
fmt
,
hash
[
i
]);
}
static
const
WCHAR
CertsW
[]
=
{
'C'
,
'e'
,
'r'
,
't'
,
'i'
,
'f'
,
'i'
,
'c'
,
'a'
,
't'
,
'e'
,
's'
,
0
};
static
const
WCHAR
CRLsW
[]
=
{
'C'
,
'R'
,
'L'
,
's'
,
0
};
static
const
WCHAR
CTLsW
[]
=
{
'C'
,
'T'
,
'L'
,
's'
,
0
};
static
const
WCHAR
BlobW
[]
=
{
'B'
,
'l'
,
'o'
,
'b'
,
0
};
static
void
CRYPT_RegReadSerializedFromReg
(
const
WINE_REGSTOREINFO
*
store
,
HKEY
key
,
DWORD
contextType
)
{
LONG
rc
;
DWORD
index
=
0
;
WCHAR
subKeyName
[
MAX_PATH
];
do
{
DWORD
size
=
sizeof
(
subKeyName
)
/
sizeof
(
WCHAR
);
rc
=
RegEnumKeyExW
(
key
,
index
++
,
subKeyName
,
&
size
,
NULL
,
NULL
,
NULL
,
NULL
);
if
(
!
rc
)
{
HKEY
subKey
;
rc
=
RegOpenKeyExW
(
key
,
subKeyName
,
0
,
KEY_READ
,
&
subKey
);
if
(
!
rc
)
{
LPBYTE
buf
=
NULL
;
size
=
0
;
rc
=
RegQueryValueExW
(
subKey
,
BlobW
,
NULL
,
NULL
,
NULL
,
&
size
);
if
(
!
rc
)
buf
=
CryptMemAlloc
(
size
);
if
(
buf
)
{
rc
=
RegQueryValueExW
(
subKey
,
BlobW
,
NULL
,
NULL
,
buf
,
&
size
);
if
(
!
rc
)
{
const
void
*
context
;
DWORD
addedType
;
TRACE
(
"Adding cert with hash %s
\n
"
,
debugstr_w
(
subKeyName
));
context
=
CRYPT_ReadSerializedElement
(
buf
,
size
,
contextType
,
&
addedType
);
if
(
context
)
{
const
WINE_CONTEXT_INTERFACE
*
contextInterface
;
BYTE
hash
[
20
];
switch
(
addedType
)
{
case
CERT_STORE_CERTIFICATE_CONTEXT
:
contextInterface
=
pCertInterface
;
break
;
case
CERT_STORE_CRL_CONTEXT
:
contextInterface
=
pCRLInterface
;
break
;
case
CERT_STORE_CTL_CONTEXT
:
contextInterface
=
pCTLInterface
;
break
;
default:
contextInterface
=
NULL
;
}
if
(
contextInterface
)
{
size
=
sizeof
(
hash
);
if
(
contextInterface
->
getProp
(
context
,
CERT_HASH_PROP_ID
,
hash
,
&
size
))
{
WCHAR
asciiHash
[
20
*
2
+
1
];
CRYPT_HashToStr
(
hash
,
asciiHash
);
TRACE
(
"comparing %s
\n
"
,
debugstr_w
(
asciiHash
));
TRACE
(
"with %s
\n
"
,
debugstr_w
(
subKeyName
));
if
(
!
lstrcmpW
(
asciiHash
,
subKeyName
))
{
TRACE
(
"hash matches, adding
\n
"
);
contextInterface
->
addContextToStore
(
store
->
memStore
,
context
,
CERT_STORE_ADD_REPLACE_EXISTING
,
NULL
);
}
else
TRACE
(
"hash doesn't match, ignoring
\n
"
);
}
contextInterface
->
free
(
context
);
}
}
}
CryptMemFree
(
buf
);
}
RegCloseKey
(
subKey
);
}
/* Ignore intermediate errors, continue enumerating */
rc
=
ERROR_SUCCESS
;
}
}
while
(
!
rc
);
}
static
void
CRYPT_RegReadFromReg
(
const
WINE_REGSTOREINFO
*
store
)
{
static
const
WCHAR
*
const
subKeys
[]
=
{
CertsW
,
CRLsW
,
CTLsW
};
static
const
DWORD
contextFlags
[]
=
{
CERT_STORE_CERTIFICATE_CONTEXT_FLAG
,
CERT_STORE_CRL_CONTEXT_FLAG
,
CERT_STORE_CTL_CONTEXT_FLAG
};
DWORD
i
;
for
(
i
=
0
;
i
<
sizeof
(
subKeys
)
/
sizeof
(
subKeys
[
0
]);
i
++
)
{
HKEY
key
;
LONG
rc
;
rc
=
RegCreateKeyExW
(
store
->
key
,
subKeys
[
i
],
0
,
NULL
,
0
,
KEY_READ
,
NULL
,
&
key
,
NULL
);
if
(
!
rc
)
{
CRYPT_RegReadSerializedFromReg
(
store
,
key
,
contextFlags
[
i
]);
RegCloseKey
(
key
);
}
}
}
/* Hash is assumed to be 20 bytes in length (a SHA-1 hash) */
static
BOOL
CRYPT_WriteSerializedToReg
(
HKEY
key
,
const
BYTE
*
hash
,
const
BYTE
*
buf
,
DWORD
len
)
{
WCHAR
asciiHash
[
20
*
2
+
1
];
LONG
rc
;
HKEY
subKey
;
BOOL
ret
;
CRYPT_HashToStr
(
hash
,
asciiHash
);
rc
=
RegCreateKeyExW
(
key
,
asciiHash
,
0
,
NULL
,
0
,
KEY_ALL_ACCESS
,
NULL
,
&
subKey
,
NULL
);
if
(
!
rc
)
{
rc
=
RegSetValueExW
(
subKey
,
BlobW
,
0
,
REG_BINARY
,
buf
,
len
);
RegCloseKey
(
subKey
);
}
if
(
!
rc
)
ret
=
TRUE
;
else
{
SetLastError
(
rc
);
ret
=
FALSE
;
}
return
ret
;
}
static
BOOL
CRYPT_SerializeContextsToReg
(
HKEY
key
,
const
WINE_CONTEXT_INTERFACE
*
contextInterface
,
HCERTSTORE
memStore
)
{
const
void
*
context
=
NULL
;
BOOL
ret
;
do
{
context
=
contextInterface
->
enumContextsInStore
(
memStore
,
context
);
if
(
context
)
{
BYTE
hash
[
20
];
DWORD
hashSize
=
sizeof
(
hash
);
ret
=
contextInterface
->
getProp
(
context
,
CERT_HASH_PROP_ID
,
hash
,
&
hashSize
);
if
(
ret
)
{
DWORD
size
=
0
;
LPBYTE
buf
=
NULL
;
ret
=
contextInterface
->
serialize
(
context
,
0
,
NULL
,
&
size
);
if
(
size
)
buf
=
CryptMemAlloc
(
size
);
if
(
buf
)
{
ret
=
contextInterface
->
serialize
(
context
,
0
,
buf
,
&
size
);
if
(
ret
)
ret
=
CRYPT_WriteSerializedToReg
(
key
,
hash
,
buf
,
size
);
}
CryptMemFree
(
buf
);
}
}
else
ret
=
TRUE
;
}
while
(
ret
&&
context
!=
NULL
);
if
(
context
)
contextInterface
->
free
(
context
);
return
ret
;
}
static
BOOL
CRYPT_RegWriteToReg
(
PWINE_REGSTOREINFO
store
)
{
static
const
WCHAR
*
const
subKeys
[]
=
{
CertsW
,
CRLsW
,
CTLsW
};
const
WINE_CONTEXT_INTERFACE
*
const
interfaces
[]
=
{
pCertInterface
,
pCRLInterface
,
pCTLInterface
};
struct
list
*
listToDelete
[]
=
{
&
store
->
certsToDelete
,
&
store
->
crlsToDelete
,
NULL
};
BOOL
ret
=
TRUE
;
DWORD
i
;
for
(
i
=
0
;
ret
&&
i
<
sizeof
(
subKeys
)
/
sizeof
(
subKeys
[
0
]);
i
++
)
{
HKEY
key
;
LONG
rc
=
RegCreateKeyExW
(
store
->
key
,
subKeys
[
i
],
0
,
NULL
,
0
,
KEY_ALL_ACCESS
,
NULL
,
&
key
,
NULL
);
if
(
!
rc
)
{
if
(
listToDelete
[
i
])
{
PWINE_HASH_TO_DELETE
toDelete
,
next
;
WCHAR
asciiHash
[
20
*
2
+
1
];
EnterCriticalSection
(
&
store
->
cs
);
LIST_FOR_EACH_ENTRY_SAFE
(
toDelete
,
next
,
listToDelete
[
i
],
WINE_HASH_TO_DELETE
,
entry
)
{
LONG
rc
;
CRYPT_HashToStr
(
toDelete
->
hash
,
asciiHash
);
TRACE
(
"Removing %s
\n
"
,
debugstr_w
(
asciiHash
));
rc
=
RegDeleteKeyW
(
key
,
asciiHash
);
if
(
rc
!=
ERROR_SUCCESS
&&
rc
!=
ERROR_FILE_NOT_FOUND
)
{
SetLastError
(
rc
);
ret
=
FALSE
;
}
list_remove
(
&
toDelete
->
entry
);
CryptMemFree
(
toDelete
);
}
LeaveCriticalSection
(
&
store
->
cs
);
}
ret
=
CRYPT_SerializeContextsToReg
(
key
,
interfaces
[
i
],
store
->
memStore
);
RegCloseKey
(
key
);
}
else
{
SetLastError
(
rc
);
ret
=
FALSE
;
}
}
return
ret
;
}
/* If force is true or the registry store is dirty, writes the contents of the
* store to the registry.
*/
static
BOOL
CRYPT_RegFlushStore
(
PWINE_REGSTOREINFO
store
,
BOOL
force
)
{
BOOL
ret
;
TRACE
(
"(%p, %d)
\n
"
,
store
,
force
);
if
(
store
->
dirty
||
force
)
ret
=
CRYPT_RegWriteToReg
(
store
);
else
ret
=
TRUE
;
return
ret
;
}
static
void
WINAPI
CRYPT_RegCloseStore
(
HCERTSTORE
hCertStore
,
DWORD
dwFlags
)
{
PWINE_REGSTOREINFO
store
=
(
PWINE_REGSTOREINFO
)
hCertStore
;
TRACE
(
"(%p, %08x)
\n
"
,
store
,
dwFlags
);
if
(
dwFlags
)
FIXME
(
"Unimplemented flags: %08x
\n
"
,
dwFlags
);
CRYPT_RegFlushStore
(
store
,
FALSE
);
RegCloseKey
(
store
->
key
);
store
->
cs
.
DebugInfo
->
Spare
[
0
]
=
0
;
DeleteCriticalSection
(
&
store
->
cs
);
CryptMemFree
(
store
);
}
static
BOOL
WINAPI
CRYPT_RegWriteContext
(
PWINE_REGSTOREINFO
store
,
const
void
*
context
,
DWORD
dwFlags
)
{
BOOL
ret
;
if
(
dwFlags
&
CERT_STORE_PROV_WRITE_ADD_FLAG
)
{
store
->
dirty
=
TRUE
;
ret
=
TRUE
;
}
else
ret
=
FALSE
;
return
ret
;
}
static
BOOL
CRYPT_RegDeleteContext
(
PWINE_REGSTOREINFO
store
,
struct
list
*
deleteList
,
const
void
*
context
,
PCWINE_CONTEXT_INTERFACE
contextInterface
)
{
BOOL
ret
;
if
(
store
->
dwOpenFlags
&
CERT_STORE_READONLY_FLAG
)
{
SetLastError
(
ERROR_ACCESS_DENIED
);
ret
=
FALSE
;
}
else
{
PWINE_HASH_TO_DELETE
toDelete
=
CryptMemAlloc
(
sizeof
(
WINE_HASH_TO_DELETE
));
if
(
toDelete
)
{
DWORD
size
=
sizeof
(
toDelete
->
hash
);
ret
=
contextInterface
->
getProp
(
context
,
CERT_HASH_PROP_ID
,
toDelete
->
hash
,
&
size
);
if
(
ret
)
{
EnterCriticalSection
(
&
store
->
cs
);
list_add_tail
(
deleteList
,
&
toDelete
->
entry
);
LeaveCriticalSection
(
&
store
->
cs
);
}
else
{
CryptMemFree
(
toDelete
);
ret
=
FALSE
;
}
}
else
ret
=
FALSE
;
if
(
ret
)
store
->
dirty
=
TRUE
;
}
return
ret
;
}
static
BOOL
WINAPI
CRYPT_RegWriteCert
(
HCERTSTORE
hCertStore
,
PCCERT_CONTEXT
cert
,
DWORD
dwFlags
)
{
PWINE_REGSTOREINFO
store
=
(
PWINE_REGSTOREINFO
)
hCertStore
;
TRACE
(
"(%p, %p, %d)
\n
"
,
hCertStore
,
cert
,
dwFlags
);
return
CRYPT_RegWriteContext
(
store
,
cert
,
dwFlags
);
}
static
BOOL
WINAPI
CRYPT_RegDeleteCert
(
HCERTSTORE
hCertStore
,
PCCERT_CONTEXT
pCertContext
,
DWORD
dwFlags
)
{
PWINE_REGSTOREINFO
store
=
(
PWINE_REGSTOREINFO
)
hCertStore
;
TRACE
(
"(%p, %p, %08x)
\n
"
,
store
,
pCertContext
,
dwFlags
);
return
CRYPT_RegDeleteContext
(
store
,
&
store
->
certsToDelete
,
pCertContext
,
pCertInterface
);
}
static
BOOL
WINAPI
CRYPT_RegWriteCRL
(
HCERTSTORE
hCertStore
,
PCCRL_CONTEXT
crl
,
DWORD
dwFlags
)
{
PWINE_REGSTOREINFO
store
=
(
PWINE_REGSTOREINFO
)
hCertStore
;
TRACE
(
"(%p, %p, %d)
\n
"
,
hCertStore
,
crl
,
dwFlags
);
return
CRYPT_RegWriteContext
(
store
,
crl
,
dwFlags
);
}
static
BOOL
WINAPI
CRYPT_RegDeleteCRL
(
HCERTSTORE
hCertStore
,
PCCRL_CONTEXT
pCrlContext
,
DWORD
dwFlags
)
{
PWINE_REGSTOREINFO
store
=
(
PWINE_REGSTOREINFO
)
hCertStore
;
TRACE
(
"(%p, %p, %08x)
\n
"
,
store
,
pCrlContext
,
dwFlags
);
return
CRYPT_RegDeleteContext
(
store
,
&
store
->
crlsToDelete
,
pCrlContext
,
pCRLInterface
);
}
static
BOOL
WINAPI
CRYPT_RegControl
(
HCERTSTORE
hCertStore
,
DWORD
dwFlags
,
DWORD
dwCtrlType
,
void
const
*
pvCtrlPara
)
{
PWINE_REGSTOREINFO
store
=
(
PWINE_REGSTOREINFO
)
hCertStore
;
BOOL
ret
;
TRACE
(
"(%p, %08x, %d, %p)
\n
"
,
hCertStore
,
dwFlags
,
dwCtrlType
,
pvCtrlPara
);
switch
(
dwCtrlType
)
{
case
CERT_STORE_CTRL_RESYNC
:
CRYPT_RegFlushStore
(
store
,
FALSE
);
CRYPT_EmptyStore
(
store
->
memStore
);
CRYPT_RegReadFromReg
(
store
);
ret
=
TRUE
;
break
;
case
CERT_STORE_CTRL_COMMIT
:
ret
=
CRYPT_RegFlushStore
(
store
,
dwFlags
&
CERT_STORE_CTRL_COMMIT_FORCE_FLAG
);
break
;
default:
FIXME
(
"%d: stub
\n
"
,
dwCtrlType
);
ret
=
FALSE
;
}
return
ret
;
}
static
void
*
regProvFuncs
[]
=
{
CRYPT_RegCloseStore
,
NULL
,
/* CERT_STORE_PROV_READ_CERT_FUNC */
CRYPT_RegWriteCert
,
CRYPT_RegDeleteCert
,
NULL
,
/* CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC */
NULL
,
/* CERT_STORE_PROV_READ_CRL_FUNC */
CRYPT_RegWriteCRL
,
CRYPT_RegDeleteCRL
,
NULL
,
/* CERT_STORE_PROV_SET_CRL_PROPERTY_FUNC */
NULL
,
/* CERT_STORE_PROV_READ_CTL_FUNC */
NULL
,
/* CERT_STORE_PROV_WRITE_CTL_FUNC */
NULL
,
/* CERT_STORE_PROV_DELETE_CTL_FUNC */
NULL
,
/* CERT_STORE_PROV_SET_CTL_PROPERTY_FUNC */
CRYPT_RegControl
,
};
static
WINECRYPT_CERTSTORE
*
CRYPT_RegOpenStore
(
HCRYPTPROV
hCryptProv
,
DWORD
dwFlags
,
const
void
*
pvPara
)
{
PWINECRYPT_CERTSTORE
store
=
NULL
;
TRACE
(
"(%ld, %08x, %p)
\n
"
,
hCryptProv
,
dwFlags
,
pvPara
);
if
(
dwFlags
&
CERT_STORE_DELETE_FLAG
)
{
DWORD
rc
=
RegDeleteTreeW
((
HKEY
)
pvPara
,
CertsW
);
if
(
rc
==
ERROR_SUCCESS
||
rc
==
ERROR_NO_MORE_ITEMS
)
rc
=
RegDeleteTreeW
((
HKEY
)
pvPara
,
CRLsW
);
if
(
rc
==
ERROR_SUCCESS
||
rc
==
ERROR_NO_MORE_ITEMS
)
rc
=
RegDeleteTreeW
((
HKEY
)
pvPara
,
CTLsW
);
if
(
rc
==
ERROR_NO_MORE_ITEMS
)
rc
=
ERROR_SUCCESS
;
SetLastError
(
rc
);
}
else
{
HKEY
key
;
if
(
DuplicateHandle
(
GetCurrentProcess
(),
(
HANDLE
)
pvPara
,
GetCurrentProcess
(),
(
LPHANDLE
)
&
key
,
dwFlags
&
CERT_STORE_READONLY_FLAG
?
KEY_READ
:
KEY_ALL_ACCESS
,
TRUE
,
0
))
{
PWINECRYPT_CERTSTORE
memStore
;
memStore
=
CertOpenStore
(
CERT_STORE_PROV_MEMORY
,
0
,
hCryptProv
,
CERT_STORE_CREATE_NEW_FLAG
,
NULL
);
if
(
memStore
)
{
PWINE_REGSTOREINFO
regInfo
=
CryptMemAlloc
(
sizeof
(
WINE_REGSTOREINFO
));
if
(
regInfo
)
{
CERT_STORE_PROV_INFO
provInfo
=
{
0
};
regInfo
->
dwOpenFlags
=
dwFlags
;
regInfo
->
cryptProv
=
hCryptProv
;
regInfo
->
memStore
=
memStore
;
regInfo
->
key
=
key
;
InitializeCriticalSection
(
&
regInfo
->
cs
);
regInfo
->
cs
.
DebugInfo
->
Spare
[
0
]
=
(
DWORD_PTR
)(
__FILE__
": PWINE_REGSTOREINFO->cs"
);
list_init
(
&
regInfo
->
certsToDelete
);
list_init
(
&
regInfo
->
crlsToDelete
);
CRYPT_RegReadFromReg
(
regInfo
);
regInfo
->
dirty
=
FALSE
;
provInfo
.
cbSize
=
sizeof
(
provInfo
);
provInfo
.
cStoreProvFunc
=
sizeof
(
regProvFuncs
)
/
sizeof
(
regProvFuncs
[
0
]);
provInfo
.
rgpvStoreProvFunc
=
regProvFuncs
;
provInfo
.
hStoreProv
=
regInfo
;
store
=
CRYPT_ProvCreateStore
(
hCryptProv
,
dwFlags
,
memStore
,
&
provInfo
);
}
}
}
}
TRACE
(
"returning %p
\n
"
,
store
);
return
store
;
}
/* FIXME: this isn't complete for the Root store, in which the top-level
* self-signed CA certs reside. Adding a cert to the Root store should present
* the user with a dialog indicating the consequences of doing so, and asking
...
...
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