VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/tools/VBoxCertUtil.cpp@ 69222

Last change on this file since 69222 was 67935, checked in by vboxsync, 7 years ago

VBoxCertUtil: made the add-trusted-publisher command more flexible by globbing both root and trusted publisher certs, allowing multiple certs to be installed at once.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.8 KB
Line 
1/* $Id: VBoxCertUtil.cpp 67935 2017-07-12 14:56:29Z vboxsync $ */
2/** @file
3 * VBoxCertUtil - VBox Certificate Utility - Windows Only.
4 */
5
6/*
7 * Copyright (C) 2012-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#include <iprt/win/windows.h>
23#include <Wincrypt.h>
24
25#include <iprt/buildconfig.h>
26#include <iprt/err.h>
27#include <iprt/file.h>
28#include <iprt/getopt.h>
29#include <iprt/initterm.h>
30#include <iprt/message.h>
31#include <iprt/path.h>
32#include <iprt/stream.h>
33#include <iprt/string.h>
34#include <iprt/time.h>
35
36
37/*******************************************************************************
38* Global Variables *
39*******************************************************************************/
40/** The verbosity level. */
41static unsigned g_cVerbosityLevel = 1;
42
43
44static const char *errorToString(DWORD dwErr)
45{
46 switch (dwErr)
47 {
48#define MY_CASE(a_uConst) case a_uConst: return #a_uConst;
49 MY_CASE(CRYPT_E_MSG_ERROR);
50 MY_CASE(CRYPT_E_UNKNOWN_ALGO);
51 MY_CASE(CRYPT_E_OID_FORMAT);
52 MY_CASE(CRYPT_E_INVALID_MSG_TYPE);
53 MY_CASE(CRYPT_E_UNEXPECTED_ENCODING);
54 MY_CASE(CRYPT_E_AUTH_ATTR_MISSING);
55 MY_CASE(CRYPT_E_HASH_VALUE);
56 MY_CASE(CRYPT_E_INVALID_INDEX);
57 MY_CASE(CRYPT_E_ALREADY_DECRYPTED);
58 MY_CASE(CRYPT_E_NOT_DECRYPTED);
59 MY_CASE(CRYPT_E_RECIPIENT_NOT_FOUND);
60 MY_CASE(CRYPT_E_CONTROL_TYPE);
61 MY_CASE(CRYPT_E_ISSUER_SERIALNUMBER);
62 MY_CASE(CRYPT_E_SIGNER_NOT_FOUND);
63 MY_CASE(CRYPT_E_ATTRIBUTES_MISSING);
64 MY_CASE(CRYPT_E_STREAM_MSG_NOT_READY);
65 MY_CASE(CRYPT_E_STREAM_INSUFFICIENT_DATA);
66 MY_CASE(CRYPT_I_NEW_PROTECTION_REQUIRED);
67 MY_CASE(CRYPT_E_BAD_LEN);
68 MY_CASE(CRYPT_E_BAD_ENCODE);
69 MY_CASE(CRYPT_E_FILE_ERROR);
70 MY_CASE(CRYPT_E_NOT_FOUND);
71 MY_CASE(CRYPT_E_EXISTS);
72 MY_CASE(CRYPT_E_NO_PROVIDER);
73 MY_CASE(CRYPT_E_SELF_SIGNED);
74 MY_CASE(CRYPT_E_DELETED_PREV);
75 MY_CASE(CRYPT_E_NO_MATCH);
76 MY_CASE(CRYPT_E_UNEXPECTED_MSG_TYPE);
77 MY_CASE(CRYPT_E_NO_KEY_PROPERTY);
78 MY_CASE(CRYPT_E_NO_DECRYPT_CERT);
79 MY_CASE(CRYPT_E_BAD_MSG);
80 MY_CASE(CRYPT_E_NO_SIGNER);
81 MY_CASE(CRYPT_E_PENDING_CLOSE);
82 MY_CASE(CRYPT_E_REVOKED);
83 MY_CASE(CRYPT_E_NO_REVOCATION_DLL);
84 MY_CASE(CRYPT_E_NO_REVOCATION_CHECK);
85 MY_CASE(CRYPT_E_REVOCATION_OFFLINE);
86 MY_CASE(CRYPT_E_NOT_IN_REVOCATION_DATABASE);
87 MY_CASE(CRYPT_E_INVALID_NUMERIC_STRING);
88 MY_CASE(CRYPT_E_INVALID_PRINTABLE_STRING);
89 MY_CASE(CRYPT_E_INVALID_IA5_STRING);
90 MY_CASE(CRYPT_E_INVALID_X500_STRING);
91 MY_CASE(CRYPT_E_NOT_CHAR_STRING);
92 MY_CASE(CRYPT_E_FILERESIZED);
93 MY_CASE(CRYPT_E_SECURITY_SETTINGS);
94 MY_CASE(CRYPT_E_NO_VERIFY_USAGE_DLL);
95 MY_CASE(CRYPT_E_NO_VERIFY_USAGE_CHECK);
96 MY_CASE(CRYPT_E_VERIFY_USAGE_OFFLINE);
97 MY_CASE(CRYPT_E_NOT_IN_CTL);
98 MY_CASE(CRYPT_E_NO_TRUSTED_SIGNER);
99 MY_CASE(CRYPT_E_MISSING_PUBKEY_PARA);
100 MY_CASE(CRYPT_E_OSS_ERROR);
101 default:
102 {
103 PCRTCOMERRMSG pWinComMsg = RTErrCOMGet(dwErr);
104 if (pWinComMsg)
105 return pWinComMsg->pszDefine;
106
107 static char s_szErr[32];
108 RTStrPrintf(s_szErr, sizeof(s_szErr), "%#x (%d)", dwErr, dwErr);
109 return s_szErr;
110 }
111 }
112}
113
114#if 0 /* hacking */
115static RTEXITCODE addToStore(const char *pszFilename, PCRTUTF16 pwszStore)
116{
117 /*
118 * Open the source.
119 */
120 void *pvFile;
121 size_t cbFile;
122 int rc = RTFileReadAll(pszFilename, &pvFile, &cbFile);
123 if (RT_FAILURE(rc))
124 return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTFileReadAll failed on '%s': %Rrc", pszFilename, rc);
125
126 RTEXITCODE rcExit = RTEXITCODE_FAILURE;
127
128 PCCERT_CONTEXT pCertCtx = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
129 (PBYTE)pvFile,
130 (DWORD)cbFile);
131 if (pCertCtx)
132 {
133 /*
134 * Open the destination.
135 */
136 HCERTSTORE hDstStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
137 PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
138 NULL /* hCryptProv = default */,
139 /*CERT_SYSTEM_STORE_LOCAL_MACHINE*/ CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG,
140 pwszStore);
141 if (hDstStore != NULL)
142 {
143#if 0
144 DWORD dwContextType;
145 if (CertAddSerializedElementToStore(hDstStore,
146 pCertCtx->pbCertEncoded,
147 pCertCtx->cbCertEncoded,
148 CERT_STORE_ADD_NEW,
149 0 /* dwFlags (reserved) */,
150 CERT_STORE_ALL_CONTEXT_FLAG,
151 &dwContextType,
152 NULL))
153 {
154 RTMsgInfo("Successfully added '%s' to the '%ls' store (ctx type %u)", pszFilename, pwszStore, dwContextType);
155 rcExit = RTEXITCODE_SUCCESS;
156 }
157 else
158 RTMsgError("CertAddSerializedElementToStore returned %s", errorToString(GetLastError()));
159#else
160 if (CertAddCertificateContextToStore(hDstStore, pCertCtx, CERT_STORE_ADD_NEW, NULL))
161 {
162 RTMsgInfo("Successfully added '%s' to the '%ls' store", pszFilename, pwszStore);
163 rcExit = RTEXITCODE_SUCCESS;
164 }
165 else
166 RTMsgError("CertAddCertificateContextToStore returned %s", errorToString(GetLastError()));
167#endif
168
169 CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG);
170 }
171 else
172 RTMsgError("CertOpenStore returned %s", errorToString(GetLastError()));
173 CertFreeCertificateContext(pCertCtx);
174 }
175 else
176 RTMsgError("CertCreateCertificateContext returned %s", errorToString(GetLastError()));
177 RTFileReadAllFree(pvFile, cbFile);
178 return rcExit;
179
180#if 0
181
182 CRYPT_DATA_BLOB Blob;
183 Blob.cbData = (DWORD)cbData;
184 Blob.pbData = (PBYTE)pvData;
185 HCERTSTORE hSrcStore = PFXImportCertStore(&Blob, L"", )
186
187#endif
188}
189#endif /* hacking */
190
191
192/**
193 * Reads a certificate from a file, returning a context or a the handle to a
194 * temporary memory store.
195 *
196 * @returns true on success, false on failure (error message written).
197 * @param pszCertFile The name of the file containing the
198 * certificates.
199 * @param ppOutCtx Where to return the certificate context.
200 * @param phSrcStore Where to return the handle to the temporary
201 * memory store.
202 */
203static bool readCertFile(const char *pszCertFile, PCCERT_CONTEXT *ppOutCtx, HCERTSTORE *phSrcStore)
204{
205 *ppOutCtx = NULL;
206 *phSrcStore = NULL;
207
208 bool fRc = false;
209 void *pvFile;
210 size_t cbFile;
211 int rc = RTFileReadAll(pszCertFile, &pvFile, &cbFile);
212 if (RT_SUCCESS(rc))
213 {
214 *ppOutCtx = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
215 (PBYTE)pvFile, (DWORD)cbFile);
216 if (*ppOutCtx)
217 fRc = true;
218 else
219 {
220 /** @todo figure out if it's some other format... */
221 RTMsgError("CertCreateCertificateContext returned %s parsing the content of '%s'",
222 errorToString(GetLastError()), pszCertFile);
223 }
224 RTFileReadAllFree(pvFile, cbFile);
225 }
226 else
227 RTMsgError("RTFileReadAll failed on '%s': %Rrc", pszCertFile, rc);
228 return fRc;
229}
230
231
232/**
233 * Opens a certificate store.
234 *
235 * @returns true on success, false on failure (error message written).
236 * @param dwDst The destination, like
237 * CERT_SYSTEM_STORE_LOCAL_MACHINE or
238 * CERT_SYSTEM_STORE_CURRENT_USER.
239 * @param pszStoreNm The store name.
240 */
241static HCERTSTORE openCertStore(DWORD dwDst, const char *pszStoreNm)
242{
243 HCERTSTORE hStore = NULL;
244 PRTUTF16 pwszStoreNm;
245 int rc = RTStrToUtf16(pszStoreNm, &pwszStoreNm);
246 if (RT_SUCCESS(rc))
247 {
248 if (g_cVerbosityLevel > 1)
249 RTMsgInfo("Opening store %#x:'%s'", dwDst, pszStoreNm);
250
251 /*
252 * Make sure CERT_STORE_OPEN_EXISTING_FLAG is not set. This causes Windows XP
253 * to return ACCESS_DENIED when installing TrustedPublisher certificates via
254 * CertAddCertificateContextToStore() if the TrustedPublisher store never has
255 * been used (through certmgr.exe and friends) yet.
256 *
257 * According to MSDN, if neither CERT_STORE_OPEN_EXISTING_FLAG nor
258 * CERT_STORE_CREATE_NEW_FLAG is set, the store will be either opened or
259 * created accordingly.
260 */
261 dwDst &= ~CERT_STORE_OPEN_EXISTING_FLAG;
262
263 hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
264 PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
265 NULL /* hCryptProv = default */,
266 dwDst,
267 pwszStoreNm);
268 if (hStore == NULL)
269 RTMsgError("CertOpenStore failed opening %#x:'%s': %s",
270 dwDst, pszStoreNm, errorToString(GetLastError()));
271
272 RTUtf16Free(pwszStoreNm);
273 }
274 return hStore;
275}
276
277/**
278 * Removes a certificate, given by file, from a store
279 *
280 * @returns true on success, false on failure (error message written).
281 * @param dwDst The destination, like
282 * CERT_SYSTEM_STORE_LOCAL_MACHINE or
283 * CERT_SYSTEM_STORE_CURRENT_USER.
284 * @param pszStoreNm The store name.
285 * @param pszCertFile The file containing the certificate to add.
286 */
287static bool removeCertFromStoreByFile(DWORD dwDst, const char *pszStoreNm, const char *pszCertFile)
288{
289 /*
290 * Read the certificate file first.
291 */
292 PCCERT_CONTEXT pSrcCtx = NULL;
293 HCERTSTORE hSrcStore = NULL;
294 if (!readCertFile(pszCertFile, &pSrcCtx, &hSrcStore))
295 return false;
296
297 WCHAR wszName[1024];
298 if (!CertGetNameStringW(pSrcCtx, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0 /*dwFlags*/, NULL /*pvTypePara*/,
299 wszName, sizeof(wszName)))
300 {
301 RTMsgError("CertGetNameStringW(Subject) failed: %s\n", errorToString(GetLastError()));
302 wszName[0] = '\0';
303 }
304
305 /*
306 * Open the destination store.
307 */
308 bool fRc = false;
309 HCERTSTORE hDstStore = openCertStore(dwDst, pszStoreNm);
310 if (hDstStore)
311 {
312 if (pSrcCtx)
313 {
314 fRc = true;
315 unsigned cDeleted = 0;
316 PCCERT_CONTEXT pCurCtx = NULL;
317 while ((pCurCtx = CertEnumCertificatesInStore(hDstStore, pCurCtx)) != NULL)
318 {
319 if (CertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, pCurCtx->pCertInfo, pSrcCtx->pCertInfo))
320 {
321 if (g_cVerbosityLevel > 1)
322 RTMsgInfo("Removing '%ls'...", wszName);
323 PCCERT_CONTEXT pDeleteCtx = CertDuplicateCertificateContext(pCurCtx);
324 if (pDeleteCtx)
325 {
326 if (CertDeleteCertificateFromStore(pDeleteCtx))
327 cDeleted++;
328 else
329 RTMsgError("CertDeleteFromStore('%ls') failed: %s\n", wszName, errorToString(GetLastError()));
330 }
331 else
332 RTMsgError("CertDuplicateCertificateContext('%ls') failed: %s\n", wszName, errorToString(GetLastError()));
333 }
334 }
335
336 if (!cDeleted)
337 RTMsgInfo("Found no matching certificates to remove.");
338 }
339 else
340 {
341 RTMsgError("Path not implemented at line %d\n", __LINE__);
342 }
343
344 CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG);
345 }
346 if (pSrcCtx)
347 CertFreeCertificateContext(pSrcCtx);
348 if (hSrcStore)
349 CertCloseStore(hSrcStore, CERT_CLOSE_STORE_CHECK_FLAG);
350 return fRc;
351}
352
353/**
354 * Adds a certificate to a store.
355 *
356 * @returns true on success, false on failure (error message written).
357 * @param dwDst The destination, like
358 * CERT_SYSTEM_STORE_LOCAL_MACHINE or
359 * CERT_SYSTEM_STORE_CURRENT_USER.
360 * @param pszStoreNm The store name.
361 * @param pszCertFile The file containing the certificate to add.
362 * @param dwDisposition The disposition towards existing certificates when
363 * adding it. CERT_STORE_ADD_NEW is a safe one.
364 */
365static bool addCertToStore(DWORD dwDst, const char *pszStoreNm, const char *pszCertFile, DWORD dwDisposition)
366{
367 /*
368 * Read the certificate file first.
369 */
370 PCCERT_CONTEXT pSrcCtx = NULL;
371 HCERTSTORE hSrcStore = NULL;
372 if (!readCertFile(pszCertFile, &pSrcCtx, &hSrcStore))
373 return false;
374
375 /*
376 * Open the destination store.
377 */
378 bool fRc = false;
379 HCERTSTORE hDstStore = openCertStore(dwDst, pszStoreNm);
380 if (hDstStore)
381 {
382 if (pSrcCtx)
383 {
384 if (g_cVerbosityLevel > 1)
385 RTMsgInfo("Adding '%s' to %#x:'%s'... (disp %d)", pszCertFile, dwDst, pszStoreNm, dwDisposition);
386
387 if (CertAddCertificateContextToStore(hDstStore, pSrcCtx, dwDisposition, NULL))
388 fRc = true;
389 else
390 RTMsgError("CertAddCertificateContextToStore returned %s", errorToString(GetLastError()));
391 }
392 else
393 RTMsgError("Path not implemented at line %d\n", __LINE__);
394
395 CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG);
396 }
397 if (pSrcCtx)
398 CertFreeCertificateContext(pSrcCtx);
399 if (hSrcStore)
400 CertCloseStore(hSrcStore, CERT_CLOSE_STORE_CHECK_FLAG);
401 return fRc;
402}
403
404/**
405 * Worker for cmdDisplayAll.
406 */
407static BOOL WINAPI displaySystemStoreCallback(const void *pvSystemStore, DWORD dwFlags, PCERT_SYSTEM_STORE_INFO pStoreInfo,
408 void *pvReserved, void *pvArg)
409{
410 RT_NOREF(pvArg);
411 if (g_cVerbosityLevel > 1)
412 RTPrintf(" pvSystemStore=%p dwFlags=%#x pStoreInfo=%p pvReserved=%p\n", pvSystemStore, dwFlags, pStoreInfo, pvReserved);
413 LPCWSTR pwszStoreNm = NULL;
414 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
415 {
416 const CERT_SYSTEM_STORE_RELOCATE_PARA *pRelPara = (const CERT_SYSTEM_STORE_RELOCATE_PARA *)pvSystemStore;
417 pwszStoreNm = pRelPara->pwszSystemStore;
418 RTPrintf(" %#010x '%ls' hKeyBase=%p\n", dwFlags, pwszStoreNm, pRelPara->hKeyBase);
419 }
420 else
421 {
422 pwszStoreNm = (LPCWSTR)pvSystemStore;
423 RTPrintf(" %#010x '%ls'\n", dwFlags, pwszStoreNm);
424 }
425
426 /*
427 * Open the store and list the certificates within.
428 */
429 DWORD dwDst = (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK);
430 HCERTSTORE hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
431 PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
432 NULL /* hCryptProv = default */,
433 dwDst | CERT_STORE_OPEN_EXISTING_FLAG,
434 pwszStoreNm);
435 if (hStore)
436 {
437 PCCERT_CONTEXT pCertCtx = NULL;
438 while ((pCertCtx = CertEnumCertificatesInStore(hStore, pCertCtx)) != NULL)
439 {
440 if (g_cVerbosityLevel > 1)
441 RTPrintf(" pCertCtx=%p dwCertEncodingType=%#x cbCertEncoded=%#x pCertInfo=%p\n",
442 pCertCtx, pCertCtx->dwCertEncodingType, pCertCtx->cbCertEncoded, pCertCtx->pCertInfo);
443 WCHAR wszName[1024];
444 if (CertGetNameStringW(pCertCtx, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0 /*dwFlags*/, NULL /*pvTypePara*/,
445 wszName, sizeof(wszName)))
446 {
447 RTPrintf(" '%ls'\n", wszName);
448 if (pCertCtx->pCertInfo)
449 {
450 RTTIMESPEC TmpTS;
451 char szNotBefore[80];
452 RTTimeSpecToString(RTTimeSpecSetNtFileTime(&TmpTS, &pCertCtx->pCertInfo->NotBefore),
453 szNotBefore, sizeof(szNotBefore));
454 char szNotAfter[80];
455 RTTimeSpecToString(RTTimeSpecSetNtFileTime(&TmpTS, &pCertCtx->pCertInfo->NotAfter),
456 szNotAfter, sizeof(szNotAfter));
457
458 RTPrintf(" NotBefore='%s'\n", szNotBefore);
459 RTPrintf(" NotAfter ='%s'\n", szNotAfter);
460 if (pCertCtx->pCertInfo->Issuer.cbData)
461 {
462 if (CertGetNameStringW(pCertCtx, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL /*pvTypePara*/,
463 wszName, sizeof(wszName)))
464 RTPrintf(" Issuer='%ls'\n", wszName);
465 else
466 RTMsgError("CertGetNameStringW(Issuer) failed: %s\n", errorToString(GetLastError()));
467 }
468 }
469 }
470 else
471 RTMsgError("CertGetNameStringW(Subject) failed: %s\n", errorToString(GetLastError()));
472
473 }
474
475 CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
476 }
477 else
478 RTMsgError("CertOpenStore failed opening %#x:'%ls': %s\n", dwDst, pwszStoreNm, errorToString(GetLastError()));
479
480 return TRUE;
481}
482
483/**
484 * Worker for cmdDisplayAll.
485 */
486static BOOL WINAPI displaySystemStoreLocation(LPCWSTR pwszStoreLocation, DWORD dwFlags, void *pvReserved, void *pvArg)
487{
488 NOREF(pvReserved); NOREF(pvArg);
489 RTPrintf("System store location: %#010x '%ls'\n", dwFlags, pwszStoreLocation);
490 if (!CertEnumSystemStore(dwFlags, NULL, NULL /*pvArg*/, displaySystemStoreCallback))
491 RTMsgError("CertEnumSystemStore failed on %#x:'%ls': %s\n",
492 dwFlags, pwszStoreLocation, errorToString(GetLastError()));
493
494 return TRUE;
495}
496
497/**
498 * Handler for the 'display-all' command.
499 */
500static RTEXITCODE cmdDisplayAll(int argc, char **argv)
501{
502 RT_NOREF(argv);
503 if (argc != 1)
504 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "the display-all command takes no arguments\n");
505
506 if (!CertEnumSystemStoreLocation(0, NULL /*pvArg*/, displaySystemStoreLocation))
507 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "CertEnumSystemStoreLocation failed: %s\n", errorToString(GetLastError()));
508
509 return RTEXITCODE_SUCCESS;
510}
511
512/**
513 * Handler for the 'remove-trusted-publisher' command.
514 */
515static RTEXITCODE cmdRemoveTrustedPublisher(int argc, char **argv)
516{
517 /*
518 * Parse arguments.
519 */
520 static const RTGETOPTDEF s_aOptions[] =
521 {
522 { "--root", 'r', RTGETOPT_REQ_STRING },
523 };
524
525 const char *pszRootCert = NULL;
526 const char *pszTrustedCert = NULL;
527
528 int rc;
529 RTGETOPTUNION ValueUnion;
530 RTGETOPTSTATE GetState;
531 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
532 while ((rc = RTGetOpt(&GetState, &ValueUnion)))
533 {
534 switch (rc)
535 {
536 case 'h':
537 RTPrintf("Usage: VBoxCertUtil remove-trusted-publisher [--root <root-cert>] <trusted-cert>\n");
538 break;
539
540 case 'V':
541 RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
542 return RTEXITCODE_SUCCESS;
543
544 case 'r':
545 if (pszRootCert)
546 return RTMsgErrorExit(RTEXITCODE_SUCCESS,
547 "You've already specified '%s' as root certificate.",
548 pszRootCert);
549 pszRootCert = ValueUnion.psz;
550 break;
551
552 case VINF_GETOPT_NOT_OPTION:
553 if (pszTrustedCert)
554 return RTMsgErrorExit(RTEXITCODE_SUCCESS,
555 "You've already specified '%s' as trusted certificate.",
556 pszRootCert);
557 pszTrustedCert = ValueUnion.psz;
558 break;
559
560 default:
561 return RTGetOptPrintError(rc, &ValueUnion);
562 }
563 }
564 if (!pszTrustedCert)
565 return RTMsgErrorExit(RTEXITCODE_SUCCESS, "No trusted certificate specified.");
566
567 /*
568 * Do the job.
569 */
570 if ( pszRootCert
571 && !removeCertFromStoreByFile(CERT_SYSTEM_STORE_LOCAL_MACHINE, "Root", pszRootCert))
572 return RTEXITCODE_FAILURE;
573 if (!removeCertFromStoreByFile(CERT_SYSTEM_STORE_LOCAL_MACHINE, "TrustedPublisher", pszTrustedCert))
574 return RTEXITCODE_FAILURE;
575
576 if (g_cVerbosityLevel > 0)
577 {
578 if (pszRootCert)
579 RTMsgInfo("Successfully removed '%s' as root and '%s' as trusted publisher", pszRootCert, pszTrustedCert);
580 else
581 RTMsgInfo("Successfully removed '%s' as trusted publisher", pszTrustedCert);
582 }
583 return RTEXITCODE_SUCCESS;
584}
585
586
587/**
588 * Handler for the 'add-trusted-publisher' command.
589 */
590static RTEXITCODE cmdAddTrustedPublisher(int argc, char **argv)
591{
592 /*
593 * Parse arguments and execute imports as we move along.
594 */
595 static const RTGETOPTDEF s_aOptions[] =
596 {
597 { "--root", 'r', RTGETOPT_REQ_STRING },
598 };
599
600 RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
601 unsigned cImports = 0;
602 RTGETOPTUNION ValueUnion;
603 RTGETOPTSTATE GetState;
604 int rc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
605 AssertRC(rc);
606 while ((rc = RTGetOpt(&GetState, &ValueUnion)))
607 {
608 switch (rc)
609 {
610 case 'h':
611 RTPrintf("Usage: VBoxCertUtil add-trusted-publisher [--root <root-cert>] <trusted-cert>\n");
612 break;
613
614 case 'V':
615 RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
616 return RTEXITCODE_SUCCESS;
617
618 case 'r':
619 case VINF_GETOPT_NOT_OPTION:
620 {
621 const char * const pszStoreNm = rc == 'r' ? "Root" : "TrustedPublisher";
622 const char * const pszStoreDesc = rc == 'r' ? "root" : "trusted publisher";
623 PCRTPATHGLOBENTRY pResultHead;
624 rc = RTPathGlob(ValueUnion.psz, RTPATHGLOB_F_NO_DIRS, &pResultHead, NULL);
625 if (RT_SUCCESS(rc))
626 {
627 for (PCRTPATHGLOBENTRY pCur = pResultHead; pCur; pCur = pCur->pNext)
628 {
629 if (addCertToStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, pszStoreNm, pCur->szPath, CERT_STORE_ADD_NEW))
630 RTMsgInfo("Successfully added '%s' as %s", pCur->szPath, pszStoreDesc);
631 else
632 rcExit = RTEXITCODE_FAILURE;
633 cImports++;
634 }
635 RTPathGlobFree(pResultHead);
636 }
637 else
638 {
639 rcExit = RTMsgErrorExit(RTEXITCODE_SUCCESS, "glob failed on '%s': %Rrc", ValueUnion.psz, rc);
640 cImports++;
641 }
642 break;
643 }
644
645 default:
646 return RTGetOptPrintError(rc, &ValueUnion);
647 }
648 }
649 if (cImports == 0)
650 return RTMsgErrorExit(RTEXITCODE_SUCCESS, "No trusted or root certificates specified.");
651 return rcExit;
652}
653
654
655/**
656 * Displays the usage info.
657 * @param argv0 Program name.
658 */
659static void showUsage(const char *argv0)
660{
661 RTPrintf("Usage: %Rbn [-v[v]] <command>\n"
662 " or %Rbn <-V|--version>\n"
663 " or %Rbn <-h|--help>\n"
664 "\n"
665 "Available commands:\n"
666 " add-trusted-publisher, remove-trusted-publisher,\n"
667 " display-all\n"
668 , argv0, argv0, argv0);
669}
670
671
672int main(int argc, char **argv)
673{
674 int rc = RTR3InitExe(argc, &argv, 0);
675 if (RT_FAILURE(rc))
676 return RTMsgInitFailure(rc);
677
678 /*
679 * Parse arguments up to the command and pass it on to the command handlers.
680 */
681 typedef enum
682 {
683 VCUACTION_ADD_TRUSTED_PUBLISHER = 1000,
684 VCUACTION_REMOVE_TRUSTED_PUBLISHER,
685 VCUACTION_DISPLAY_ALL,
686 VCUACTION_END
687 } VCUACTION;
688
689 static const RTGETOPTDEF s_aOptions[] =
690 {
691 { "--verbose", 'v', RTGETOPT_REQ_NOTHING },
692 { "--quiet", 'q', RTGETOPT_REQ_NOTHING },
693 { "add-trusted-publisher", VCUACTION_ADD_TRUSTED_PUBLISHER, RTGETOPT_REQ_NOTHING },
694 { "remove-trusted-publisher", VCUACTION_REMOVE_TRUSTED_PUBLISHER, RTGETOPT_REQ_NOTHING },
695 { "display-all", VCUACTION_DISPLAY_ALL, RTGETOPT_REQ_NOTHING },
696 };
697
698 RTGETOPTUNION ValueUnion;
699 RTGETOPTSTATE GetState;
700 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
701 while ((rc = RTGetOpt(&GetState, &ValueUnion)))
702 {
703 switch (rc)
704 {
705 case 'v':
706 g_cVerbosityLevel++;
707 break;
708
709 case 'q':
710 if (g_cVerbosityLevel > 0)
711 g_cVerbosityLevel--;
712 break;
713
714 case 'h':
715 showUsage(argv[0]);
716 return RTEXITCODE_SUCCESS;
717
718 case 'V':
719 RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
720 return RTEXITCODE_SUCCESS;
721
722 case VCUACTION_ADD_TRUSTED_PUBLISHER:
723 return cmdAddTrustedPublisher(argc - GetState.iNext + 1, argv + GetState.iNext - 1);
724
725 case VCUACTION_REMOVE_TRUSTED_PUBLISHER:
726 return cmdRemoveTrustedPublisher(argc - GetState.iNext + 1, argv + GetState.iNext - 1);
727
728 case VCUACTION_DISPLAY_ALL:
729 return cmdDisplayAll(argc - GetState.iNext + 1, argv + GetState.iNext - 1);
730
731 default:
732 return RTGetOptPrintError(rc, &ValueUnion);
733 }
734 }
735
736 RTMsgError("Missing command...");
737 showUsage(argv[0]);
738 return RTEXITCODE_SYNTAX;
739}
740
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette