Changeset 39746 in vbox for trunk/src/VBox/Additions/WINNT/tools/VBoxCertUtil.cpp
- Timestamp:
- Jan 11, 2012 1:57:34 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/tools/VBoxCertUtil.cpp
r39733 r39746 7 7 #include <Wincrypt.h> 8 8 9 #include <iprt/buildconfig.h> 9 10 #include <iprt/err.h> 10 11 #include <iprt/file.h> 12 #include <iprt/getopt.h> 11 13 #include <iprt/initterm.h> 12 14 #include <iprt/message.h> 13 15 #include <iprt/stream.h> 14 16 #include <iprt/string.h> 17 #include <iprt/time.h> 18 19 20 /******************************************************************************* 21 * Global Variables * 22 *******************************************************************************/ 23 /** The verbosity level. */ 24 static unsigned g_cVerbosityLevel = 1; 25 15 26 16 27 static const char *errorToString(DWORD dwErr) … … 73 84 default: 74 85 { 86 PCRTCOMERRMSG pWinComMsg = RTErrCOMGet(dwErr); 87 if (pWinComMsg) 88 return pWinComMsg->pszDefine; 89 75 90 static char s_szErr[32]; 76 RTStrPrintf(s_szErr, sizeof(s_szErr), " #x (%d)", dwErr, dwErr);91 RTStrPrintf(s_szErr, sizeof(s_szErr), "%#x (%d)", dwErr, dwErr); 77 92 return s_szErr; 78 93 } … … 80 95 } 81 96 97 #if 0 /* hacking */ 82 98 static RTEXITCODE addToStore(const char *pszFilename, PCRTUTF16 pwszStore) 83 99 { … … 137 153 } 138 154 else 139 RTMsgError("CertOpenStore Wreturned %s", errorToString(GetLastError()));155 RTMsgError("CertOpenStore returned %s", errorToString(GetLastError())); 140 156 CertFreeCertificateContext(pCertCtx); 141 157 } … … 154 170 #endif 155 171 } 172 #endif /* hacking */ 173 174 175 /** 176 * Reads a certificate from a file, returning a context or a the handle to a 177 * temporary memory store. 178 * 179 * @returns true on success, false on failure (error message written). 180 * @param pszCertFile The name of the file containing the 181 * certificates. 182 * @param ppOutCtx Where to return the certificate context. 183 * @param phSrcStore Where to return the handle to the temporary 184 * memory store. 185 */ 186 static bool readCertFile(const char *pszCertFile, PCCERT_CONTEXT *ppOutCtx, HCERTSTORE *phSrcStore) 187 { 188 *ppOutCtx = NULL; 189 *phSrcStore = NULL; 190 191 bool fRc = false; 192 void *pvFile; 193 size_t cbFile; 194 int rc = RTFileReadAll(pszCertFile, &pvFile, &cbFile); 195 if (RT_SUCCESS(rc)) 196 { 197 *ppOutCtx = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 198 (PBYTE)pvFile, (DWORD)cbFile); 199 if (*ppOutCtx) 200 rc = true; 201 else 202 { 203 /** @todo figure out if it's some other format... */ 204 RTMsgError("CertCreateCertificateContext returned %s parsing the content of '%s'", 205 errorToString(GetLastError()), pszCertFile); 206 } 207 } 208 else 209 RTMsgError("RTFileReadAll failed on '%s': %Rrc", pszCertFile, rc); 210 RTFileReadAllFree(pvFile, cbFile); 211 return fRc; 212 } 213 214 215 /** 216 * Opens a certificate store. 217 * 218 * @returns true on success, false on failure (error message written). 219 * @param dwDst The destination, like 220 * CERT_SYSTEM_STORE_LOCAL_MACHINE or 221 * ERT_SYSTEM_STORE_CURRENT_USER. 222 * @param pszStoreNm The store name. 223 */ 224 static HCERTSTORE openCertStore(DWORD dwDst, const char *pszStoreNm) 225 { 226 HCERTSTORE hStore = NULL; 227 PRTUTF16 pwszStoreNm; 228 int rc = RTStrToUtf16(pszStoreNm, &pwszStoreNm); 229 if (RT_SUCCESS(rc)) 230 { 231 if (g_cVerbosityLevel > 1) 232 RTMsgInfo("Opening store %#x:'%s'", dwDst, pszStoreNm); 233 234 hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 235 PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 236 NULL /* hCryptProv = default */, 237 dwDst | CERT_STORE_OPEN_EXISTING_FLAG, 238 pwszStoreNm); 239 if (hStore == NULL) 240 RTMsgError("CertOpenStore failed opening %#x:'%s': %s", 241 dwDst, pszStoreNm, errorToString(GetLastError())); 242 243 RTUtf16Free(pwszStoreNm); 244 } 245 return hStore; 246 } 247 248 249 /** 250 * Adds a certificate to a store. 251 * 252 * @returns true on success, false on failure (error message written). 253 * @param dwDst The destination, like 254 * CERT_SYSTEM_STORE_LOCAL_MACHINE or 255 * ERT_SYSTEM_STORE_CURRENT_USER. 256 * @param pszStoreNm The store name. 257 * @param pszCertFile The file containing the certificate to add. 258 * @param dwDisposition The disposition towards existing certificates when 259 * adding it. CERT_STORE_ADD_NEW is a safe one. 260 */ 261 static bool addCertToStore(DWORD dwDst, const char *pszStoreNm, const char *pszCertFile, DWORD dwDisposition) 262 { 263 /* 264 * Read the certificate file first. 265 */ 266 PCCERT_CONTEXT pSrcCtx = NULL; 267 HCERTSTORE hSrcStore = NULL; 268 if (!readCertFile(pszCertFile, &pSrcCtx, &hSrcStore)) 269 return false; 270 271 /* 272 * Open the destination store. 273 */ 274 bool fRc = false; 275 HCERTSTORE hDstStore = openCertStore(dwDst, pszStoreNm); 276 if (hDstStore) 277 { 278 if (pSrcCtx) 279 { 280 if (g_cVerbosityLevel > 1) 281 RTMsgInfo("Adding '%s' to %#x:'%s'... (disp %d)", pszCertFile, dwDst, pszStoreNm, dwDisposition); 282 283 if (CertAddCertificateContextToStore(hDstStore, pSrcCtx, dwDisposition, NULL)) 284 fRc = true; 285 else 286 RTMsgError("CertAddCertificateContextToStore returned %s", errorToString(GetLastError())); 287 } 288 else 289 { 290 RTMsgError("Path not implemented at line %d\n", __LINE__); 291 } 292 293 CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG); 294 } 295 if (pSrcCtx) 296 CertFreeCertificateContext(pSrcCtx); 297 if (hSrcStore) 298 CertCloseStore(hSrcStore, CERT_CLOSE_STORE_CHECK_FLAG); 299 return fRc; 300 } 301 302 /** 303 * Worker for cmdDisplayAll. 304 */ 305 static BOOL WINAPI displaySystemStoreCallback(const void *pvSystemStore, DWORD dwFlags, PCERT_SYSTEM_STORE_INFO pStoreInfo, 306 void *pvReserved, void *pvArg) 307 { 308 if (g_cVerbosityLevel > 1) 309 RTPrintf(" pvSystemStore=%p dwFlags=%#x pStoreInfo=%p pvReserved=%p\n", pvSystemStore, dwFlags, pStoreInfo, pvReserved); 310 LPCWSTR pwszStoreNm = NULL; 311 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG) 312 { 313 const CERT_SYSTEM_STORE_RELOCATE_PARA *pRelPara = (const CERT_SYSTEM_STORE_RELOCATE_PARA *)pvSystemStore; 314 pwszStoreNm = pRelPara->pwszSystemStore; 315 RTPrintf(" %#010x '%ls' hKeyBase=%p\n", dwFlags, pwszStoreNm, pRelPara->hKeyBase); 316 } 317 else 318 { 319 pwszStoreNm = (LPCWSTR)pvSystemStore; 320 RTPrintf(" %#010x '%ls'\n", dwFlags, pwszStoreNm); 321 } 322 323 /* 324 * Open the store and list the certificates within. 325 */ 326 DWORD dwDst = (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK); 327 HCERTSTORE hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 328 PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 329 NULL /* hCryptProv = default */, 330 dwDst | CERT_STORE_OPEN_EXISTING_FLAG, 331 pwszStoreNm); 332 if (hStore) 333 { 334 PCCERT_CONTEXT pCertCtx = NULL; 335 while ((pCertCtx = CertEnumCertificatesInStore(hStore, pCertCtx)) != NULL) 336 { 337 if (g_cVerbosityLevel > 1) 338 RTPrintf(" pCertCtx=%p dwCertEncodingType=%#x cbCertEncoded=%#x pCertInfo=%p\n", 339 pCertCtx, pCertCtx->dwCertEncodingType, pCertCtx->cbCertEncoded, pCertCtx->pCertInfo); 340 WCHAR wszName[1024]; 341 if (CertGetNameStringW(pCertCtx, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0 /*dwFlags*/, NULL /*pvTypePara*/, 342 wszName, sizeof(wszName))) 343 { 344 RTPrintf(" '%ls'\n", wszName); 345 if (pCertCtx->pCertInfo) 346 { 347 RTTIMESPEC TmpTS; 348 char szNotBefore[80]; 349 RTTimeSpecToString(RTTimeSpecSetNtFileTime(&TmpTS, &pCertCtx->pCertInfo->NotBefore), 350 szNotBefore, sizeof(szNotBefore)); 351 char szNotAfter[80]; 352 RTTimeSpecToString(RTTimeSpecSetNtFileTime(&TmpTS, &pCertCtx->pCertInfo->NotAfter), 353 szNotAfter, sizeof(szNotAfter)); 354 355 RTPrintf(" NotBefore='%s'\n", szNotBefore); 356 RTPrintf(" NotAfter ='%s'\n", szNotAfter); 357 if (pCertCtx->pCertInfo->Issuer.cbData) 358 { 359 if (CertGetNameStringW(pCertCtx, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL /*pvTypePara*/, 360 wszName, sizeof(wszName))) 361 RTPrintf(" Issuer='%ls'\n", wszName); 362 else 363 RTMsgError("CertGetNameStringW(Issuer) failed: %s\n", errorToString(GetLastError())); 364 } 365 } 366 } 367 else 368 RTMsgError("CertGetNameStringW(Subject) failed: %s\n", errorToString(GetLastError())); 369 370 } 371 372 CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG); 373 } 374 else 375 RTMsgError("CertOpenStore failed opening %#x:'%ls': %s\n", dwDst, pwszStoreNm, errorToString(GetLastError())); 376 377 return TRUE; 378 } 379 380 /** 381 * Worker for cmdDisplayAll. 382 */ 383 static BOOL WINAPI displaySystemStoreLocation(LPCWSTR pwszStoreLocation, DWORD dwFlags, void *pvReserved, void *pvArg) 384 { 385 NOREF(pvReserved); NOREF(pvArg); 386 RTPrintf("System store location: %#010x '%ls'\n", dwFlags, pwszStoreLocation); 387 if (!CertEnumSystemStore(dwFlags, NULL, NULL /*pvArg*/, displaySystemStoreCallback)) 388 RTMsgError("CertEnumSystemStore failed on %#x:'%ls': %s\n", 389 dwFlags, pwszStoreLocation, errorToString(GetLastError())); 390 391 return TRUE; 392 } 393 394 /** 395 * Handler for the 'display-all' command. 396 */ 397 static RTEXITCODE cmdDisplayAll(int argc, char **argv) 398 { 399 if (argc != 1) 400 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "the display-all command takes no arguments\n"); 401 402 if (!CertEnumSystemStoreLocation(0, NULL /*pvArg*/, displaySystemStoreLocation)) 403 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "CertEnumSystemStoreLocation failed: %s\n", errorToString(GetLastError())); 404 405 return RTEXITCODE_SUCCESS; 406 } 407 408 /** 409 * Handler for the 'add-trusted-publisher' command. 410 */ 411 static RTEXITCODE cmdAddTrustedPublisher(int argc, char **argv) 412 { 413 /* 414 * Parse arguments. 415 */ 416 static const RTGETOPTDEF s_aOptions[] = 417 { 418 { "--root", 'r', RTGETOPT_REQ_STRING }, 419 }; 420 421 const char *pszRootCert = NULL; 422 const char *pszTrustedCert = NULL; 423 424 int rc; 425 RTGETOPTUNION ValueUnion; 426 RTGETOPTSTATE GetState; 427 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0); 428 while ((rc = RTGetOpt(&GetState, &ValueUnion))) 429 { 430 switch (rc) 431 { 432 case 'h': 433 RTPrintf("Usage: VBoxCertUtil add-trusted-publisher [--root <root-cert>] <trusted-cert>\n"); 434 break; 435 436 case 'V': 437 RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision()); 438 return RTEXITCODE_SUCCESS; 439 440 case 'r': 441 if (pszRootCert) 442 return RTMsgErrorExit(RTEXITCODE_SUCCESS, 443 "You've already specified '%s' as root certificate.", 444 pszRootCert); 445 pszRootCert = ValueUnion.psz; 446 break; 447 448 case VINF_GETOPT_NOT_OPTION: 449 if (pszTrustedCert) 450 return RTMsgErrorExit(RTEXITCODE_SUCCESS, 451 "You've already specified '%s' as trusted certificate.", 452 pszRootCert); 453 pszTrustedCert = ValueUnion.psz; 454 break; 455 456 default: 457 return RTGetOptPrintError(rc, &ValueUnion); 458 } 459 } 460 if (!pszTrustedCert) 461 return RTMsgErrorExit(RTEXITCODE_SUCCESS, "No trusted certificate specified."); 462 463 /* 464 * Do the job. 465 */ 466 if ( pszRootCert 467 && !addCertToStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, "Root", pszRootCert, CERT_STORE_ADD_NEW)) 468 return RTEXITCODE_FAILURE; 469 if (!addCertToStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, "TrustedPublisher", pszTrustedCert, CERT_STORE_ADD_NEW)) 470 return RTEXITCODE_FAILURE; 471 472 if (g_cVerbosityLevel > 0) 473 { 474 if (pszRootCert) 475 RTMsgInfo("Successfully added '%s' as root and '%s' as trusted publisher", pszRootCert, pszTrustedCert); 476 else 477 RTMsgInfo("Successfully added '%s' as trusted publisher", pszTrustedCert); 478 } 479 return RTEXITCODE_SUCCESS; 480 } 156 481 157 482 … … 162 487 return RTMsgInitFailure(rc); 163 488 164 165 RTEXITCODE rcExit; 166 167 rcExit = addToStore("my", L"my"); 168 169 return rcExit; 170 } 489 /* 490 * Parse arguments up to the command and pass it on to the command handlers. 491 */ 492 typedef enum 493 { 494 VCUACTION_ADD_TRUSTED_PUBLISHER = 1000, 495 VCUACTION_DISPLAY_ALL, 496 VCUACTION_END 497 } VCUACTION; 498 499 static const RTGETOPTDEF s_aOptions[] = 500 { 501 { "--verbose", 'v', RTGETOPT_REQ_NOTHING }, 502 { "--quiet", 'q', RTGETOPT_REQ_NOTHING }, 503 { "add-trusted-publisher", VCUACTION_ADD_TRUSTED_PUBLISHER, RTGETOPT_REQ_NOTHING }, 504 { "display-all", VCUACTION_DISPLAY_ALL, RTGETOPT_REQ_NOTHING }, 505 }; 506 507 RTGETOPTUNION ValueUnion; 508 RTGETOPTSTATE GetState; 509 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0); 510 while ((rc = RTGetOpt(&GetState, &ValueUnion))) 511 { 512 switch (rc) 513 { 514 case 'v': 515 g_cVerbosityLevel++; 516 break; 517 518 case 'q': 519 if (g_cVerbosityLevel > 0) 520 g_cVerbosityLevel--; 521 break; 522 523 case 'h': 524 RTPrintf("Usage: TODO\n"); 525 break; 526 527 case 'V': 528 RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision()); 529 return RTEXITCODE_SUCCESS; 530 531 case VCUACTION_ADD_TRUSTED_PUBLISHER: 532 return cmdAddTrustedPublisher(argc - GetState.iNext + 1, argv + GetState.iNext - 1); 533 534 case VCUACTION_DISPLAY_ALL: 535 return cmdDisplayAll(argc - GetState.iNext + 1, argv + GetState.iNext - 1); 536 537 default: 538 return RTGetOptPrintError(rc, &ValueUnion); 539 } 540 } 541 542 RTMsgError("Missing command...\n"); 543 return RTEXITCODE_SYNTAX; 544 } 545
Note:
See TracChangeset
for help on using the changeset viewer.