VirtualBox

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

Last change on this file since 60020 was 42991, checked in by vboxsync, 12 years ago

VBoxCertUtil: Fixed crashing when installing non-existent certificates.

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