static int rtCrStoreAddCertsFromNative(RTCRSTORE hStore, DWORD fStore, PCRTUTF16 pwszStoreName, PFNCERTOPENSTORE pfnOpenStore, PFNCERTCLOSESTORE pfnCloseStore, PFNCERTENUMCERTIFICATESINSTORE pfnEnumCerts, int rc, PRTERRINFO pErrInfo) { DWORD fOpenStore = CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG; HCERTSTORE hNativeStore = pfnOpenStore(CERT_STORE_PROV_SYSTEM_W, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, NULL /* hCryptProv = default */, fStore | fOpenStore, pwszStoreName); if (hStore) { PCCERT_CONTEXT pCurCtx = NULL; while ((pCurCtx = pfnEnumCerts(hNativeStore, pCurCtx)) != NULL) { if (pCurCtx->dwCertEncodingType & X509_ASN_ENCODING) { RTERRINFOSTATIC StaticErrInfo; RTASN1CURSORPRIMARY PrimaryCursor; RTAsn1CursorInitPrimary(&PrimaryCursor, pCurCtx->pbCertEncoded, pCurCtx->cbCertEncoded, RTErrInfoInitStatic(&StaticErrInfo), &g_RTAsn1DefaultAllocator, RTASN1CURSOR_FLAGS_DER, "CurCtx"); RTCRX509CERTIFICATE MyCert; int rc2 = RTCrX509Certificate_DecodeAsn1(&PrimaryCursor.Cursor, 0, &MyCert, "Cert"); if (RT_SUCCESS(rc2)) { rc2 = RTCrStoreCertAddEncoded(hStore, RTCRCERTCTX_F_ENC_X509_DER | RTCRCERTCTX_F_ADD_IF_NOT_FOUND, pCurCtx->pbCertEncoded, pCurCtx->cbCertEncoded, RTErrInfoInitStatic(&StaticErrInfo)); RTCrX509Certificate_Delete(&MyCert); } if (RT_FAILURE(rc2)) { if (RTErrInfoIsSet(&StaticErrInfo.Core)) RTErrInfoAddF(pErrInfo, -rc2, " %s", StaticErrInfo.Core.pszMsg); else RTErrInfoAddF(pErrInfo, -rc2, " %Rrc adding cert", rc2); rc = -rc2; } } } pfnCloseStore(hNativeStore, CERT_CLOSE_STORE_CHECK_FLAG); } else { DWORD uLastErr = GetLastError(); if (uLastErr != ERROR_FILE_NOT_FOUND) rc = RTErrInfoAddF(pErrInfo, -RTErrConvertFromWin32(uLastErr), " CertOpenStore(%#x,'%ls') failed: %u", fStore, pwszStoreName); } return rc; }
/** * Recursively changes the file mode. * * @returns exit code * @param pOpts The mkdir option. * @param pszPath The path to start changing the mode of. */ static int rtCmdChModRecursive(RTCMDCHMODOPTS const *pOpts, const char *pszPath) { /* * Check if it's a directory first. If not, join the non-recursive code. */ int rc; uint32_t offError; RTFSOBJINFO ObjInfo; RTERRINFOSTATIC ErrInfo; bool const fUseChainApi = pOpts->fAlwaysUseChainApi || RTVfsChainIsSpec(pszPath); if (!fUseChainApi) { rc = RTPathQueryInfoEx(pszPath, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_FOLLOW_LINK); if (RT_FAILURE(rc)) return RTMsgErrorExitFailure("RTPathQueryInfoEx failed on '%s': %Rrc", pszPath, rc); } else { rc = RTVfsChainQueryInfo(pszPath, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_FOLLOW_LINK, &offError, RTErrInfoInitStatic(&ErrInfo)); if (RT_FAILURE(rc)) return RTVfsChainMsgErrorExitFailure("RTVfsChainQueryInfo", pszPath, rc, offError, &ErrInfo.Core); } if (!RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode)) { /* * Don't bother redoing the above work if its not necessary. */ RTFMODE fNewMode = rtCmdMkModCalcNewMode(pOpts, ObjInfo.Attr.fMode); if (fNewMode != ObjInfo.Attr.fMode) return rtCmdChModOne(pOpts, pszPath); if (pOpts->enmNoiseLevel >= kRTCmdChModNoise_Verbose) RTPrintf("%s\n", pszPath); return RTEXITCODE_SUCCESS; } /* * For recursion we always use the VFS layer. */ RTVFSDIR hVfsDir; if (!fUseChainApi) { rc = RTVfsDirOpenNormal(pszPath, 0 /** @todo write attrib flag*/, &hVfsDir); if (RT_FAILURE(rc)) return RTMsgErrorExitFailure("RTVfsDirOpenNormal failed on '%s': %Rrc", pszPath, rc); } else { rc = RTVfsChainOpenDir(pszPath, 0 /** @todo write attrib flag*/, &hVfsDir, &offError, RTErrInfoInitStatic(&ErrInfo)); if (RT_FAILURE(rc)) return RTVfsChainMsgErrorExitFailure("RTVfsChainQueryInfo", pszPath, rc, offError, &ErrInfo.Core); } RTMsgError("Recursion is not yet implemented\n"); RTVfsDirRelease(hVfsDir); rc = VERR_NOT_IMPLEMENTED; return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; }
/** * Loads the modules. * * @returns RTEXITCODE_SUCCESS on success. */ static RTEXITCODE LoadModules(void) { for (uint32_t i = 0; i < RT_ELEMENTS(g_aModules); i++) { if (g_aModules[i].fPreload) { char szPath[RTPATH_MAX]; int rc = RTPathAppPrivateArch(szPath, sizeof(szPath)); if (RT_SUCCESS(rc)) rc = RTPathAppend(szPath, sizeof(szPath), g_aModules[i].pszName); if (RT_FAILURE(rc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTPathAppPrivateArch or RTPathAppend returned %Rrc", rc); void *pvImageBase; RTERRINFOSTATIC ErrInfo; RTErrInfoInitStatic(&ErrInfo); rc = SUPR3LoadModule(szPath, g_aModules[i].pszName, &g_aModules[i].pvImageBase, &ErrInfo.Core); if (RT_FAILURE(rc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "SUPR3LoadModule failed for %s (%s): %s (rc=%Rrc)", g_aModules[i].pszName, szPath, ErrInfo.Core.pszMsg, rc); if (g_cVerbose >= 1) RTMsgInfo("Loaded '%s' ('%s') at %p\n", szPath, g_aModules[i].pszName, g_aModules[i].pvImageBase); } } RTStrmFlush(g_pStdOut); return RTEXITCODE_SUCCESS; }
/** * Changes the file mode of one file system object. * * @returns exit code * @param pOpts The chmod options. * @param pszPath The path to the file system object to change the * file mode of. */ static RTEXITCODE rtCmdChModOne(RTCMDCHMODOPTS const *pOpts, const char *pszPath) { int rc; RTFSOBJINFO ObjInfo; bool fChanges = false; if (!pOpts->fAlwaysUseChainApi && !RTVfsChainIsSpec(pszPath) ) { rc = RTPathQueryInfoEx(pszPath, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_FOLLOW_LINK); if (RT_SUCCESS(rc)) { RTFMODE fNewMode = rtCmdMkModCalcNewMode(pOpts, ObjInfo.Attr.fMode); fChanges = fNewMode != ObjInfo.Attr.fMode; if (fChanges) { rc = RTPathSetMode(pszPath, fNewMode); if (RT_FAILURE(rc)) RTMsgError("RTPathSetMode failed on '%s' with fNewMode=%#x: %Rrc", pszPath, fNewMode, rc); } } else RTMsgError("RTPathQueryInfoEx failed on '%s': %Rrc", pszPath, rc); } else { RTVFSOBJ hVfsObj; uint32_t offError; RTERRINFOSTATIC ErrInfo; rc = RTVfsChainOpenObj(pszPath, RTFILE_O_ACCESS_ATTR_READWRITE | RTFILE_O_DENY_NONE | RTFILE_O_OPEN, RTVFSOBJ_F_OPEN_ANY | RTVFSOBJ_F_CREATE_NOTHING | RTPATH_F_FOLLOW_LINK, &hVfsObj, &offError, RTErrInfoInitStatic(&ErrInfo)); if (RT_SUCCESS(rc)) { rc = RTVfsObjQueryInfo(hVfsObj, &ObjInfo, RTFSOBJATTRADD_NOTHING); if (RT_SUCCESS(rc)) { RTFMODE fNewMode = rtCmdMkModCalcNewMode(pOpts, ObjInfo.Attr.fMode); fChanges = fNewMode != ObjInfo.Attr.fMode; if (fChanges) { rc = RTVfsObjSetMode(hVfsObj, fNewMode, RTCHMOD_SET_ALL_MASK); if (RT_FAILURE(rc)) RTMsgError("RTVfsObjSetMode failed on '%s' with fNewMode=%#x: %Rrc", pszPath, fNewMode, rc); } } else RTVfsChainMsgError("RTVfsObjQueryInfo", pszPath, rc, offError, &ErrInfo.Core); RTVfsObjRelease(hVfsObj); } else RTVfsChainMsgError("RTVfsChainOpenObject", pszPath, rc, offError, &ErrInfo.Core); } if (RT_SUCCESS(rc)) { if (pOpts->enmNoiseLevel >= (fChanges ? kRTCmdChModNoise_Changes : kRTCmdChModNoise_Verbose)) RTPrintf("%s\n", pszPath); return RTEXITCODE_SUCCESS; } return RTEXITCODE_FAILURE; }
/** * Opens the input file. * * @returns Command exit, error messages written using RTMsg*. * * @param pszFile The input filename. * @param pOpts The options, szOutput will be filled in by this * function on success. * @param phVfsIos Where to return the input stream handle. */ static RTEXITCODE gzipOpenInput(const char *pszFile, PRTGZIPCMDOPTS pOpts, PRTVFSIOSTREAM phVfsIos) { int rc; pOpts->pszInput = pszFile; if (!strcmp(pszFile, "-")) { if ( !pOpts->fForce && pOpts->fDecompress && gzipIsStdHandleATty(RTHANDLESTD_OUTPUT)) return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Yeah, right. I'm not reading any compressed data from the terminal without --force.\n"); rc = RTVfsIoStrmFromStdHandle(RTHANDLESTD_INPUT, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE, true /*fLeaveOpen*/, phVfsIos); if (RT_FAILURE(rc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error opening standard input: %Rrc", rc); } else { uint32_t offError = 0; RTERRINFOSTATIC ErrInfo; rc = RTVfsChainOpenIoStream(pszFile, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, phVfsIos, &offError, RTErrInfoInitStatic(&ErrInfo)); if (RT_FAILURE(rc)) return RTVfsChainMsgErrorExitFailure("RTVfsChainOpenIoStream", pszFile, rc, offError, &ErrInfo.Core); } return RTEXITCODE_SUCCESS; }
int main(int argc, char **argv) { /* * Init IPRT. */ int rc = RTR3InitExe(argc, &argv, 0); if (RT_FAILURE(rc)) return RTMsgInitFailure(rc); /* * Locate a native DTrace command binary. */ bool fIsNativeDTrace = false; char szDTraceCmd[RTPATH_MAX]; szDTraceCmd[0] = '\0'; #if defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD) || defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS) /* * 1. Try native first on platforms where it's applicable. */ static const char * const s_apszNativeDTrace[] = { "/usr/sbin/dtrace", "/sbin/dtrace", "/usr/bin/dtrace", "/bin/dtrace", "/usr/local/sbin/dtrace", "/usr/local/bin/dtrace" }; if (!RTEnvExist("VBOX_DTRACE_NO_NATIVE")) for (uint32_t i = 0; i < RT_ELEMENTS(s_apszNativeDTrace); i++) if (RTFileExists(s_apszNativeDTrace[i])) { fIsNativeDTrace = true; strcpy(szDTraceCmd, s_apszNativeDTrace[i]); # ifdef RT_OS_LINUX /** @todo Warn if the dtrace modules haven't been loaded or vboxdrv isn't * compiled against them. */ # endif break; } if (szDTraceCmd[0] == '\0') #endif { /* * 2. VBoxDTrace extension pack installed? * * Note! We cannot use the COM API here because this program is usually * run thru sudo or directly as root, even if the target * VirtualBox process is running as regular user. This is due to * the privileges required to run dtrace scripts on a host. */ rc = RTPathAppPrivateArch(szDTraceCmd, sizeof(szDTraceCmd)); if (RT_SUCCESS(rc)) rc = RTPathAppend(szDTraceCmd, sizeof(szDTraceCmd), VBOX_EXTPACK_INSTALL_DIR RTPATH_SLASH_STR VBOX_EXTPACK_VBOXDTRACE_MANGLED_NAME); if (RT_SUCCESS(rc)) rc = RTPathAppend(szDTraceCmd, sizeof(szDTraceCmd), RTBldCfgTargetDotArch()); if (RT_SUCCESS(rc)) rc = RTPathAppend(szDTraceCmd, sizeof(szDTraceCmd), "VBoxDTraceCmd"); if (RT_SUCCESS(rc)) rc = RTStrCat(szDTraceCmd, sizeof(szDTraceCmd), RTLdrGetSuff()); if (RT_FAILURE(rc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error constructing extension pack path: %Rrc", rc); if (!RTFileExists(szDTraceCmd)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "Unable to find a DTrace implementation. VBoxDTrace Extension Pack installed?"); fIsNativeDTrace = false; } /* * Construct a new command line that includes our libary. */ char szDTraceLibDir[RTPATH_MAX]; rc = RTPathAppPrivateNoArch(szDTraceLibDir, sizeof(szDTraceLibDir)); if (RT_SUCCESS(rc)) rc = RTPathAppend(szDTraceLibDir, sizeof(szDTraceLibDir), "dtrace" RTPATH_SLASH_STR "lib"); if (RT_SUCCESS(rc)) rc = RTPathAppend(szDTraceLibDir, sizeof(szDTraceLibDir), RTBldCfgTargetArch()); if (RT_FAILURE(rc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error constructing dtrace library path for VBox: %Rrc", rc); char **papszArgs = (char **)RTMemAlloc((argc + 3) * sizeof(char *)); if (!papszArgs) return RTMsgErrorExit(RTEXITCODE_FAILURE, "No memory for argument list."); int cArgs = 1; papszArgs[0] = fIsNativeDTrace ? szDTraceCmd : argv[0]; if (argc > 1) { papszArgs[cArgs++] = (char *)"-L"; papszArgs[cArgs++] = szDTraceLibDir; } for (int i = 1; i < argc; i++) papszArgs[cArgs++] = argv[i]; papszArgs[cArgs] = NULL; Assert(cArgs <= argc + 3); /* * The native DTrace we execute as a sub-process and wait for. */ RTEXITCODE rcExit; if (fIsNativeDTrace) { RTPROCESS hProc; rc = RTProcCreate(szDTraceCmd, papszArgs, RTENV_DEFAULT, 0, &hProc); if (RT_SUCCESS(rc)) { RTPROCSTATUS Status; rc = RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &Status); if (RT_SUCCESS(rc)) { if (Status.enmReason == RTPROCEXITREASON_NORMAL) rcExit = (RTEXITCODE)Status.iStatus; else rcExit = RTEXITCODE_FAILURE; } else rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Error waiting for child process: %Rrc", rc); } else rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Error executing '%s': %Rrc", szDTraceCmd, rc); } /* * While the VBoxDTrace we load and call the main function of. */ else { RTERRINFOSTATIC ErrInfo; RTLDRMOD hMod; rc = SUPR3HardenedLdrLoadPlugIn(szDTraceCmd, &hMod, RTErrInfoInitStatic(&ErrInfo)); if (RT_SUCCESS(rc)) { PFNVBOXDTRACEMAIN pfnVBoxDTraceMain; rc = RTLdrGetSymbol(hMod, "VBoxDTraceMain", (void **)&pfnVBoxDTraceMain); if (RT_SUCCESS(rc)) rcExit = (RTEXITCODE)pfnVBoxDTraceMain(cArgs, papszArgs); else rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Error locating 'VBoxDTraceMain' in '%s': %Rrc", szDTraceCmd, rc); } else rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Error loading '%s': %Rrc (%s)", szDTraceCmd, rc, ErrInfo.szMsg); } return rcExit; }
static RTEXITCODE RTCmdChMod(unsigned cArgs, char **papszArgs) { /* * Parse the command line. */ static const RTGETOPTDEF s_aOptions[] = { /* operations */ { "--recursive", 'R', RTGETOPT_REQ_NOTHING }, { "--preserve-root", 'x', RTGETOPT_REQ_NOTHING }, { "--no-preserve-root", 'X', RTGETOPT_REQ_NOTHING }, { "--changes", 'c', RTGETOPT_REQ_NOTHING }, { "--quiet", 'f', RTGETOPT_REQ_NOTHING }, { "--silent", 'f', RTGETOPT_REQ_NOTHING }, { "--verbose", 'v', RTGETOPT_REQ_NOTHING }, { "--reference", 'Z', RTGETOPT_REQ_NOTHING }, { "--always-use-vfs-chain-api", 'A', RTGETOPT_REQ_NOTHING }, }; RTGETOPTSTATE GetState; int rc = RTGetOptInit(&GetState, cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); if (RT_FAILURE(rc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTGetOpt failed: %Rrc", rc); RTCMDCHMODOPTS Opts; Opts.enmNoiseLevel = kRTCmdChModNoise_Default; Opts.fPreserveRoot = false; Opts.fRecursive = false; Opts.fAlwaysUseChainApi = false; Opts.fModeClear = 0; Opts.fModeSet = 0; RTGETOPTUNION ValueUnion; while ( (rc = RTGetOpt(&GetState, &ValueUnion)) != 0 && rc != VINF_GETOPT_NOT_OPTION) { switch (rc) { case 'R': Opts.fRecursive = true; break; case 'x': Opts.fPreserveRoot = true; break; case 'X': Opts.fPreserveRoot = false; break; case 'f': Opts.enmNoiseLevel = kRTCmdChModNoise_Quiet; break; case 'c': Opts.enmNoiseLevel = kRTCmdChModNoise_Changes; break; case 'v': Opts.enmNoiseLevel = kRTCmdChModNoise_Verbose; break; case 'Z': { RTFSOBJINFO ObjInfo; RTERRINFOSTATIC ErrInfo; uint32_t offError; rc = RTVfsChainQueryInfo(ValueUnion.psz, &ObjInfo,RTFSOBJATTRADD_NOTHING, RTPATH_F_FOLLOW_LINK, &offError, RTErrInfoInitStatic(&ErrInfo)); if (RT_FAILURE(rc)) return RTVfsChainMsgErrorExitFailure("RTVfsChainQueryInfo", ValueUnion.psz, rc, offError, &ErrInfo.Core); Opts.fModeClear = RTCHMOD_SET_ALL_MASK; Opts.fModeSet = ObjInfo.Attr.fMode & RTCHMOD_SET_ALL_MASK; break; } case 'A': Opts.fAlwaysUseChainApi = true; break; case 'h': RTPrintf("Usage: %s [options] <mode> <file> [..]\n" "\n" "Options:\n" " -f, --silent, --quiet\n" " -c, --changes\n" " -v, --verbose\n" " Noise level selection.\n" " -R, --recursive\n" " Recurse into directories.\n" " --preserve-root, --no-preserve-root\n" " Whether to allow recursion from the root (default: yes).\n" " --reference <file>\n" " Take mode mask to use from <file> instead of <mode>.\n" "\n" "The <mode> part isn't fully implemented, so only numerical octal notation\n" "works. Prefix the number(s) with 0x to use hexadecimal. There are two forms\n" "of the numerical notation: <SET> and <SET>:<CLEAR>\n" , papszArgs[0]); return RTEXITCODE_SUCCESS; case 'V': RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision()); return RTEXITCODE_SUCCESS; default: return RTGetOptPrintError(rc, &ValueUnion); } } /* * The MODE. */ if ( Opts.fModeClear == 0 && Opts.fModeSet == 0) { if (rc != VINF_GETOPT_NOT_OPTION) return RTMsgErrorExit(RTEXITCODE_SYNTAX, "No mode change specified.\n"); char *pszNext; if ( ValueUnion.psz[0] == '0' && (ValueUnion.psz[1] == 'x' || ValueUnion.psz[1] == 'X')) rc = RTStrToUInt32Ex(ValueUnion.psz, &pszNext, 16, &Opts.fModeSet); else rc = RTStrToUInt32Ex(ValueUnion.psz, &pszNext, 8, &Opts.fModeSet); if ( rc != VINF_SUCCESS && (rc != VWRN_TRAILING_CHARS || *pszNext != ':')) return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Unable to parse mode mask: %s\n", ValueUnion.psz); Opts.fModeSet &= RTCHMOD_SET_ALL_MASK; if (rc == VINF_SUCCESS) Opts.fModeClear = RTCHMOD_SET_ALL_MASK; else { pszNext++; if ( pszNext[0] == '0' && (pszNext[1] == 'x' || pszNext[1] == 'X')) rc = RTStrToUInt32Ex(pszNext, &pszNext, 16, &Opts.fModeClear); else rc = RTStrToUInt32Ex(pszNext, &pszNext, 8, &Opts.fModeClear); if (rc != VINF_SUCCESS) return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Unable to parse mode mask: %s\n", ValueUnion.psz); Opts.fModeClear &= RTCHMOD_SET_ALL_MASK; } rc = RTGetOpt(&GetState, &ValueUnion); } /* * No files means error. */ if (rc != VINF_GETOPT_NOT_OPTION) return RTMsgErrorExit(RTEXITCODE_FAILURE, "No directories specified.\n"); /* * Work thru the specified dirs. */ RTEXITCODE rcExit = RTEXITCODE_SUCCESS; while (rc == VINF_GETOPT_NOT_OPTION) { if (Opts.fRecursive) rc = rtCmdChModRecursive(&Opts, ValueUnion.psz); else rc = rtCmdChModOne(&Opts, ValueUnion.psz); if (RT_FAILURE(rc)) rcExit = RTEXITCODE_FAILURE; /* next */ rc = RTGetOpt(&GetState, &ValueUnion); } if (rc != 0) rcExit = RTGetOptPrintError(rc, &ValueUnion); return rcExit; }
int main(int argc, char **argv) { /* * Init. */ int rc = RTR3InitExe(argc, &argv, RTR3INIT_FLAGS_SUPLIB); if (RT_FAILURE(rc)) return RTMsgInitFailure(rc); /* * Process arguments. */ static const RTGETOPTDEF s_aOptions[] = { { "--keep", 'k', RTGETOPT_REQ_NOTHING }, { "--no-keep", 'n', RTGETOPT_REQ_NOTHING }, }; bool fKeepLoaded = false; int ch; RTGETOPTUNION ValueUnion; RTGETOPTSTATE GetState; RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0); while ((ch = RTGetOpt(&GetState, &ValueUnion))) { switch (ch) { case VINF_GETOPT_NOT_OPTION: { void *pvImageBase; RTERRINFOSTATIC ErrInfo; RTErrInfoInitStatic(&ErrInfo); rc = SUPR3LoadModule(ValueUnion.psz, RTPathFilename(ValueUnion.psz), &pvImageBase, &ErrInfo.Core); if (RT_FAILURE(rc)) { RTMsgError("%Rrc when attempting to load '%s': %s\n", rc, ValueUnion.psz, ErrInfo.Core.pszMsg); return 1; } RTPrintf("Loaded '%s' at %p\n", ValueUnion.psz, pvImageBase); if (!fKeepLoaded) { rc = SUPR3FreeModule(pvImageBase); if (RT_FAILURE(rc)) { RTMsgError("%Rrc when attempting to load '%s'\n", rc, ValueUnion.psz); return 1; } } break; } case 'k': fKeepLoaded = true; break; case 'n': fKeepLoaded = false; break; case 'h': RTPrintf("%s [mod1 [mod2...]]\n", argv[0]); return 1; case 'V': RTPrintf("$Revision$\n"); return 0; default: return RTGetOptPrintError(ch, &ValueUnion); } } return 0; }
/** * Create one directory and any missing parent directories. * * @returns exit code * @param pOpts The mkdir option. * @param pszDir The path to the new directory. */ static int rtCmdRmDirOneWithParents(RTCMDRMDIROPTS const *pOpts, const char *pszDir) { /* We need a copy we can work with here. */ char *pszCopy = RTStrDup(pszDir); if (!pszCopy) return RTMsgErrorExitFailure("Out of string memory!"); int rc; if (!pOpts->fAlwaysUseChainApi && !RTVfsChainIsSpec(pszDir) ) { size_t cchCopy = strlen(pszCopy); do { rc = RTDirRemove(pszCopy); if (RT_SUCCESS(rc)) { if (pOpts->fVerbose) RTPrintf("%s\n", pszCopy); } else if ((rc == VERR_PATH_NOT_FOUND || rc == VERR_FILE_NOT_FOUND) && pOpts->fIgnoreNonExisting) rc = VINF_SUCCESS; else { if ((rc == VERR_DIR_NOT_EMPTY || rc == VERR_SHARING_VIOLATION) && pOpts->fIgnoreNotEmpty) rc = VINF_SUCCESS; else RTMsgError("Failed to remove directory '%s': %Rrc", pszCopy, rc); break; } /* Strip off a component. */ while (cchCopy > 0 && RTPATH_IS_SLASH(pszCopy[cchCopy - 1])) cchCopy--; while (cchCopy > 0 && !RTPATH_IS_SLASH(pszCopy[cchCopy - 1])) cchCopy--; while (cchCopy > 0 && RTPATH_IS_SLASH(pszCopy[cchCopy - 1])) cchCopy--; pszCopy[cchCopy] = '\0'; } while (cchCopy > 0); } else { /* * Strip the final path element from the pszDir spec. */ char *pszFinalPath; char *pszSpec; uint32_t offError; rc = RTVfsChainSplitOffFinalPath(pszCopy, &pszSpec, &pszFinalPath, &offError); if (RT_SUCCESS(rc)) { /* * Open the root director/whatever. */ RTERRINFOSTATIC ErrInfo; RTVFSDIR hVfsBaseDir; if (pszSpec) { rc = RTVfsChainOpenDir(pszSpec, 0 /*fOpen*/, &hVfsBaseDir, &offError, RTErrInfoInitStatic(&ErrInfo)); if (RT_FAILURE(rc)) RTVfsChainMsgError("RTVfsChainOpenDir", pszSpec, rc, offError, &ErrInfo.Core); else if (!pszFinalPath) pszFinalPath = RTStrEnd(pszSpec, RTSTR_MAX); } else if (!RTPathStartsWithRoot(pszFinalPath)) { rc = RTVfsDirOpenNormal(".", 0 /*fOpen*/, &hVfsBaseDir); if (RT_FAILURE(rc)) RTMsgError("Failed to open '.' (for %s): %Rrc", rc, pszFinalPath); } else { char *pszRoot = pszFinalPath; pszFinalPath = RTPathSkipRootSpec(pszFinalPath); char const chSaved = *pszFinalPath; *pszFinalPath = '\0'; rc = RTVfsDirOpenNormal(pszRoot, 0 /*fOpen*/, &hVfsBaseDir); *pszFinalPath = chSaved; if (RT_FAILURE(rc)) RTMsgError("Failed to open root dir for '%s': %Rrc", rc, pszRoot); } /* * Walk the path component by component, starting at the end. */ if (RT_SUCCESS(rc)) { size_t cchFinalPath = strlen(pszFinalPath); while (RT_SUCCESS(rc) && cchFinalPath > 0) { rc = RTVfsDirRemoveDir(hVfsBaseDir, pszFinalPath, 0 /*fFlags*/); if (RT_SUCCESS(rc)) { if (pOpts->fVerbose) RTPrintf("%s\n", pszCopy); } else if ((rc == VERR_PATH_NOT_FOUND || rc == VERR_FILE_NOT_FOUND) && pOpts->fIgnoreNonExisting) rc = VINF_SUCCESS; else { if ((rc == VERR_DIR_NOT_EMPTY || rc == VERR_SHARING_VIOLATION) && pOpts->fIgnoreNotEmpty) rc = VINF_SUCCESS; else if (pszSpec) RTMsgError("Failed to remove directory '%s:%s': %Rrc", pszSpec, pszFinalPath, rc); else RTMsgError("Failed to remove directory '%s': %Rrc", pszFinalPath, rc); break; } /* Strip off a component. */ while (cchFinalPath > 0 && RTPATH_IS_SLASH(pszFinalPath[cchFinalPath - 1])) cchFinalPath--; while (cchFinalPath > 0 && !RTPATH_IS_SLASH(pszFinalPath[cchFinalPath - 1])) cchFinalPath--; while (cchFinalPath > 0 && RTPATH_IS_SLASH(pszFinalPath[cchFinalPath - 1])) cchFinalPath--; pszFinalPath[cchFinalPath] = '\0'; } RTVfsDirRelease(hVfsBaseDir); } } else RTVfsChainMsgError("RTVfsChainOpenParentDir", pszCopy, rc, offError, NULL); } RTStrFree(pszCopy); return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; }
/** * Removes one directory. * * @returns exit code * @param pOpts The mkdir option. * @param pszDir The path to the new directory. */ static RTEXITCODE rtCmdRmDirOne(RTCMDRMDIROPTS const *pOpts, const char *pszDir) { int rc; if (!pOpts->fAlwaysUseChainApi && !RTVfsChainIsSpec(pszDir) ) rc = RTDirRemove(pszDir); else { RTVFSDIR hVfsDir; const char *pszChild; uint32_t offError; RTERRINFOSTATIC ErrInfo; rc = RTVfsChainOpenParentDir(pszDir, 0 /*fOpen*/, &hVfsDir, &pszChild, &offError, RTErrInfoInitStatic(&ErrInfo)); if (RT_SUCCESS(rc)) { rc = RTVfsDirRemoveDir(hVfsDir, pszChild, 0 /*fFlags*/); RTVfsDirRelease(hVfsDir); } else return RTVfsChainMsgErrorExitFailure("RTVfsChainOpenParentDir", pszDir, rc, offError, &ErrInfo.Core); } if (RT_SUCCESS(rc)) { if (pOpts->fVerbose) RTPrintf("%s\n", pszDir); return RTEXITCODE_SUCCESS; } if ((rc == VERR_DIR_NOT_EMPTY || rc == VERR_SHARING_VIOLATION) && pOpts->fIgnoreNotEmpty) return RTEXITCODE_SUCCESS; /** @todo be verbose about this? */ if ((rc == VERR_PATH_NOT_FOUND || rc == VERR_FILE_NOT_FOUND) && pOpts->fIgnoreNonExisting) return RTEXITCODE_SUCCESS; /** @todo be verbose about this? */ return RTMsgErrorExitFailure("Failed to remove '%s': %Rrc", pszDir, rc); }
static RTEXITCODE HandleExtractExeSignerCert(int cArgs, char **papszArgs) { /* * Parse arguments. */ static const RTGETOPTDEF s_aOptions[] = { { "--ber", 'b', RTGETOPT_REQ_NOTHING }, { "--cer", 'c', RTGETOPT_REQ_NOTHING }, { "--der", 'd', RTGETOPT_REQ_NOTHING }, { "--exe", 'e', RTGETOPT_REQ_STRING }, { "--output", 'o', RTGETOPT_REQ_STRING }, }; const char *pszExe = NULL; const char *pszOut = NULL; RTLDRARCH enmLdrArch = RTLDRARCH_WHATEVER; uint32_t fCursorFlags = RTASN1CURSOR_FLAGS_DER; RTGETOPTSTATE GetState; int rc = RTGetOptInit(&GetState, cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); AssertRCReturn(rc, RTEXITCODE_FAILURE); RTGETOPTUNION ValueUnion; int ch; while ((ch = RTGetOpt(&GetState, &ValueUnion))) { switch (ch) { case 'e': pszExe = ValueUnion.psz; break; case 'o': pszOut = ValueUnion.psz; break; case 'b': fCursorFlags = 0; break; case 'c': fCursorFlags = RTASN1CURSOR_FLAGS_CER; break; case 'd': fCursorFlags = RTASN1CURSOR_FLAGS_DER; break; case 'V': return HandleVersion(cArgs, papszArgs); case 'h': return HelpExtractExeSignerCert(g_pStdOut, RTSIGNTOOLHELP_FULL); case VINF_GETOPT_NOT_OPTION: if (!pszExe) pszExe = ValueUnion.psz; else if (!pszOut) pszOut = ValueUnion.psz; else return RTMsgErrorExit(RTEXITCODE_FAILURE, "Too many file arguments: %s", ValueUnion.psz); break; default: return RTGetOptPrintError(ch, &ValueUnion); } } if (!pszExe) return RTMsgErrorExit(RTEXITCODE_FAILURE, "No executable given."); if (!pszOut) return RTMsgErrorExit(RTEXITCODE_FAILURE, "No output file given."); if (RTPathExists(pszOut)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "The output file '%s' exists.", pszOut); /* * Do it. */ /* Open the executable image and query the PKCS7 info. */ RTLDRMOD hLdrMod; rc = RTLdrOpen(pszExe, RTLDR_O_FOR_VALIDATION, enmLdrArch, &hLdrMod); if (RT_FAILURE(rc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error opening executable image '%s': %Rrc", pszExe, rc); RTEXITCODE rcExit = RTEXITCODE_FAILURE; #ifdef DEBUG size_t cbBuf = 64; #else size_t cbBuf = _512K; #endif void *pvBuf = RTMemAlloc(cbBuf); size_t cbRet = 0; rc = RTLdrQueryPropEx(hLdrMod, RTLDRPROP_PKCS7_SIGNED_DATA, NULL /*pvBits*/, pvBuf, cbBuf, &cbRet); if (rc == VERR_BUFFER_OVERFLOW && cbRet < _4M && cbRet > 0) { RTMemFree(pvBuf); cbBuf = cbRet; pvBuf = RTMemAlloc(cbBuf); rc = RTLdrQueryPropEx(hLdrMod, RTLDRPROP_PKCS7_SIGNED_DATA, NULL /*pvBits*/, pvBuf, cbBuf, &cbRet); } if (RT_SUCCESS(rc)) { static RTERRINFOSTATIC s_StaticErrInfo; RTErrInfoInitStatic(&s_StaticErrInfo); /* * Decode the output. */ RTASN1CURSORPRIMARY PrimaryCursor; RTAsn1CursorInitPrimary(&PrimaryCursor, pvBuf, (uint32_t)cbRet, &s_StaticErrInfo.Core, &g_RTAsn1DefaultAllocator, fCursorFlags, "exe"); RTCRPKCS7CONTENTINFO Pkcs7Ci; rc = RTCrPkcs7ContentInfo_DecodeAsn1(&PrimaryCursor.Cursor, 0, &Pkcs7Ci, "pkcs7"); if (RT_SUCCESS(rc)) { if (RTCrPkcs7ContentInfo_IsSignedData(&Pkcs7Ci)) { PCRTCRPKCS7SIGNEDDATA pSd = Pkcs7Ci.u.pSignedData; if (pSd->SignerInfos.cItems == 1) { PCRTCRPKCS7ISSUERANDSERIALNUMBER pISN = &pSd->SignerInfos.paItems[0].IssuerAndSerialNumber; PCRTCRX509CERTIFICATE pCert; pCert = RTCrPkcs7SetOfCerts_FindX509ByIssuerAndSerialNumber(&pSd->Certificates, &pISN->Name, &pISN->SerialNumber); if (pCert) { /* * Write it out. */ RTFILE hFile; rc = RTFileOpen(&hFile, pszOut, RTFILE_O_WRITE | RTFILE_O_DENY_WRITE | RTFILE_O_CREATE); if (RT_SUCCESS(rc)) { uint32_t cbCert = pCert->SeqCore.Asn1Core.cbHdr + pCert->SeqCore.Asn1Core.cb; rc = RTFileWrite(hFile, pCert->SeqCore.Asn1Core.uData.pu8 - pCert->SeqCore.Asn1Core.cbHdr, cbCert, NULL); if (RT_SUCCESS(rc)) { rc = RTFileClose(hFile); if (RT_SUCCESS(rc)) { hFile = NIL_RTFILE; rcExit = RTEXITCODE_SUCCESS; RTMsgInfo("Successfully wrote %u bytes to '%s'", cbCert, pszOut); } else RTMsgError("RTFileClose failed: %Rrc", rc); } else RTMsgError("RTFileWrite failed: %Rrc", rc); RTFileClose(hFile); } else RTMsgError("Error opening '%s': %Rrc", pszOut, rc); } else RTMsgError("Certificate not found."); } else RTMsgError("SignerInfo count: %u", pSd->SignerInfos.cItems); } else RTMsgError("No PKCS7 content: ContentType=%s", Pkcs7Ci.ContentType.szObjId); RTAsn1VtDelete(&Pkcs7Ci.SeqCore.Asn1Core); } else RTMsgError("RTPkcs7ContentInfoDecodeAsn1 failed: %Rrc - %s", rc, s_StaticErrInfo.szMsg); } else RTMsgError("RTLDRPROP_PKCS7_SIGNED_DATA failed on '%s': %Rrc", pszExe, rc); RTMemFree(pvBuf); rc = RTLdrClose(hLdrMod); if (RT_FAILURE(rc)) rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "RTLdrClose failed: %Rrc\n", rc); return rcExit; }