reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
WinSecurity.cxx
Go to the documentation of this file.
1#include <sys/types.h>
2
3#if defined(HAVE_CONFIG_H)
4 #include "config.h"
5#endif
6
7
8#ifdef USE_SSL
10#include <openssl/e_os2.h>
11#include <openssl/evp.h>
12#include <openssl/crypto.h>
13#include <openssl/err.h>
14#include <openssl/pem.h>
15#include <openssl/pkcs7.h>
16#include <openssl/ossl_typ.h>
17#include <openssl/x509.h>
18#include <openssl/x509v3.h>
19#include <openssl/ssl.h>
20#include <openssl/pkcs12.h>
21
22#include <Wincrypt.h>
23#include "rutil/Logger.hxx"
24
25using namespace resip;
26using namespace std;
27
28#define RESIPROCATE_SUBSYSTEM Subsystem::SIP
29
30#include <windows.h>
31#include <wincrypt.h>
32
33void
35{
37 //getCerts(WinSecurity::CA_STORE);
38 //getCredentials(WinSecurity::PRIVATE_STORE);
39 //getCerts(WinSecurity::USERS_STORE);
40
41 // Preload any domain certs
43}
44
45void
46WinSecurity::onReadPEM(const Data& name, PEMType type, Data& buffer) const
47{
48 return;
49}
50
51void
52WinSecurity::onWritePEM(const Data& name, PEMType type, const Data& buffer) const
53{
54 return;
55}
56
57void
58WinSecurity::onRemovePEM(const Data& name, PEMType type) const
59{
60 return;
61}
62
63static const Data storeRootCA("Root");
64static const Data storeCA("CA");
65static const Data storePrivate("My");
66static const Data storeUsers("DOMAIN_USERS");
67static const Data storeUnknown("UNKNOWN_STORE");
68static const Data
70{
71 switch (pType)
72 {
74 case WinSecurity::CA_STORE: return storeCA;
77 default:
78 {
79 ErrLog( << "Some unknown certificate store type requested" << (int)(pType) );
80 resip_assert(0);
81 }
82 }
83 return storeUnknown;
84}
85
86#ifdef UNICODE
87static LPWSTR AnsiToUnicode(LPCSTR szInString)
88{
89 LPWSTR pwszString = NULL;
90 if(NULL == szInString))
91 return 0;
92
93int iLen = 0;
94iLen = MultiByteToWideChar( CP_UTF8, 0, szInString, -1, 0, 0 );
95if (0 == iLen)
96 return pwszString;
97
98 pwszString = (LPWSTR)LocalAlloc(
99 LMEM_FIXED,
100 iLen * sizeof(WCHAR)
101 );
102if (NULL == pwszString)
103 return pwszString;
104
105int iRet = MultiByteToWideChar( CP_UTF8, 0, szInString, -1, pwszString, iLen );
106
107if (0 == iRet)
108{
109 LocalFree(pwszString);
110}
111return pwszString;
112}
113#endif
114
115HCERTSTORE
117{
118 HCERTSTORE mStoreHandle = NULL;
119 LPCTSTR storeName = NULL;
120 DWORD dwFlags;
121
122 dwFlags = CERT_STORE_OPEN_EXISTING_FLAG | CERT_SYSTEM_STORE_LOCAL_MACHINE;
123
124#ifndef UNICODE
125 storeName = name.c_str();
126#else
127 storeName = AnsiToUnicode(name.c_str());
128#endif
129
130 if (NULL == storeName)
131 {
132 ErrLog( << " Invalid store name");
133 resip_assert(0);
134 return NULL;
135 }
136 //mStoreHandle = ::CertOpenStore(
137 // CERT_STORE_PROV_SYSTEM,
138 // 0,
139 // 0,
140 // dwFlags,
141 // storeName
142 // );
143 mStoreHandle = ::CertOpenSystemStore(0, name.c_str());
144#ifdef UNICODE
145 LocalFree((HLOCAL)storeName);
146#endif
147
148 if(NULL == mStoreHandle)
149 {
150 ErrLog( << name.c_str() << " system certificate store cannot be openned");
151 resip_assert(0);
152 return NULL;
153 }
154 InfoLog( << name.c_str() << " System certificate store opened");
155 return mStoreHandle;
156}
157
158void
159WinSecurity::closeCertifStore(HCERTSTORE storeHandle)
160{
161 if (NULL == storeHandle)
162 return;
163
164 ::CertCloseStore(storeHandle ,0);
165}
166
167void
169{
170 //retrive only certificates
171 HCERTSTORE storeHandle = NULL;
172 storeHandle = openSystemCertStore(certStoreTypes(eType));
173 int i = 0;
174 if(NULL != storeHandle)
175 {
176 InfoLog(<< "WinSecurity::getCerts: reading certs from store type=" << certStoreTypes(eType));
177
178 PCCERT_CONTEXT pCertContext = NULL;
179 while((pCertContext = ::CertEnumCertificatesInStore(storeHandle, pCertContext)) != NULL)
180 {
181 Data certDER(Data::Borrow, (const char*)pCertContext->pbCertEncoded, pCertContext->cbCertEncoded);
182 addCertDER (BaseSecurity::RootCert, NULL, certDER, false);
183
184 /*
185 char pszNameString[256] = {0};
186 CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, pszNameString, sizeof(pszNameString));
187 char pszIssuerString[256] = {0};
188 CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL, pszIssuerString, sizeof(pszIssuerString));
189 char pszFriendlyNameString[256] = {0};
190 CertGetNameString(pCertContext, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, pszFriendlyNameString, sizeof(pszFriendlyNameString));
191 char pszRDNString[256] = {0};
192 DWORD dwStrType = CERT_X500_NAME_STR;
193 //DWORD dwStrType = CERT_SIMPLE_NAME_STR;
194 CertGetNameString(pCertContext, CERT_NAME_RDN_TYPE, 0, &dwStrType, pszRDNString, sizeof(pszRDNString));
195
196 DebugLog(<< "[" << i+1 << "] WinSecurity::getCerts: CertificateInfo: Version=" << pCertContext->pCertInfo->dwVersion);
197 DebugLog(<< " Name=" << pszNameString);
198 DebugLog(<< " Issuer=" << pszIssuerString);
199 DebugLog(<< " FriendlyName=" << pszFriendlyNameString);
200 DebugLog(<< " Subject=" << pszRDNString); */
201 i++;
202 }
203 CertFreeCertificateContext(pCertContext);
204 }
205 InfoLog( << i << " certs loaded of type " << eType );
206 closeCertifStore(storeHandle);
207}
208
209void
211{
212 //retrieves both certificates and assocaited private keys
213 //retrive only certificates
214 HCERTSTORE storeHandle = NULL;
215 storeHandle = openSystemCertStore(certStoreTypes(eType));
216 int i = 0;
217 int ip = 0;
218 if(NULL != storeHandle)
219 {
220 PCCERT_CONTEXT pCertContext = NULL;
221 while((pCertContext = ::CertEnumCertificatesInStore(storeHandle, pCertContext)) != NULL)
222 {
223 Data certDER(Data::Borrow, (const char*)pCertContext->pbCertEncoded, pCertContext->cbCertEncoded);
224 addCertDER (BaseSecurity::DomainCert, NULL, certDER, true);
225
226 char pszNameString[256] = {0};
227 CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, pszNameString, sizeof(pszNameString));
228 char pszIssuerString[256] = {0};
229 CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL, pszIssuerString, sizeof(pszIssuerString));
230 char pszFriendlyNameString[256] = {0};
231 CertGetNameString(pCertContext, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, pszFriendlyNameString, sizeof(pszFriendlyNameString));
232 char pszRDNString[256] = {0};
233 DWORD dwStrType = CERT_X500_NAME_STR;
234 //DWORD dwStrType = CERT_SIMPLE_NAME_STR;
235 CertGetNameString(pCertContext, CERT_NAME_RDN_TYPE, 0, &dwStrType, pszRDNString, sizeof(pszRDNString));
236
237 DebugLog(<< "[" << i+1 << "] WinSecurity::getCerts: CertificateInfo: Version=" << pCertContext->pCertInfo->dwVersion);
238 DebugLog(<< " Name=" << pszNameString);
239 DebugLog(<< " Issuer=" << pszIssuerString);
240 DebugLog(<< " FriendlyName=" << pszFriendlyNameString);
241 DebugLog(<< " Subject=" << pszRDNString);
242 i++;
243
244 DWORD dwKeySpec;
245 HCRYPTPROV hCryptProv;
246 BOOL bCallerFreeProvOrNCryptKey;
247 //get private key
248 BOOL bRet = CryptAcquireCertificatePrivateKey(
249 pCertContext,
250 0,
251 NULL,
252 &hCryptProv,
253 &dwKeySpec,
254 &bCallerFreeProvOrNCryptKey);
255 if (!bRet)
256 {
257 DWORD dwRet = GetLastError();
258 if(dwRet == CRYPT_E_NO_KEY_PROPERTY)
259 {
260 ErrLog( << " Cannot retrieve private key - non present!");
261 }
262 else
263 {
264 ErrLog( << " Cannot retrieve private key, dwRet=" << dwRet);
265 }
266 }
267 else
268 {
269 DebugLog(<< " PrivateKey=Loaded!");
270 ip++;
271
272 HCERTSTORE hMemoryStore;
273 if(hMemoryStore = CertOpenStore(
274 CERT_STORE_PROV_MEMORY, // Memory store
275 0, // Encoding type
276 // not used with a memory store
277 NULL, // Use the default provider
278 0, // No flags
279 NULL)) // Not needed
280 {
281 printf("Opened a memory store for private key export. \n");
282
283 //-------------------------------------------------------------------
284 // Add the certificate from the My store to the new memory store.
285 if(CertAddCertificateContextToStore(
286 hMemoryStore, // Store handle
287 pCertContext, // Pointer to a certificate
288 CERT_STORE_ADD_USE_EXISTING,
289 NULL))
290 {
291 printf("Certificate added to the memory store. \n");
292
293 CRYPT_DATA_BLOB dataBlob = {0};
294 LPCWSTR password = L""; // your password for the cretificate and private key goes here
295
296 if(PFXExportCertStoreEx(hMemoryStore, &dataBlob, password, NULL,
297 EXPORT_PRIVATE_KEYS | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY | REPORT_NO_PRIVATE_KEY))
298 {
299 if (dataBlob.cbData > 0)
300 {
301 dataBlob.pbData = (BYTE*)malloc(dataBlob.cbData);
302 if (PFXExportCertStoreEx(hMemoryStore, &dataBlob, password, NULL,
303 EXPORT_PRIVATE_KEYS | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY | REPORT_NO_PRIVATE_KEY))
304 {
305 EVP_PKEY *pkey;
306 X509 *cert;
307 STACK_OF(X509) *ca = NULL;
308 PKCS12 *p12;
309
310 BIO* input = BIO_new_mem_buf((void*)dataBlob.pbData, dataBlob.cbData);
311 p12 = d2i_PKCS12_bio(input, NULL);
312
313 PKCS12_parse(p12, "" /* password */, &pkey, &cert, &ca);
314 PKCS12_free(p12);
315
316 if (pkey)
317 {
318 BIO *bo = BIO_new( BIO_s_mem() );
319 PEM_write_bio_PrivateKey(bo, pkey, NULL, (unsigned char *)"" /* password */, 0, NULL, (char*)"" /* password */);
320
321 char *p;
322 long len = BIO_get_mem_data(bo, &p);
323
324 Data keyPEM(Data::Borrow, (const char*)p, len);
325 addDomainPrivateKeyPEM("test", keyPEM);
326
327 BIO_free_all(bo);
328 }
329 free(dataBlob.pbData);
330 }
331 }
332 }
333 else
334 {
335 DWORD dwRet = GetLastError();
336 ErrLog( << " Could not PFXExportCertStoreEx, dwRet=" << dwRet);
337 }
338 }
339 else
340 {
341 DWORD dwRet = GetLastError();
342 ErrLog( << " Could not add the certificate to the memory store, dwRet=" << dwRet);
343 }
344
345 CertCloseStore(hMemoryStore, CERT_CLOSE_STORE_CHECK_FLAG);
346 }
347 else
348 {
349 DWORD dwRet = GetLastError();
350 ErrLog( << " Cannot open cert store, dwRet=" << dwRet);
351 }
352
353 if(bCallerFreeProvOrNCryptKey)
354 {
355#if(_WIN32_WINNT >= 0x0600)
356 if(dwKeySpec == CERT_NCRYPT_KEY_SPEC)
357 {
358 NCryptFreeObject(hCryptProv);
359 }
360 else
361 {
362 CryptReleaseContext(hCryptProv, 0);
363 }
364#else
365 CryptReleaseContext(hCryptProv, 0);
366#endif // if(_WIN32_WINNT >= 0x0600)
367 }
368 }
369 }
370 }
371 InfoLog( << i << " certs loaded of type " << eType << " (" << ip << " private keys loaded)");
372 closeCertifStore(storeHandle);
373}
374
375#endif // ifdef USE_SSL
376
377/* ====================================================================
378 * The Vovida Software License, Version 1.0
379 *
380 * Copyright (c) 2026 SIP Spectrum, Inc. https://www.sipspectrum.com
381 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
382 *
383 * Redistribution and use in source and binary forms, with or without
384 * modification, are permitted provided that the following conditions
385 * are met:
386 *
387 * 1. Redistributions of source code must retain the above copyright
388 * notice, this list of conditions and the following disclaimer.
389 *
390 * 2. Redistributions in binary form must reproduce the above copyright
391 * notice, this list of conditions and the following disclaimer in
392 * the documentation and/or other materials provided with the
393 * distribution.
394 *
395 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
396 * and "Vovida Open Communication Application Library (VOCAL)" must
397 * not be used to endorse or promote products derived from this
398 * software without prior written permission. For written
399 * permission, please contact vocal@vovida.org.
400 *
401 * 4. Products derived from this software may not be called "VOCAL", nor
402 * may "VOCAL" appear in their name, without prior written
403 * permission of Vovida Networks, Inc.
404 *
405 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
406 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
407 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
408 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
409 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
410 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
411 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
412 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
413 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
414 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
415 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
416 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
417 * DAMAGE.
418 *
419 * ====================================================================
420 *
421 * This software consists of voluntary contributions made by Vovida
422 * Networks, Inc. and many individuals on behalf of Vovida Networks,
423 * Inc. For more information on Vovida Networks, Inc., please see
424 * <http://www.vovida.org/>.
425 *
426 */
struct evp_pkey_st EVP_PKEY
struct x509_st X509
#define DebugLog(args_)
Definition Logger.hxx:128
#define InfoLog(args_)
Definition Logger.hxx:131
#define ErrLog(args_)
Definition Logger.hxx:137
#define resip_assert(x)
This file needs to work for both C and C++ code.
static const Data storePrivate("My")
static const Data storeUnknown("UNKNOWN_STORE")
static const Data storeUsers("DOMAIN_USERS")
static const Data certStoreTypes(WinSecurity::MsCertStoreType pType)
static const Data storeCA("CA")
static const Data storeRootCA("Root")
void addCertDER(PEMType type, const Data &name, const Data &certDER, bool write)
Definition Security.cxx:550
void addDomainPrivateKeyPEM(const Data &domainName, const Data &privateKeyPEM, const Data &privateKeyPassPhrase=Data::Empty)
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
const char * c_str() const
Returns a null-terminated string representing.
Definition Data.cxx:1097
@ Borrow
The Data instance is borrowing the memory from the passed in buffer.
Definition Data.hxx:260
virtual void preload()
Definition Security.cxx:277
virtual void preload()
void getCredentials(MsCertStoreType eType)
void closeCertifStore(HCERTSTORE)
virtual void onRemovePEM(const Data &name, PEMType type) const
void getCerts(MsCertStoreType eType)
virtual void onWritePEM(const Data &name, PEMType type, const Data &buffer) const
virtual void onReadPEM(const Data &name, PEMType type, Data &buffer) const
HCERTSTORE openSystemCertStore(const Data &name)
dcm! – add UnusedChecking(_enum) below;