VirtualBox

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

Last change on this file since 40901 was 39748, checked in by vboxsync, 13 years ago

VBoxCertUtil: remove-trusted-publisher + bugfix.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.3 KB
Line 
1/* $Id: VBoxCertUtil.cpp 39748 2012-01-11 14:42:05Z 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 }
224 else
225 RTMsgError("RTFileReadAll failed on '%s': %Rrc", pszCertFile, rc);
226 RTFileReadAllFree(pvFile, cbFile);
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 * ERT_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 hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
251 PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
252 NULL /* hCryptProv = default */,
253 dwDst | CERT_STORE_OPEN_EXISTING_FLAG,
254 pwszStoreNm);
255 if (hStore == NULL)
256 RTMsgError("CertOpenStore failed opening %#x:'%s': %s",
257 dwDst, pszStoreNm, errorToString(GetLastError()));
258
259 RTUtf16Free(pwszStoreNm);
260 }
261 return hStore;
262}
263
264/**
265 * Removes a certificate, given by file, from a store
266 *
267 * @returns true on success, false on failure (error message written).
268 * @param dwDst The destination, like
269 * CERT_SYSTEM_STORE_LOCAL_MACHINE or
270 * ERT_SYSTEM_STORE_CURRENT_USER.
271 * @param pszStoreNm The store name.
272 * @param pszCertFile The file containing the certificate to add.
273 */
274static bool removeCertFromStoreByFile(DWORD dwDst, const char *pszStoreNm, const char *pszCertFile)
275{
276 /*
277 * Read the certificate file first.
278 */
279 PCCERT_CONTEXT pSrcCtx = NULL;
280 HCERTSTORE hSrcStore = NULL;
281 if (!readCertFile(pszCertFile, &pSrcCtx, &hSrcStore))
282 return false;
283
284 WCHAR wszName[1024];
285 if (!CertGetNameStringW(pSrcCtx, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0 /*dwFlags*/, NULL /*pvTypePara*/,
286 wszName, sizeof(wszName)))
287 {
288 RTMsgError("CertGetNameStringW(Subject) failed: %s\n", errorToString(GetLastError()));
289 wszName[0] = '\0';
290 }
291
292 /*
293 * Open the destination store.
294 */
295 bool fRc = false;
296 HCERTSTORE hDstStore = openCertStore(dwDst, pszStoreNm);
297 if (hDstStore)
298 {
299 if (pSrcCtx)
300 {
301 fRc = true;
302 unsigned cDeleted = 0;
303 PCCERT_CONTEXT pCurCtx = NULL;
304 while ((pCurCtx = CertEnumCertificatesInStore(hDstStore, pCurCtx)) != NULL)
305 {
306 if (CertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, pCurCtx->pCertInfo, pSrcCtx->pCertInfo))
307 {
308 if (g_cVerbosityLevel > 1)
309 RTMsgInfo("Removing '%ls'...", wszName);
310 PCCERT_CONTEXT pDeleteCtx = CertDuplicateCertificateContext(pCurCtx);
311 if (pDeleteCtx)
312 {
313 if (CertDeleteCertificateFromStore(pDeleteCtx))
314 cDeleted++;
315 else
316 RTMsgError("CertDeleteFromStore('%ls') failed: %s\n", wszName, errorToString(GetLastError()));
317 }
318 else
319 RTMsgError("CertDuplicateCertificateContext('%ls') failed: %s\n", wszName, errorToString(GetLastError()));
320 }
321 }
322
323 if (!cDeleted)
324 RTMsgInfo("Found no matching certificates to remove.");
325 }
326 else
327 {
328 RTMsgError("Path not implemented at line %d\n", __LINE__);
329 }
330
331 CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG);
332 }
333 if (pSrcCtx)
334 CertFreeCertificateContext(pSrcCtx);
335 if (hSrcStore)
336 CertCloseStore(hSrcStore, CERT_CLOSE_STORE_CHECK_FLAG);
337 return fRc;
338}
339
340/**
341 * Adds a certificate to a store.
342 *
343 * @returns true on success, false on failure (error message written).
344 * @param dwDst The destination, like
345 * CERT_SYSTEM_STORE_LOCAL_MACHINE or
346 * ERT_SYSTEM_STORE_CURRENT_USER.
347 * @param pszStoreNm The store name.
348 * @param pszCertFile The file containing the certificate to add.
349 * @param dwDisposition The disposition towards existing certificates when
350 * adding it. CERT_STORE_ADD_NEW is a safe one.
351 */
352static bool addCertToStore(DWORD dwDst, const char *pszStoreNm, const char *pszCertFile, DWORD dwDisposition)
353{
354 /*
355 * Read the certificate file first.
356 */
357 PCCERT_CONTEXT pSrcCtx = NULL;
358 HCERTSTORE hSrcStore = NULL;
359 if (!readCertFile(pszCertFile, &pSrcCtx, &hSrcStore))
360 return false;
361
362 /*
363 * Open the destination store.
364 */
365 bool fRc = false;
366 HCERTSTORE hDstStore = openCertStore(dwDst, pszStoreNm);
367 if (hDstStore)
368 {
369 if (pSrcCtx)
370 {
371 if (g_cVerbosityLevel > 1)
372 RTMsgInfo("Adding '%s' to %#x:'%s'... (disp %d)", pszCertFile, dwDst, pszStoreNm, dwDisposition);
373
374 if (CertAddCertificateContextToStore(hDstStore, pSrcCtx, dwDisposition, NULL))
375 fRc = true;
376 else
377 RTMsgError("CertAddCertificateContextToStore returned %s", errorToString(GetLastError()));
378 }
379 else
380 {
381 RTMsgError("Path not implemented at line %d\n", __LINE__);
382 }
383
384 CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG);
385 }
386 if (pSrcCtx)
387 CertFreeCertificateContext(pSrcCtx);
388 if (hSrcStore)
389 CertCloseStore(hSrcStore, CERT_CLOSE_STORE_CHECK_FLAG);
390 return fRc;
391}
392
393/**
394 * Worker for cmdDisplayAll.
395 */
396static BOOL WINAPI displaySystemStoreCallback(const void *pvSystemStore, DWORD dwFlags, PCERT_SYSTEM_STORE_INFO pStoreInfo,
397 void *pvReserved, void *pvArg)
398{
399 if (g_cVerbosityLevel > 1)
400 RTPrintf(" pvSystemStore=%p dwFlags=%#x pStoreInfo=%p pvReserved=%p\n", pvSystemStore, dwFlags, pStoreInfo, pvReserved);
401 LPCWSTR pwszStoreNm = NULL;
402 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
403 {
404 const CERT_SYSTEM_STORE_RELOCATE_PARA *pRelPara = (const CERT_SYSTEM_STORE_RELOCATE_PARA *)pvSystemStore;
405 pwszStoreNm = pRelPara->pwszSystemStore;
406 RTPrintf(" %#010x '%ls' hKeyBase=%p\n", dwFlags, pwszStoreNm, pRelPara->hKeyBase);
407 }
408 else
409 {
410 pwszStoreNm = (LPCWSTR)pvSystemStore;
411 RTPrintf(" %#010x '%ls'\n", dwFlags, pwszStoreNm);
412 }
413
414 /*
415 * Open the store and list the certificates within.
416 */
417 DWORD dwDst = (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK);
418 HCERTSTORE hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
419 PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
420 NULL /* hCryptProv = default */,
421 dwDst | CERT_STORE_OPEN_EXISTING_FLAG,
422 pwszStoreNm);
423 if (hStore)
424 {
425 PCCERT_CONTEXT pCertCtx = NULL;
426 while ((pCertCtx = CertEnumCertificatesInStore(hStore, pCertCtx)) != NULL)
427 {
428 if (g_cVerbosityLevel > 1)
429 RTPrintf(" pCertCtx=%p dwCertEncodingType=%#x cbCertEncoded=%#x pCertInfo=%p\n",
430 pCertCtx, pCertCtx->dwCertEncodingType, pCertCtx->cbCertEncoded, pCertCtx->pCertInfo);
431 WCHAR wszName[1024];
432 if (CertGetNameStringW(pCertCtx, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0 /*dwFlags*/, NULL /*pvTypePara*/,
433 wszName, sizeof(wszName)))
434 {
435 RTPrintf(" '%ls'\n", wszName);
436 if (pCertCtx->pCertInfo)
437 {
438 RTTIMESPEC TmpTS;
439 char szNotBefore[80];
440 RTTimeSpecToString(RTTimeSpecSetNtFileTime(&TmpTS, &pCertCtx->pCertInfo->NotBefore),
441 szNotBefore, sizeof(szNotBefore));
442 char szNotAfter[80];
443 RTTimeSpecToString(RTTimeSpecSetNtFileTime(&TmpTS, &pCertCtx->pCertInfo->NotAfter),
444 szNotAfter, sizeof(szNotAfter));
445
446 RTPrintf(" NotBefore='%s'\n", szNotBefore);
447 RTPrintf(" NotAfter ='%s'\n", szNotAfter);
448 if (pCertCtx->pCertInfo->Issuer.cbData)
449 {
450 if (CertGetNameStringW(pCertCtx, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL /*pvTypePara*/,
451 wszName, sizeof(wszName)))
452 RTPrintf(" Issuer='%ls'\n", wszName);
453 else
454 RTMsgError("CertGetNameStringW(Issuer) failed: %s\n", errorToString(GetLastError()));
455 }
456 }
457 }
458 else
459 RTMsgError("CertGetNameStringW(Subject) failed: %s\n", errorToString(GetLastError()));
460
461 }
462
463 CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
464 }
465 else
466 RTMsgError("CertOpenStore failed opening %#x:'%ls': %s\n", dwDst, pwszStoreNm, errorToString(GetLastError()));
467
468 return TRUE;
469}
470
471/**
472 * Worker for cmdDisplayAll.
473 */
474static BOOL WINAPI displaySystemStoreLocation(LPCWSTR pwszStoreLocation, DWORD dwFlags, void *pvReserved, void *pvArg)
475{
476 NOREF(pvReserved); NOREF(pvArg);
477 RTPrintf("System store location: %#010x '%ls'\n", dwFlags, pwszStoreLocation);
478 if (!CertEnumSystemStore(dwFlags, NULL, NULL /*pvArg*/, displaySystemStoreCallback))
479 RTMsgError("CertEnumSystemStore failed on %#x:'%ls': %s\n",
480 dwFlags, pwszStoreLocation, errorToString(GetLastError()));
481
482 return TRUE;
483}
484
485/**
486 * Handler for the 'display-all' command.
487 */
488static RTEXITCODE cmdDisplayAll(int argc, char **argv)
489{
490 if (argc != 1)
491 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "the display-all command takes no arguments\n");
492
493 if (!CertEnumSystemStoreLocation(0, NULL /*pvArg*/, displaySystemStoreLocation))
494 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "CertEnumSystemStoreLocation failed: %s\n", errorToString(GetLastError()));
495
496 return RTEXITCODE_SUCCESS;
497}
498
499/**
500 * Handler for the 'remove-trusted-publisher' command.
501 */
502static RTEXITCODE cmdRemoveTrustedPublisher(int argc, char **argv)
503{
504 /*
505 * Parse arguments.
506 */
507 static const RTGETOPTDEF s_aOptions[] =
508 {
509 { "--root", 'r', RTGETOPT_REQ_STRING },
510 };
511
512 const char *pszRootCert = NULL;
513 const char *pszTrustedCert = NULL;
514
515 int rc;
516 RTGETOPTUNION ValueUnion;
517 RTGETOPTSTATE GetState;
518 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
519 while ((rc = RTGetOpt(&GetState, &ValueUnion)))
520 {
521 switch (rc)
522 {
523 case 'h':
524 RTPrintf("Usage: VBoxCertUtil remove-trusted-publisher [--root <root-cert>] <trusted-cert>\n");
525 break;
526
527 case 'V':
528 RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
529 return RTEXITCODE_SUCCESS;
530
531 case 'r':
532 if (pszRootCert)
533 return RTMsgErrorExit(RTEXITCODE_SUCCESS,
534 "You've already specified '%s' as root certificate.",
535 pszRootCert);
536 pszRootCert = ValueUnion.psz;
537 break;
538
539 case VINF_GETOPT_NOT_OPTION:
540 if (pszTrustedCert)
541 return RTMsgErrorExit(RTEXITCODE_SUCCESS,
542 "You've already specified '%s' as trusted certificate.",
543 pszRootCert);
544 pszTrustedCert = ValueUnion.psz;
545 break;
546
547 default:
548 return RTGetOptPrintError(rc, &ValueUnion);
549 }
550 }
551 if (!pszTrustedCert)
552 return RTMsgErrorExit(RTEXITCODE_SUCCESS, "No trusted certificate specified.");
553
554 /*
555 * Do the job.
556 */
557 if ( pszRootCert
558 && !removeCertFromStoreByFile(CERT_SYSTEM_STORE_LOCAL_MACHINE, "Root", pszRootCert))
559 return RTEXITCODE_FAILURE;
560 if (!removeCertFromStoreByFile(CERT_SYSTEM_STORE_LOCAL_MACHINE, "TrustedPublisher", pszTrustedCert))
561 return RTEXITCODE_FAILURE;
562
563 if (g_cVerbosityLevel > 0)
564 {
565 if (pszRootCert)
566 RTMsgInfo("Successfully removed '%s' as root and '%s' as trusted publisher", pszRootCert, pszTrustedCert);
567 else
568 RTMsgInfo("Successfully removed '%s' as trusted publisher", pszTrustedCert);
569 }
570 return RTEXITCODE_SUCCESS;
571}
572
573
574/**
575 * Handler for the 'add-trusted-publisher' command.
576 */
577static RTEXITCODE cmdAddTrustedPublisher(int argc, char **argv)
578{
579 /*
580 * Parse arguments.
581 */
582 static const RTGETOPTDEF s_aOptions[] =
583 {
584 { "--root", 'r', RTGETOPT_REQ_STRING },
585 };
586
587 const char *pszRootCert = NULL;
588 const char *pszTrustedCert = NULL;
589
590 int rc;
591 RTGETOPTUNION ValueUnion;
592 RTGETOPTSTATE GetState;
593 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
594 while ((rc = RTGetOpt(&GetState, &ValueUnion)))
595 {
596 switch (rc)
597 {
598 case 'h':
599 RTPrintf("Usage: VBoxCertUtil add-trusted-publisher [--root <root-cert>] <trusted-cert>\n");
600 break;
601
602 case 'V':
603 RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
604 return RTEXITCODE_SUCCESS;
605
606 case 'r':
607 if (pszRootCert)
608 return RTMsgErrorExit(RTEXITCODE_SUCCESS,
609 "You've already specified '%s' as root certificate.",
610 pszRootCert);
611 pszRootCert = ValueUnion.psz;
612 break;
613
614 case VINF_GETOPT_NOT_OPTION:
615 if (pszTrustedCert)
616 return RTMsgErrorExit(RTEXITCODE_SUCCESS,
617 "You've already specified '%s' as trusted certificate.",
618 pszRootCert);
619 pszTrustedCert = ValueUnion.psz;
620 break;
621
622 default:
623 return RTGetOptPrintError(rc, &ValueUnion);
624 }
625 }
626 if (!pszTrustedCert)
627 return RTMsgErrorExit(RTEXITCODE_SUCCESS, "No trusted certificate specified.");
628
629 /*
630 * Do the job.
631 */
632 /** @todo The root-cert part needs to be made more flexible. */
633 if ( pszRootCert
634 && !addCertToStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, "Root", pszRootCert, CERT_STORE_ADD_NEW))
635 return RTEXITCODE_FAILURE;
636
637 if (!addCertToStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, "TrustedPublisher", pszTrustedCert, CERT_STORE_ADD_NEW))
638 return RTEXITCODE_FAILURE;
639
640 if (g_cVerbosityLevel > 0)
641 {
642 if (pszRootCert)
643 RTMsgInfo("Successfully added '%s' as root and '%s' as trusted publisher", pszRootCert, pszTrustedCert);
644 else
645 RTMsgInfo("Successfully added '%s' as trusted publisher", pszTrustedCert);
646 }
647 return RTEXITCODE_SUCCESS;
648}
649
650
651/**
652 * Displays the usage info.
653 * @param argv0 Program name.
654 */
655static void showUsage(const char *argv0)
656{
657 RTPrintf("Usage: %Rbn [-v[v]] <command>\n"
658 " or %Rbn <-V|--version>\n"
659 " or %Rbn <-h|--help>\n"
660 "\n"
661 "Available commands:\n"
662 " add-trusted-publisher, remove-trusted-publisher,\n"
663 " display-all\n"
664 , argv0, argv0, argv0);
665}
666
667
668int main(int argc, char **argv)
669{
670 int rc = RTR3InitExe(argc, &argv, 0);
671 if (RT_FAILURE(rc))
672 return RTMsgInitFailure(rc);
673
674 /*
675 * Parse arguments up to the command and pass it on to the command handlers.
676 */
677 typedef enum
678 {
679 VCUACTION_ADD_TRUSTED_PUBLISHER = 1000,
680 VCUACTION_REMOVE_TRUSTED_PUBLISHER,
681 VCUACTION_DISPLAY_ALL,
682 VCUACTION_END
683 } VCUACTION;
684
685 static const RTGETOPTDEF s_aOptions[] =
686 {
687 { "--verbose", 'v', RTGETOPT_REQ_NOTHING },
688 { "--quiet", 'q', RTGETOPT_REQ_NOTHING },
689 { "add-trusted-publisher", VCUACTION_ADD_TRUSTED_PUBLISHER, RTGETOPT_REQ_NOTHING },
690 { "remove-trusted-publisher", VCUACTION_REMOVE_TRUSTED_PUBLISHER, RTGETOPT_REQ_NOTHING },
691 { "display-all", VCUACTION_DISPLAY_ALL, RTGETOPT_REQ_NOTHING },
692 };
693
694 RTGETOPTUNION ValueUnion;
695 RTGETOPTSTATE GetState;
696 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
697 while ((rc = RTGetOpt(&GetState, &ValueUnion)))
698 {
699 switch (rc)
700 {
701 case 'v':
702 g_cVerbosityLevel++;
703 break;
704
705 case 'q':
706 if (g_cVerbosityLevel > 0)
707 g_cVerbosityLevel--;
708 break;
709
710 case 'h':
711 showUsage(argv[0]);
712 return RTEXITCODE_SUCCESS;
713
714 case 'V':
715 RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
716 return RTEXITCODE_SUCCESS;
717
718 case VCUACTION_ADD_TRUSTED_PUBLISHER:
719 return cmdAddTrustedPublisher(argc - GetState.iNext + 1, argv + GetState.iNext - 1);
720
721 case VCUACTION_REMOVE_TRUSTED_PUBLISHER:
722 return cmdRemoveTrustedPublisher(argc - GetState.iNext + 1, argv + GetState.iNext - 1);
723
724 case VCUACTION_DISPLAY_ALL:
725 return cmdDisplayAll(argc - GetState.iNext + 1, argv + GetState.iNext - 1);
726
727 default:
728 return RTGetOptPrintError(rc, &ValueUnion);
729 }
730 }
731
732 RTMsgError("Missing command...");
733 showUsage(argv[0]);
734 return RTEXITCODE_SYNTAX;
735}
736
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