VirtualBox

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

Last change on this file since 82968 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

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