Revision | 28844 (tree) |
---|---|
Zeit | 2020-04-25 15:30:01 |
Autor | stefankueng |
apply the e_capi patch.
@@ -1,6 +1,6 @@ | ||
1 | 1 | Index: engines/e_capi.c |
2 | 2 | =================================================================== |
3 | ---- engines/e_capi.c (revision 28672) | |
3 | +--- engines/e_capi.c (revision 28843) | |
4 | 4 | +++ engines/e_capi.c (working copy) |
5 | 5 | @@ -9,7 +9,7 @@ |
6 | 6 |
@@ -9,7 +9,7 @@ | ||
9 | 9 | |
10 | 10 | #ifdef _WIN32 |
11 | 11 | # ifndef _WIN32_WINNT |
12 | -# define _WIN32_WINNT 0x0400 | |
12 | +# define _WIN32_WINNT 0x0600 | |
13 | 13 | # endif |
14 | 14 | # include <windows.h> |
15 | 15 | # include <wincrypt.h> |
@@ -18,10 +18,11 @@ | ||
18 | 18 | # include <string.h> |
19 | 19 | # include <stdlib.h> |
20 | 20 | # include <malloc.h> |
21 | +# include <shlwapi.h> | |
21 | 22 | # ifndef alloca |
22 | 23 | # define alloca _alloca |
23 | 24 | # endif |
24 | - | |
25 | +# pragma comment(lib, "shlwapi.lib") | |
25 | 26 | # include <openssl/crypto.h> |
26 | 27 | |
27 | 28 | # ifndef OPENSSL_NO_CAPIENG |
@@ -31,6 +32,15 @@ | ||
31 | 32 | # include <openssl/rsa.h> |
32 | 33 | # include <openssl/dsa.h> |
33 | 34 | |
35 | +struct X509_name_st { | |
36 | + STACK_OF(X509_NAME_ENTRY) *entries; /* DN components */ | |
37 | + int modified; /* true if 'bytes' needs to be built */ | |
38 | + BUF_MEM *bytes; /* cached encoding: cannot be NULL */ | |
39 | + /* canonical encoding used for rapid Name comparison */ | |
40 | + unsigned char *canon_enc; | |
41 | + int canon_enclen; | |
42 | +} /* X509_NAME */ ; | |
43 | + | |
34 | 44 | /* |
35 | 45 | * This module uses several "new" interfaces, among which is |
36 | 46 | * CertGetCertificateContextProperty. CERT_KEY_PROV_INFO_PROP_ID is |
@@ -99,6 +109,96 @@ | ||
99 | 109 | # include "e_capi_err.h" |
100 | 110 | # include "e_capi_err.c" |
101 | 111 | |
112 | +char lastUsedAuthCacheHash[100] = {0}; | |
113 | + | |
114 | + void TSVN_GetSHA1HashFromX509(STACK_OF(X509_NAME) *ca_dn, char * outbuf) | |
115 | + { | |
116 | + HCRYPTPROV hProv = 0; | |
117 | + HCRYPTHASH hHash = 0; | |
118 | + DWORD cbHash = 0; | |
119 | + BYTE rgbHash[20]; | |
120 | + char sha1hashstring[50]; | |
121 | + CHAR rgbDigits[] = "0123456789abcdef"; | |
122 | + int i; | |
123 | + X509_NAME * nm; | |
124 | + | |
125 | + outbuf[0] = 0; | |
126 | + if (CryptAcquireContext(&hProv, | |
127 | + NULL, | |
128 | + NULL, | |
129 | + PROV_RSA_FULL, | |
130 | + CRYPT_VERIFYCONTEXT)) | |
131 | + { | |
132 | + if (CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash)) | |
133 | + { | |
134 | + for (i = 0; i < sk_X509_NAME_num(ca_dn); ++i) | |
135 | + { | |
136 | + nm = sk_X509_NAME_value(ca_dn, i); | |
137 | + CryptHashData(hHash, nm->canon_enc, nm->canon_enclen, 0); | |
138 | + } | |
139 | + | |
140 | + cbHash = 20; | |
141 | + if (CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0)) | |
142 | + { | |
143 | + for (i = 0; i < (int)cbHash; ++i) | |
144 | + { | |
145 | + sha1hashstring[i*2] = rgbDigits[rgbHash[i] >> 4]; | |
146 | + sha1hashstring[i*2+1] = rgbDigits[rgbHash[i] & 0xf]; | |
147 | + } | |
148 | + sha1hashstring[cbHash] = 0; | |
149 | + strcpy(outbuf, sha1hashstring); | |
150 | + } | |
151 | + CryptDestroyHash(hHash); | |
152 | + } | |
153 | + CryptReleaseContext(hProv, 0); | |
154 | + } | |
155 | + } | |
156 | + | |
157 | + int TSVN_GetSavedIndexForHash(const char* hash) | |
158 | + { | |
159 | + int ret = -1; | |
160 | + DWORD dwType = 0; | |
161 | + DWORD dwData = 0; | |
162 | + DWORD dwDataSize = 4; | |
163 | + int bLoad = 1; | |
164 | + if (SHGetValueA(HKEY_CURRENT_USER, "Software\\TortoiseSVN\\CAPIAuthz", hash, &dwType, &dwData, &dwDataSize) == ERROR_SUCCESS) | |
165 | + { | |
166 | + if (dwType == REG_DWORD) | |
167 | + { | |
168 | + ret = (int)dwData; | |
169 | + } | |
170 | + } | |
171 | + return ret; | |
172 | + } | |
173 | + | |
174 | + void TSVN_SaveIndexForHash(const char* hash, int index) | |
175 | + { | |
176 | + DWORD value = index; | |
177 | + SHSetValueA(HKEY_CURRENT_USER, "Software\\TortoiseSVN\\CAPIAuthz", hash, REG_DWORD, &value, sizeof(value)); | |
178 | + } | |
179 | + | |
180 | + void TSVN_ClearLastUsedAuthCache() | |
181 | + { | |
182 | + SHDeleteValueA(HKEY_CURRENT_USER, "Software\\TortoiseSVN\\CAPIAuthz", lastUsedAuthCacheHash); | |
183 | + } | |
184 | + | |
185 | + BOOL CALLBACK FindWindoProc(HWND hwnd, LPARAM lParam) | |
186 | + { | |
187 | + HWND * pWnd; | |
188 | + DWORD pid = 0; | |
189 | + if ((GetWindowLongPtr(hwnd, GWL_STYLE) & WS_VISIBLE)) | |
190 | + { | |
191 | + GetWindowThreadProcessId(hwnd, &pid); | |
192 | + if (pid == GetCurrentProcessId()) | |
193 | + { | |
194 | + pWnd = (HWND*)lParam; | |
195 | + (*pWnd) = hwnd; | |
196 | + return FALSE; | |
197 | + } | |
198 | + } | |
199 | + return TRUE; | |
200 | + } | |
201 | + | |
102 | 202 | static const char *engine_capi_id = "capi"; |
103 | 203 | static const char *engine_capi_name = "CryptoAPI ENGINE"; |
104 | 204 |
@@ -593,6 +693,22 @@ | ||
593 | 693 | |
594 | 694 | void engine_load_capi_int(void) |
595 | 695 | { |
696 | + DWORD dwType = 0; | |
697 | + DWORD dwData = 0; | |
698 | + DWORD dwDataSize = 4; | |
699 | + int bLoad = 1; | |
700 | + if (SHGetValueA(HKEY_CURRENT_USER, "Software\\TortoiseSVN", "OpenSSLCapi", &dwType, &dwData, &dwDataSize) == ERROR_SUCCESS) | |
701 | + { | |
702 | + if (dwType == REG_DWORD) | |
703 | + { | |
704 | + if (dwData == 0) | |
705 | + { | |
706 | + bLoad = 0; | |
707 | + } | |
708 | + } | |
709 | + } | |
710 | + if (bLoad) | |
711 | + { | |
596 | 712 | /* Copied from eng_[openssl|dyn].c */ |
597 | 713 | ENGINE *toadd = engine_capi(); |
598 | 714 | if (!toadd) |
@@ -600,6 +716,7 @@ | ||
600 | 716 | ENGINE_add(toadd); |
601 | 717 | ENGINE_free(toadd); |
602 | 718 | ERR_clear_error(); |
719 | + } | |
603 | 720 | } |
604 | 721 | # endif |
605 | 722 |
@@ -1507,9 +1624,11 @@ | ||
1507 | 1624 | dwFlags = CRYPT_MACHINE_KEYSET; |
1508 | 1625 | if (!CryptAcquireContextW(&key->hprov, contname, provname, ptype, |
1509 | 1626 | dwFlags)) { |
1510 | - CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_CRYPTACQUIRECONTEXT_ERROR); | |
1511 | - capi_addlasterror(); | |
1512 | - goto err; | |
1627 | + if (!CryptAcquireContext(&key->hprov, contname, provname, ptype, dwFlags)) { | |
1628 | + CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_CRYPTACQUIRECONTEXT_ERROR); | |
1629 | + capi_addlasterror(); | |
1630 | + goto err; | |
1631 | + } | |
1513 | 1632 | } |
1514 | 1633 | if (!CryptGetUserKey(key->hprov, keyspec, &key->key)) { |
1515 | 1634 | CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_GETUSERKEY_ERROR); |
@@ -1703,6 +1822,7 @@ | ||
1703 | 1822 | PCCERT_CONTEXT cert = NULL, excert = NULL; |
1704 | 1823 | CAPI_CTX *ctx; |
1705 | 1824 | CAPI_KEY *key; |
1825 | + char hash[100]; | |
1706 | 1826 | ctx = ENGINE_get_ex_data(e, capi_idx); |
1707 | 1827 | |
1708 | 1828 | *pcert = NULL; |
@@ -1759,9 +1879,22 @@ | ||
1759 | 1879 | return 0; |
1760 | 1880 | |
1761 | 1881 | /* Select the appropriate certificate */ |
1882 | + TSVN_GetSHA1HashFromX509(ca_dn, hash); | |
1883 | + strcpy(lastUsedAuthCacheHash, hash); | |
1884 | + client_cert_idx = TSVN_GetSavedIndexForHash(hash); | |
1885 | + if ((client_cert_idx < 0) || (client_cert_idx >= sk_X509_num(certs))) | |
1886 | + { | |
1887 | + client_cert_idx = ctx->client_cert_select(e, ssl, certs); | |
1888 | + if (client_cert_idx >= 0) | |
1889 | + { | |
1890 | + TSVN_SaveIndexForHash(hash, client_cert_idx); | |
1891 | + } | |
1892 | + } | |
1893 | + else if (client_cert_idx >= sk_X509_num(certs)) | |
1894 | + { | |
1895 | + TSVN_ClearLastUsedAuthCache(); | |
1896 | + } | |
1762 | 1897 | |
1763 | - client_cert_idx = ctx->client_cert_select(e, ssl, certs); | |
1764 | - | |
1765 | 1898 | /* Set the selected certificate and free the rest */ |
1766 | 1899 | |
1767 | 1900 | for (i = 0; i < sk_X509_num(certs); i++) { |
@@ -1794,7 +1927,9 @@ | ||
1794 | 1927 | |
1795 | 1928 | static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs) |
1796 | 1929 | { |
1797 | - return 0; | |
1930 | + if (sk_X509_num(certs) == 1) | |
1931 | + return 0; | |
1932 | + return -1; /* let TSVN decide which certificate to use */ | |
1798 | 1933 | } |
1799 | 1934 | |
1800 | 1935 | # ifdef OPENSSL_CAPIENG_DIALOG |
@@ -1814,7 +1949,7 @@ | ||
1814 | 1949 | # define CRYPTUI_SELECT_INTENDEDUSE_COLUMN 0x000000004 |
1815 | 1950 | # endif |
1816 | 1951 | |
1817 | -# define dlg_title L"OpenSSL Application SSL Client Certificate Selection" | |
1952 | +# define dlg_title L"TortoiseSVN SSL Client Certificate Selection" | |
1818 | 1953 | # define dlg_prompt L"Select a certificate to use for authentication" |
1819 | 1954 | # define dlg_columns CRYPTUI_SELECT_LOCATION_COLUMN \ |
1820 | 1955 | |CRYPTUI_SELECT_INTENDEDUSE_COLUMN |
@@ -1852,8 +1987,10 @@ | ||
1852 | 1987 | } |
1853 | 1988 | |
1854 | 1989 | } |
1855 | - hwnd = GetForegroundWindow(); | |
1990 | + EnumWindows(FindWindoProc, (LPARAM)&hwnd); | |
1856 | 1991 | if (!hwnd) |
1992 | + hwnd = GetForegroundWindow(); | |
1993 | + if (!hwnd) | |
1857 | 1994 | hwnd = GetActiveWindow(); |
1858 | 1995 | if (!hwnd && ctx->getconswindow) |
1859 | 1996 | hwnd = ctx->getconswindow(); |