/** * Destroys the given config tokenizer. * * @returns nothing. * @param pCfgTokenizer The config tokenizer to destroy. */ static void autostartConfigTokenizerDestroy(PCFGTOKENIZER pCfgTokenizer) { if (pCfgTokenizer->pszLine) RTMemFree(pCfgTokenizer->pszLine); if (pCfgTokenizer->hStrmConfig) RTStrmClose(pCfgTokenizer->hStrmConfig); if (pCfgTokenizer->pTokenNext) RTMemFree(pCfgTokenizer->pTokenNext); RTMemFree(pCfgTokenizer); }
RTR3DECL(bool) RTProcIsRunningByName(const char *pszName) { /* * Quick validation. */ if (!pszName) return false; bool const fWithPath = RTPathHavePath(pszName); /* * Enumerate /proc. */ RTDIR hDir; int rc = RTDirOpen(&hDir, "/proc"); AssertMsgRCReturn(rc, ("RTDirOpen on /proc failed: rc=%Rrc\n", rc), false); if (RT_SUCCESS(rc)) { RTDIRENTRY DirEntry; while (RT_SUCCESS(RTDirRead(hDir, &DirEntry, NULL))) { /* * Filter numeric directory entries only. */ if ( ( DirEntry.enmType == RTDIRENTRYTYPE_DIRECTORY || DirEntry.enmType == RTDIRENTRYTYPE_UNKNOWN) && RTStrToUInt32(DirEntry.szName) > 0) { /* * Try readlink on exe first since it's more faster and reliable. * Fall back on reading the first line in cmdline if that fails * (access errors typically). cmdline is unreliable as it might * contain whatever the execv caller passes as argv[0]. */ char szName[RTPATH_MAX]; RTStrPrintf(szName, sizeof(szName), "/proc/%s/exe", &DirEntry.szName[0]); char szExe[RTPATH_MAX]; int cchLink = readlink(szName, szExe, sizeof(szExe) - 1); if ( cchLink > 0 && (size_t)cchLink < sizeof(szExe)) { szExe[cchLink] = '\0'; rc = VINF_SUCCESS; } else { RTStrPrintf(szName, sizeof(szName), "/proc/%s/cmdline", &DirEntry.szName[0]); PRTSTREAM pStream; rc = RTStrmOpen(szName, "r", &pStream); if (RT_SUCCESS(rc)) { rc = RTStrmGetLine(pStream, szExe, sizeof(szExe)); RTStrmClose(pStream); } } if (RT_SUCCESS(rc)) { /* * We are interested on the file name part only. */ char const *pszProcName = fWithPath ? szExe : RTPathFilename(szExe); if (RTStrCmp(pszProcName, pszName) == 0) { /* Found it! */ RTDirClose(hDir); return true; } } } } RTDirClose(hDir); } return false; }
/** * Gathers VM statistics and reports them to the host. */ static void VBoxServiceVMStatsReport(void) { #if defined(RT_OS_WINDOWS) SYSTEM_INFO systemInfo; PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION pProcInfo; MEMORYSTATUSEX memStatus; uint32_t cbStruct; DWORD cbReturned; Assert(gCtx.pfnGlobalMemoryStatusEx && gCtx.pfnNtQuerySystemInformation); if ( !gCtx.pfnGlobalMemoryStatusEx || !gCtx.pfnNtQuerySystemInformation) return; /* Clear the report so we don't report garbage should NtQuerySystemInformation behave in an unexpected manner. */ VMMDevReportGuestStats req; RT_ZERO(req); /* Query and report guest statistics */ GetSystemInfo(&systemInfo); memStatus.dwLength = sizeof(memStatus); gCtx.pfnGlobalMemoryStatusEx(&memStatus); req.guestStats.u32PageSize = systemInfo.dwPageSize; req.guestStats.u32PhysMemTotal = (uint32_t)(memStatus.ullTotalPhys / _4K); req.guestStats.u32PhysMemAvail = (uint32_t)(memStatus.ullAvailPhys / _4K); /* The current size of the committed memory limit, in bytes. This is physical memory plus the size of the page file, minus a small overhead. */ req.guestStats.u32PageFileSize = (uint32_t)(memStatus.ullTotalPageFile / _4K) - req.guestStats.u32PhysMemTotal; req.guestStats.u32MemoryLoad = memStatus.dwMemoryLoad; req.guestStats.u32StatCaps = VBOX_GUEST_STAT_PHYS_MEM_TOTAL | VBOX_GUEST_STAT_PHYS_MEM_AVAIL | VBOX_GUEST_STAT_PAGE_FILE_SIZE | VBOX_GUEST_STAT_MEMORY_LOAD; #ifdef VBOX_WITH_MEMBALLOON req.guestStats.u32PhysMemBalloon = VBoxServiceBalloonQueryPages(_4K); req.guestStats.u32StatCaps |= VBOX_GUEST_STAT_PHYS_MEM_BALLOON; #else req.guestStats.u32PhysMemBalloon = 0; #endif if (gCtx.pfnGetPerformanceInfo) { PERFORMANCE_INFORMATION perfInfo; if (gCtx.pfnGetPerformanceInfo(&perfInfo, sizeof(perfInfo))) { req.guestStats.u32Processes = perfInfo.ProcessCount; req.guestStats.u32Threads = perfInfo.ThreadCount; req.guestStats.u32Handles = perfInfo.HandleCount; req.guestStats.u32MemCommitTotal = perfInfo.CommitTotal; /* already in pages */ req.guestStats.u32MemKernelTotal = perfInfo.KernelTotal; /* already in pages */ req.guestStats.u32MemKernelPaged = perfInfo.KernelPaged; /* already in pages */ req.guestStats.u32MemKernelNonPaged = perfInfo.KernelNonpaged; /* already in pages */ req.guestStats.u32MemSystemCache = perfInfo.SystemCache; /* already in pages */ req.guestStats.u32StatCaps |= VBOX_GUEST_STAT_PROCESSES | VBOX_GUEST_STAT_THREADS | VBOX_GUEST_STAT_HANDLES | VBOX_GUEST_STAT_MEM_COMMIT_TOTAL | VBOX_GUEST_STAT_MEM_KERNEL_TOTAL | VBOX_GUEST_STAT_MEM_KERNEL_PAGED | VBOX_GUEST_STAT_MEM_KERNEL_NONPAGED | VBOX_GUEST_STAT_MEM_SYSTEM_CACHE; } else VBoxServiceVerbose(3, "VBoxServiceVMStatsReport: GetPerformanceInfo failed with %d\n", GetLastError()); } /* Query CPU load information */ cbStruct = systemInfo.dwNumberOfProcessors * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION); pProcInfo = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)RTMemAlloc(cbStruct); if (!pProcInfo) return; /* Unfortunately GetSystemTimes is XP SP1 and up only, so we need to use the semi-undocumented NtQuerySystemInformation */ NTSTATUS rc = gCtx.pfnNtQuerySystemInformation(SystemProcessorPerformanceInformation, pProcInfo, cbStruct, &cbReturned); if ( !rc && cbReturned == cbStruct) { if (gCtx.au64LastCpuLoad_Kernel == 0) { /* first time */ gCtx.au64LastCpuLoad_Idle[0] = pProcInfo->IdleTime.QuadPart; gCtx.au64LastCpuLoad_Kernel[0] = pProcInfo->KernelTime.QuadPart; gCtx.au64LastCpuLoad_User[0] = pProcInfo->UserTime.QuadPart; Sleep(250); rc = gCtx.pfnNtQuerySystemInformation(SystemProcessorPerformanceInformation, pProcInfo, cbStruct, &cbReturned); Assert(!rc); } uint64_t deltaIdle = (pProcInfo->IdleTime.QuadPart - gCtx.au64LastCpuLoad_Idle[0]); uint64_t deltaKernel = (pProcInfo->KernelTime.QuadPart - gCtx.au64LastCpuLoad_Kernel[0]); uint64_t deltaUser = (pProcInfo->UserTime.QuadPart - gCtx.au64LastCpuLoad_User[0]); deltaKernel -= deltaIdle; /* idle time is added to kernel time */ uint64_t ullTotalTime = deltaIdle + deltaKernel + deltaUser; if (ullTotalTime == 0) /* Prevent division through zero. */ ullTotalTime = 1; req.guestStats.u32CpuLoad_Idle = (uint32_t)(deltaIdle * 100 / ullTotalTime); req.guestStats.u32CpuLoad_Kernel = (uint32_t)(deltaKernel* 100 / ullTotalTime); req.guestStats.u32CpuLoad_User = (uint32_t)(deltaUser * 100 / ullTotalTime); req.guestStats.u32StatCaps |= VBOX_GUEST_STAT_CPU_LOAD_IDLE | VBOX_GUEST_STAT_CPU_LOAD_KERNEL | VBOX_GUEST_STAT_CPU_LOAD_USER; gCtx.au64LastCpuLoad_Idle[0] = pProcInfo->IdleTime.QuadPart; gCtx.au64LastCpuLoad_Kernel[0] = pProcInfo->KernelTime.QuadPart; gCtx.au64LastCpuLoad_User[0] = pProcInfo->UserTime.QuadPart; /** @todo SMP: report details for each CPU? */ } for (uint32_t i = 0; i < systemInfo.dwNumberOfProcessors; i++) { req.guestStats.u32CpuId = i; rc = VbglR3StatReport(&req); if (RT_SUCCESS(rc)) VBoxServiceVerbose(3, "VBoxStatsReportStatistics: new statistics (CPU %u) reported successfully!\n", i); else VBoxServiceVerbose(3, "VBoxStatsReportStatistics: DeviceIoControl (stats report) failed with %d\n", GetLastError()); } RTMemFree(pProcInfo); #elif defined(RT_OS_LINUX) VMMDevReportGuestStats req; RT_ZERO(req); PRTSTREAM pStrm; char szLine[256]; char *psz; int rc = RTStrmOpen("/proc/meminfo", "r", &pStrm); if (RT_SUCCESS(rc)) { uint64_t u64Kb; uint64_t u64Total = 0, u64Free = 0, u64Buffers = 0, u64Cached = 0, u64PagedTotal = 0; for (;;) { rc = RTStrmGetLine(pStrm, szLine, sizeof(szLine)); if (RT_FAILURE(rc)) break; if (strstr(szLine, "MemTotal:") == szLine) { rc = RTStrToUInt64Ex(RTStrStripL(&szLine[9]), &psz, 0, &u64Kb); if (RT_SUCCESS(rc)) u64Total = u64Kb * _1K; } else if (strstr(szLine, "MemFree:") == szLine) { rc = RTStrToUInt64Ex(RTStrStripL(&szLine[8]), &psz, 0, &u64Kb); if (RT_SUCCESS(rc)) u64Free = u64Kb * _1K; } else if (strstr(szLine, "Buffers:") == szLine) { rc = RTStrToUInt64Ex(RTStrStripL(&szLine[8]), &psz, 0, &u64Kb); if (RT_SUCCESS(rc)) u64Buffers = u64Kb * _1K; } else if (strstr(szLine, "Cached:") == szLine) { rc = RTStrToUInt64Ex(RTStrStripL(&szLine[7]), &psz, 0, &u64Kb); if (RT_SUCCESS(rc)) u64Cached = u64Kb * _1K; } else if (strstr(szLine, "SwapTotal:") == szLine) { rc = RTStrToUInt64Ex(RTStrStripL(&szLine[10]), &psz, 0, &u64Kb); if (RT_SUCCESS(rc)) u64PagedTotal = u64Kb * _1K; } } req.guestStats.u32PhysMemTotal = u64Total / _4K; req.guestStats.u32PhysMemAvail = (u64Free + u64Buffers + u64Cached) / _4K; req.guestStats.u32MemSystemCache = (u64Buffers + u64Cached) / _4K; req.guestStats.u32PageFileSize = u64PagedTotal / _4K; RTStrmClose(pStrm); } else VBoxServiceVerbose(3, "VBoxStatsReportStatistics: memory info not available!\n"); req.guestStats.u32PageSize = getpagesize(); req.guestStats.u32StatCaps = VBOX_GUEST_STAT_PHYS_MEM_TOTAL | VBOX_GUEST_STAT_PHYS_MEM_AVAIL | VBOX_GUEST_STAT_MEM_SYSTEM_CACHE | VBOX_GUEST_STAT_PAGE_FILE_SIZE; #ifdef VBOX_WITH_MEMBALLOON req.guestStats.u32PhysMemBalloon = VBoxServiceBalloonQueryPages(_4K); req.guestStats.u32StatCaps |= VBOX_GUEST_STAT_PHYS_MEM_BALLOON; #else req.guestStats.u32PhysMemBalloon = 0; #endif /** @todo req.guestStats.u32Threads */ /** @todo req.guestStats.u32Processes */ /* req.guestStats.u32Handles doesn't make sense here. */ /** @todo req.guestStats.u32MemoryLoad */ /** @todo req.guestStats.u32MemCommitTotal */ /** @todo req.guestStats.u32MemKernelTotal */ /** @todo req.guestStats.u32MemKernelPaged, make any sense? = u32MemKernelTotal? */ /** @todo req.guestStats.u32MemKernelNonPaged, make any sense? = 0? */ bool fCpuInfoAvail = false; rc = RTStrmOpen("/proc/stat", "r", &pStrm); if (RT_SUCCESS(rc)) { for (;;) { rc = RTStrmGetLine(pStrm, szLine, sizeof(szLine)); if (RT_FAILURE(rc)) break; if ( strstr(szLine, "cpu") == szLine && strlen(szLine) > 3 && RT_C_IS_DIGIT(szLine[3])) { uint32_t u32CpuId; rc = RTStrToUInt32Ex(&szLine[3], &psz, 0, &u32CpuId); if (u32CpuId < VMM_MAX_CPU_COUNT) { uint64_t u64User = 0; if (RT_SUCCESS(rc)) rc = RTStrToUInt64Ex(RTStrStripL(psz), &psz, 0, &u64User); uint64_t u64Nice = 0; if (RT_SUCCESS(rc)) rc = RTStrToUInt64Ex(RTStrStripL(psz), &psz, 0, &u64Nice); uint64_t u64System = 0; if (RT_SUCCESS(rc)) rc = RTStrToUInt64Ex(RTStrStripL(psz), &psz, 0, &u64System); uint64_t u64Idle = 0; if (RT_SUCCESS(rc)) rc = RTStrToUInt64Ex(RTStrStripL(psz), &psz, 0, &u64Idle); uint64_t u64DeltaIdle = u64Idle - gCtx.au64LastCpuLoad_Idle[u32CpuId]; uint64_t u64DeltaSystem = u64System - gCtx.au64LastCpuLoad_Kernel[u32CpuId]; uint64_t u64DeltaUser = u64User - gCtx.au64LastCpuLoad_User[u32CpuId]; uint64_t u64DeltaNice = u64Nice - gCtx.au64LastCpuLoad_Nice[u32CpuId]; uint64_t u64DeltaAll = u64DeltaIdle + u64DeltaSystem + u64DeltaUser + u64DeltaNice; if (u64DeltaAll == 0) /* Prevent division through zero. */ u64DeltaAll = 1; gCtx.au64LastCpuLoad_Idle[u32CpuId] = u64Idle; gCtx.au64LastCpuLoad_Kernel[u32CpuId] = u64System; gCtx.au64LastCpuLoad_User[u32CpuId] = u64User; gCtx.au64LastCpuLoad_Nice[u32CpuId] = u64Nice; req.guestStats.u32CpuId = u32CpuId; req.guestStats.u32CpuLoad_Idle = (uint32_t)(u64DeltaIdle * 100 / u64DeltaAll); req.guestStats.u32CpuLoad_Kernel = (uint32_t)(u64DeltaSystem * 100 / u64DeltaAll); req.guestStats.u32CpuLoad_User = (uint32_t)((u64DeltaUser + u64DeltaNice) * 100 / u64DeltaAll); req.guestStats.u32StatCaps |= VBOX_GUEST_STAT_CPU_LOAD_IDLE | VBOX_GUEST_STAT_CPU_LOAD_KERNEL | VBOX_GUEST_STAT_CPU_LOAD_USER; fCpuInfoAvail = true; rc = VbglR3StatReport(&req); if (RT_SUCCESS(rc)) VBoxServiceVerbose(3, "VBoxStatsReportStatistics: new statistics (CPU %u) reported successfully!\n", u32CpuId); else VBoxServiceVerbose(3, "VBoxStatsReportStatistics: stats report failed with rc=%Rrc\n", rc); } else VBoxServiceVerbose(3, "VBoxStatsReportStatistics: skipping information for CPU%u\n", u32CpuId); } } RTStrmClose(pStrm); } if (!fCpuInfoAvail) { VBoxServiceVerbose(3, "VBoxStatsReportStatistics: CPU info not available!\n"); rc = VbglR3StatReport(&req); if (RT_SUCCESS(rc)) VBoxServiceVerbose(3, "VBoxStatsReportStatistics: new statistics reported successfully!\n"); else VBoxServiceVerbose(3, "VBoxStatsReportStatistics: stats report failed with rc=%Rrc\n", rc); } #elif defined(RT_OS_SOLARIS) VMMDevReportGuestStats req; RT_ZERO(req); kstat_ctl_t *pStatKern = kstat_open(); if (pStatKern) { /* * Memory statistics. */ uint64_t u64Total = 0, u64Free = 0, u64Buffers = 0, u64Cached = 0, u64PagedTotal = 0; int rc = -1; kstat_t *pStatPages = kstat_lookup(pStatKern, (char *)"unix", 0 /* instance */, (char *)"system_pages"); if (pStatPages) { rc = kstat_read(pStatKern, pStatPages, NULL /* optional-copy-buf */); if (rc != -1) { kstat_named_t *pStat = NULL; pStat = (kstat_named_t *)kstat_data_lookup(pStatPages, (char *)"pagestotal"); if (pStat) u64Total = pStat->value.ul; pStat = (kstat_named_t *)kstat_data_lookup(pStatPages, (char *)"freemem"); if (pStat) u64Free = pStat->value.ul; } } kstat_t *pStatZFS = kstat_lookup(pStatKern, (char *)"zfs", 0 /* instance */, (char *)"arcstats"); if (pStatZFS) { rc = kstat_read(pStatKern, pStatZFS, NULL /* optional-copy-buf */); if (rc != -1) { kstat_named_t *pStat = (kstat_named_t *)kstat_data_lookup(pStatZFS, (char *)"size"); if (pStat) u64Cached = pStat->value.ul; } } /* * The vminfo are accumulative counters updated every "N" ticks. Let's get the * number of stat updates so far and use that to divide the swap counter. */ kstat_t *pStatInfo = kstat_lookup(pStatKern, (char *)"unix", 0 /* instance */, (char *)"sysinfo"); if (pStatInfo) { sysinfo_t SysInfo; rc = kstat_read(pStatKern, pStatInfo, &SysInfo); if (rc != -1) { kstat_t *pStatVMInfo = kstat_lookup(pStatKern, (char *)"unix", 0 /* instance */, (char *)"vminfo"); if (pStatVMInfo) { vminfo_t VMInfo; rc = kstat_read(pStatKern, pStatVMInfo, &VMInfo); if (rc != -1) { Assert(SysInfo.updates != 0); u64PagedTotal = VMInfo.swap_avail / SysInfo.updates; } } } } req.guestStats.u32PhysMemTotal = u64Total; /* already in pages */ req.guestStats.u32PhysMemAvail = u64Free; /* already in pages */ req.guestStats.u32MemSystemCache = u64Cached / _4K; req.guestStats.u32PageFileSize = u64PagedTotal; /* already in pages */ /** @todo req.guestStats.u32Threads */ /** @todo req.guestStats.u32Processes */ /** @todo req.guestStats.u32Handles -- ??? */ /** @todo req.guestStats.u32MemoryLoad */ /** @todo req.guestStats.u32MemCommitTotal */ /** @todo req.guestStats.u32MemKernelTotal */ /** @todo req.guestStats.u32MemKernelPaged */ /** @todo req.guestStats.u32MemKernelNonPaged */ req.guestStats.u32PageSize = getpagesize(); req.guestStats.u32StatCaps = VBOX_GUEST_STAT_PHYS_MEM_TOTAL | VBOX_GUEST_STAT_PHYS_MEM_AVAIL | VBOX_GUEST_STAT_MEM_SYSTEM_CACHE | VBOX_GUEST_STAT_PAGE_FILE_SIZE; #ifdef VBOX_WITH_MEMBALLOON req.guestStats.u32PhysMemBalloon = VBoxServiceBalloonQueryPages(_4K); req.guestStats.u32StatCaps |= VBOX_GUEST_STAT_PHYS_MEM_BALLOON; #else req.guestStats.u32PhysMemBalloon = 0; #endif /* * CPU statistics. */ cpu_stat_t StatCPU; RT_ZERO(StatCPU); kstat_t *pStatNode = NULL; uint32_t cCPUs = 0; bool fCpuInfoAvail = false; for (pStatNode = pStatKern->kc_chain; pStatNode != NULL; pStatNode = pStatNode->ks_next) { if (!strcmp(pStatNode->ks_module, "cpu_stat")) { rc = kstat_read(pStatKern, pStatNode, &StatCPU); if (rc == -1) break; uint64_t u64Idle = StatCPU.cpu_sysinfo.cpu[CPU_IDLE]; uint64_t u64User = StatCPU.cpu_sysinfo.cpu[CPU_USER]; uint64_t u64System = StatCPU.cpu_sysinfo.cpu[CPU_KERNEL]; uint64_t u64DeltaIdle = u64Idle - gCtx.au64LastCpuLoad_Idle[cCPUs]; uint64_t u64DeltaSystem = u64System - gCtx.au64LastCpuLoad_Kernel[cCPUs]; uint64_t u64DeltaUser = u64User - gCtx.au64LastCpuLoad_User[cCPUs]; uint64_t u64DeltaAll = u64DeltaIdle + u64DeltaSystem + u64DeltaUser; if (u64DeltaAll == 0) /* Prevent division through zero. */ u64DeltaAll = 1; gCtx.au64LastCpuLoad_Idle[cCPUs] = u64Idle; gCtx.au64LastCpuLoad_Kernel[cCPUs] = u64System; gCtx.au64LastCpuLoad_User[cCPUs] = u64User; req.guestStats.u32CpuId = cCPUs; req.guestStats.u32CpuLoad_Idle = (uint32_t)(u64DeltaIdle * 100 / u64DeltaAll); req.guestStats.u32CpuLoad_Kernel = (uint32_t)(u64DeltaSystem * 100 / u64DeltaAll); req.guestStats.u32CpuLoad_User = (uint32_t)(u64DeltaUser * 100 / u64DeltaAll); req.guestStats.u32StatCaps |= VBOX_GUEST_STAT_CPU_LOAD_IDLE | VBOX_GUEST_STAT_CPU_LOAD_KERNEL | VBOX_GUEST_STAT_CPU_LOAD_USER; fCpuInfoAvail = true; rc = VbglR3StatReport(&req); if (RT_SUCCESS(rc)) VBoxServiceVerbose(3, "VBoxStatsReportStatistics: new statistics (CPU %u) reported successfully!\n", cCPUs); else VBoxServiceVerbose(3, "VBoxStatsReportStatistics: stats report failed with rc=%Rrc\n", rc); cCPUs++; } } /* * Report whatever statistics were collected. */ if (!fCpuInfoAvail) { VBoxServiceVerbose(3, "VBoxStatsReportStatistics: CPU info not available!\n"); rc = VbglR3StatReport(&req); if (RT_SUCCESS(rc)) VBoxServiceVerbose(3, "VBoxStatsReportStatistics: new statistics reported successfully!\n"); else VBoxServiceVerbose(3, "VBoxStatsReportStatistics: stats report failed with rc=%Rrc\n", rc); } kstat_close(pStatKern); } #else /* todo: implement for other platforms. */ #endif }
int main(int argc, char *argv[]) { /* * Initialize IPRT and convert argv to UTF-8. */ int rc = RTR3InitExe(argc, &argv, 0); if (RT_FAILURE(rc)) return RTMsgInitFailure(rc); /* * Parse arguments and read input files. */ if (argc < 4) { usage(stderr, argv[0]); return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Insufficient arguments."); } g_products.reserve(20000); g_vendors.reserve(3500); const char *pszOutFile = NULL; for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "-o") == 0) { pszOutFile = argv[++i]; continue; } if ( strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-?") == 0 || strcmp(argv[i], "--help") == 0) { usage(stdout, argv[0]); return RTEXITCODE_SUCCESS; } PRTSTREAM pInStrm; rc = RTStrmOpen(argv[i], "r", &pInStrm); if (RT_FAILURE(rc)) return RTMsgErrorExit((RTEXITCODE)ERROR_OPEN_FILE, "Failed to open file '%s' for reading: %Rrc", argv[i], rc); rc = ParseUsbIds(pInStrm, argv[i]); RTStrmClose(pInStrm); if (rc != 0) { RTMsgError("Failed parsing USB devices file '%s'", argv[i]); return rc; } } /* * Due to USBIDDBVENDOR::iProduct, there is currently a max of 64KB products. * (Not a problem as we've only have less that 54K products currently.) */ if (g_products.size() > _64K) return RTMsgErrorExit((RTEXITCODE)ERROR_TOO_MANY_PRODUCTS, "More than 64K products is not supported: %u products", g_products.size()); /* * Sort the IDs and fill in the iProduct and cProduct members. */ sort(g_products.begin(), g_products.end()); sort(g_vendors.begin(), g_vendors.end()); size_t iProduct = 0; for (size_t iVendor = 0; iVendor < g_vendors.size(); iVendor++) { size_t const idVendor = g_vendors[iVendor].vendorID; g_vendors[iVendor].iProduct = iProduct; if ( iProduct < g_products.size() && g_products[iProduct].vendorID <= idVendor) { if (g_products[iProduct].vendorID == idVendor) do iProduct++; while ( iProduct < g_products.size() && g_products[iProduct].vendorID == idVendor); else return RTMsgErrorExit((RTEXITCODE)ERROR_IN_PARSE_LINE, "product without vendor after sorting. impossible!"); } g_vendors[iVendor].cProducts = iProduct - g_vendors[iVendor].iProduct; } /* * Verify that all IDs are unique. */ ProductsSet::iterator ita = adjacent_find(g_products.begin(), g_products.end()); if (ita != g_products.end()) return RTMsgErrorExit((RTEXITCODE)ERROR_DUPLICATE_ENTRY, "Duplicate alias detected: idProduct=%#06x", ita->productID); /* * Build the string table. * Do string compression and create the string table. */ BLDPROGSTRTAB StrTab; if (!BldProgStrTab_Init(&StrTab, g_products.size() + g_vendors.size())) return RTMsgErrorExit(RTEXITCODE_FAILURE, "Out of memory!"); for (ProductsSet::iterator it = g_products.begin(); it != g_products.end(); ++it) { it->StrRef.pszString = (char *)it->str.c_str(); BldProgStrTab_AddString(&StrTab, &it->StrRef); } for (VendorsSet::iterator it = g_vendors.begin(); it != g_vendors.end(); ++it) { it->StrRef.pszString = (char *)it->str.c_str(); BldProgStrTab_AddString(&StrTab, &it->StrRef); } if (!BldProgStrTab_CompileIt(&StrTab, g_fVerbose)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "BldProgStrTab_CompileIt failed!\n"); /* * Print stats. Making a little extra effort to get it all on one line. */ size_t const cbVendorEntry = sizeof(USBIdDatabase::s_aVendors[0]) + sizeof(USBIdDatabase::s_aVendorNames[0]); size_t const cbProductEntry = sizeof(USBIdDatabase::s_aProducts[0]) + sizeof(USBIdDatabase::s_aProductNames[0]); size_t cbOldRaw = (g_products.size() + g_vendors.size()) * sizeof(const char *) * 2 + g_cbRawStrings; size_t cbRaw = g_vendors.size() * cbVendorEntry + g_products.size() * cbProductEntry + g_cbRawStrings; size_t cbActual = g_vendors.size() * cbVendorEntry + g_products.size() * cbProductEntry + StrTab.cchStrTab; #ifdef USB_ID_DATABASE_WITH_COMPRESSION cbActual += sizeof(StrTab.aCompDict); #endif char szMsg1[32]; RTStrPrintf(szMsg1, sizeof(szMsg1),"Total %zu bytes", cbActual); char szMsg2[64]; RTStrPrintf(szMsg2, sizeof(szMsg2)," old version %zu bytes + relocs (%zu%% save)", cbOldRaw, (cbOldRaw - cbActual) * 100 / cbOldRaw); if (cbActual < cbRaw) RTMsgInfo("%s - saving %zu%% (%zu bytes);%s", szMsg1, (cbRaw - cbActual) * 100 / cbRaw, cbRaw - cbActual, szMsg2); else RTMsgInfo("%s - wasting %zu bytes;%s", szMsg1, cbActual - cbRaw, szMsg2); /* * Produce the source file. */ if (!pszOutFile) return RTMsgErrorExit((RTEXITCODE)ERROR_OPEN_FILE, "Output file is not specified."); FILE *pOut = fopen(pszOutFile, "w"); if (!pOut) return RTMsgErrorExit((RTEXITCODE)ERROR_OPEN_FILE, "Error opening '%s' for writing", pszOutFile); WriteSourceFile(pOut, argv[0], &StrTab); if (ferror(pOut)) return RTMsgErrorExit((RTEXITCODE)ERROR_OPEN_FILE, "Error writing '%s'!", pszOutFile); if (fclose(pOut) != 0) return RTMsgErrorExit((RTEXITCODE)ERROR_OPEN_FILE, "Error closing '%s'!", pszOutFile); return RTEXITCODE_SUCCESS; }
int main(int argc, char **argv) { RTR3InitExe(argc, &argv, 0); RTDIGESTTYPE enmDigestType = RTDIGESTTYPE_INVALID; const char *pszDigestType = "NotSpecified"; enum { kMethod_Full, kMethod_Block, kMethod_File, kMethod_CVAS } enmMethod = kMethod_Block; uint64_t offStart = 0; uint64_t cbMax = UINT64_MAX; bool fTestcase = false; static const RTGETOPTDEF s_aOptions[] = { { "--type", 't', RTGETOPT_REQ_STRING }, { "--method", 'm', RTGETOPT_REQ_STRING }, { "--help", 'h', RTGETOPT_REQ_NOTHING }, { "--length", 'l', RTGETOPT_REQ_UINT64 }, { "--offset", 'o', RTGETOPT_REQ_UINT64 }, { "--testcase", 'x', RTGETOPT_REQ_NOTHING }, }; int ch; RTGETOPTUNION ValueUnion; RTGETOPTSTATE GetState; RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); while ((ch = RTGetOpt(&GetState, &ValueUnion))) { switch (ch) { case 't': if (!RTStrICmp(ValueUnion.psz, "crc32")) { pszDigestType = "CRC32"; enmDigestType = RTDIGESTTYPE_CRC32; } else if (!RTStrICmp(ValueUnion.psz, "crc64")) { pszDigestType = "CRC64"; enmDigestType = RTDIGESTTYPE_CRC64; } else if (!RTStrICmp(ValueUnion.psz, "md2")) { pszDigestType = "MD2"; enmDigestType = RTDIGESTTYPE_MD2; } else if (!RTStrICmp(ValueUnion.psz, "md5")) { pszDigestType = "MD5"; enmDigestType = RTDIGESTTYPE_MD5; } else if (!RTStrICmp(ValueUnion.psz, "sha1")) { pszDigestType = "SHA-1"; enmDigestType = RTDIGESTTYPE_SHA1; } else if (!RTStrICmp(ValueUnion.psz, "sha224")) { pszDigestType = "SHA-224"; enmDigestType = RTDIGESTTYPE_SHA224; } else if (!RTStrICmp(ValueUnion.psz, "sha256")) { pszDigestType = "SHA-256"; enmDigestType = RTDIGESTTYPE_SHA256; } else if (!RTStrICmp(ValueUnion.psz, "sha384")) { pszDigestType = "SHA-384"; enmDigestType = RTDIGESTTYPE_SHA384; } else if (!RTStrICmp(ValueUnion.psz, "sha512")) { pszDigestType = "SHA-512"; enmDigestType = RTDIGESTTYPE_SHA512; } else if (!RTStrICmp(ValueUnion.psz, "sha512/224")) { pszDigestType = "SHA-512/224"; enmDigestType = RTDIGESTTYPE_SHA512T224; } else if (!RTStrICmp(ValueUnion.psz, "sha512/256")) { pszDigestType = "SHA-512/256"; enmDigestType = RTDIGESTTYPE_SHA512T256; } else { Error("Invalid digest type: %s\n", ValueUnion.psz); return 1; } break; case 'm': if (!RTStrICmp(ValueUnion.psz, "full")) enmMethod = kMethod_Full; else if (!RTStrICmp(ValueUnion.psz, "block")) enmMethod = kMethod_Block; else if (!RTStrICmp(ValueUnion.psz, "file")) enmMethod = kMethod_File; else if (!RTStrICmp(ValueUnion.psz, "cvas")) enmMethod = kMethod_CVAS; else { Error("Invalid digest method: %s\n", ValueUnion.psz); return 1; } break; case 'l': cbMax = ValueUnion.u64; break; case 'o': offStart = ValueUnion.u64; break; case 'x': fTestcase = true; break; case 'h': RTPrintf("usage: tstRTDigest -t <digest-type> [-o <offset>] [-l <length>] [-x] file [file2 [..]]\n"); return 1; case VINF_GETOPT_NOT_OPTION: { if (enmDigestType == RTDIGESTTYPE_INVALID) return Error("No digest type was specified\n"); switch (enmMethod) { case kMethod_Full: return Error("Full file method is not implemented\n"); case kMethod_File: if (offStart != 0 || cbMax != UINT64_MAX) return Error("The -l and -o options do not work with the 'file' method."); switch (enmDigestType) { case RTDIGESTTYPE_SHA1: { char *pszDigest; int rc = RTSha1DigestFromFile(ValueUnion.psz, &pszDigest, NULL, NULL); if (RT_FAILURE(rc)) return Error("RTSha1Digest(%s,) -> %Rrc\n", ValueUnion.psz, rc); RTPrintf("%s %s\n", pszDigest, ValueUnion.psz); RTStrFree(pszDigest); break; } case RTDIGESTTYPE_SHA256: { char *pszDigest; int rc = RTSha256DigestFromFile(ValueUnion.psz, &pszDigest, NULL, NULL); if (RT_FAILURE(rc)) return Error("RTSha256Digest(%s,) -> %Rrc\n", ValueUnion.psz, rc); RTPrintf("%s %s\n", pszDigest, ValueUnion.psz); RTStrFree(pszDigest); break; } default: return Error("The file method isn't implemented for this digest\n"); } break; case kMethod_Block: { RTFILE hFile; int rc = RTFileOpen(&hFile, ValueUnion.psz, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); if (RT_FAILURE(rc)) return Error("RTFileOpen(,%s,) -> %Rrc\n", ValueUnion.psz, rc); if (offStart != 0) { rc = RTFileSeek(hFile, offStart, RTFILE_SEEK_BEGIN, NULL); if (RT_FAILURE(rc)) return Error("RTFileSeek(%s,%ull) -> %Rrc\n", ValueUnion.psz, offStart, rc); } uint64_t cbMaxLeft = cbMax; size_t cbRead; uint8_t abBuf[_64K]; char *pszDigest = (char *)&abBuf[0]; switch (enmDigestType) { case RTDIGESTTYPE_CRC32: { uint32_t uCRC32 = RTCrc32Start(); for (;;) { rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft); if (RT_FAILURE(rc) || !cbRead) break; uCRC32 = RTCrc32Process(uCRC32, abBuf, cbRead); } uCRC32 = RTCrc32Finish(uCRC32); RTStrPrintf(pszDigest, sizeof(abBuf), "%08RX32", uCRC32); break; } case RTDIGESTTYPE_CRC64: { uint64_t uCRC64 = RTCrc64Start(); for (;;) { rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft); if (RT_FAILURE(rc) || !cbRead) break; uCRC64 = RTCrc64Process(uCRC64, abBuf, cbRead); } uCRC64 = RTCrc64Finish(uCRC64); RTStrPrintf(pszDigest, sizeof(abBuf), "%016RX64", uCRC64); break; } case RTDIGESTTYPE_MD2: { RTMD2CONTEXT Ctx; RTMd2Init(&Ctx); for (;;) { rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft); if (RT_FAILURE(rc) || !cbRead) break; RTMd2Update(&Ctx, abBuf, cbRead); } uint8_t abDigest[RTMD2_HASH_SIZE]; RTMd2Final(&Ctx, abDigest); RTMd2ToString(abDigest, pszDigest, sizeof(abBuf)); break; } case RTDIGESTTYPE_MD5: { RTMD5CONTEXT Ctx; RTMd5Init(&Ctx); for (;;) { rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft); if (RT_FAILURE(rc) || !cbRead) break; RTMd5Update(&Ctx, abBuf, cbRead); } uint8_t abDigest[RTMD5HASHSIZE]; RTMd5Final(abDigest, &Ctx); RTMd5ToString(abDigest, pszDigest, sizeof(abBuf)); break; } case RTDIGESTTYPE_SHA1: { RTSHA1CONTEXT Ctx; RTSha1Init(&Ctx); for (;;) { rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft); if (RT_FAILURE(rc) || !cbRead) break; RTSha1Update(&Ctx, abBuf, cbRead); } uint8_t abDigest[RTSHA1_HASH_SIZE]; RTSha1Final(&Ctx, abDigest); RTSha1ToString(abDigest, pszDigest, sizeof(abBuf)); break; } case RTDIGESTTYPE_SHA256: { RTSHA256CONTEXT Ctx; RTSha256Init(&Ctx); for (;;) { rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft); if (RT_FAILURE(rc) || !cbRead) break; RTSha256Update(&Ctx, abBuf, cbRead); } uint8_t abDigest[RTSHA256_HASH_SIZE]; RTSha256Final(&Ctx, abDigest); RTSha256ToString(abDigest, pszDigest, sizeof(abBuf)); break; } case RTDIGESTTYPE_SHA512: { RTSHA512CONTEXT Ctx; RTSha512Init(&Ctx); for (;;) { rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft); if (RT_FAILURE(rc) || !cbRead) break; RTSha512Update(&Ctx, abBuf, cbRead); } uint8_t abDigest[RTSHA512_HASH_SIZE]; RTSha512Final(&Ctx, abDigest); RTSha512ToString(abDigest, pszDigest, sizeof(abBuf)); break; } default: return Error("Internal error #1\n"); } RTFileClose(hFile); if (RT_FAILURE(rc) && rc != VERR_EOF) { RTPrintf("Partial: %s %s\n", pszDigest, ValueUnion.psz); return Error("RTFileRead(%s) -> %Rrc\n", ValueUnion.psz, rc); } if (!fTestcase) RTPrintf("%s %s\n", pszDigest, ValueUnion.psz); else if (offStart) RTPrintf(" { &g_abRandom72KB[%#4llx], %5llu, \"%s\", \"%s %llu bytes @%llu\" },\n", offStart, cbMax - cbMaxLeft, pszDigest, pszDigestType, offStart, cbMax - cbMaxLeft); else RTPrintf(" { &g_abRandom72KB[0], %5llu, \"%s\", \"%s %llu bytes\" },\n", cbMax - cbMaxLeft, pszDigest, pszDigestType, cbMax - cbMaxLeft); break; } /* * Process a SHS response file: * http://csrc.nist.gov/groups/STM/cavp/index.html#03 */ case kMethod_CVAS: { RTCRDIGEST hDigest; int rc = RTCrDigestCreateByType(&hDigest, enmDigestType); if (RT_FAILURE(rc)) return Error("Failed to create digest calculator for %s: %Rrc", pszDigestType, rc); uint32_t const cbDigest = RTCrDigestGetHashSize(hDigest); if (!cbDigest || cbDigest >= _1K) return Error("Unexpected hash size: %#x\n", cbDigest); PRTSTREAM pFile; rc = RTStrmOpen(ValueUnion.psz, "r", &pFile); if (RT_FAILURE(rc)) return Error("Failed to open CVAS file '%s': %Rrc", ValueUnion.psz, rc); /* * Parse the input file. * ASSUME order: Len, Msg, MD. */ static char s_szLine[_256K]; char *psz; uint32_t cPassed = 0; uint32_t cErrors = 0; uint32_t iLine = 1; for (;;) { psz = MyGetNextSignificantLine(pFile, s_szLine, sizeof(s_szLine), &iLine, &rc); if (!psz) break; /* Skip [L = 20] stuff. */ if (*psz == '[') continue; /* Message length. */ uint64_t cMessageBits; if (RTStrNICmp(psz, RT_STR_TUPLE("Len ="))) return Error("%s(%d): Expected 'Len =' found '%.10s...'", ValueUnion.psz, iLine, psz); psz = RTStrStripL(psz + 5); rc = RTStrToUInt64Full(psz, 0, &cMessageBits); if (rc != VINF_SUCCESS) return Error("%s(%d): Error parsing length '%s': %Rrc\n", ValueUnion.psz, iLine, psz, rc); /* The message text. */ psz = MyGetNextSignificantLine(pFile, s_szLine, sizeof(s_szLine), &iLine, &rc); if (!psz) return Error("%s(%d): Expected message text not EOF.", ValueUnion.psz, iLine); if (RTStrNICmp(psz, RT_STR_TUPLE("Msg ="))) return Error("%s(%d): Expected 'Msg =' found '%.10s...'", ValueUnion.psz, iLine, psz); psz = RTStrStripL(psz + 5); size_t const cbMessage = (cMessageBits + 7) / 8; static uint8_t s_abMessage[sizeof(s_szLine) / 2]; if (cbMessage > 0) { rc = RTStrConvertHexBytes(psz, s_abMessage, cbMessage, 0 /*fFlags*/); if (rc != VINF_SUCCESS) return Error("%s(%d): Error parsing message '%.10s...': %Rrc\n", ValueUnion.psz, iLine, psz, rc); } /* The message digest. */ psz = MyGetNextSignificantLine(pFile, s_szLine, sizeof(s_szLine), &iLine, &rc); if (!psz) return Error("%s(%d): Expected message digest not EOF.", ValueUnion.psz, iLine); if (RTStrNICmp(psz, RT_STR_TUPLE("MD ="))) return Error("%s(%d): Expected 'MD =' found '%.10s...'", ValueUnion.psz, iLine, psz); psz = RTStrStripL(psz + 4); static uint8_t s_abExpectedDigest[_1K]; rc = RTStrConvertHexBytes(psz, s_abExpectedDigest, cbDigest, 0 /*fFlags*/); if (rc != VINF_SUCCESS) return Error("%s(%d): Error parsing message digest '%.10s...': %Rrc\n", ValueUnion.psz, iLine, psz, rc); /* * Do the testing. */ rc = RTCrDigestReset(hDigest); if (rc != VINF_SUCCESS) return Error("RTCrDigestReset failed: %Rrc", rc); rc = RTCrDigestUpdate(hDigest, s_abMessage, cbMessage); if (rc != VINF_SUCCESS) return Error("RTCrDigestUpdate failed: %Rrc", rc); static uint8_t s_abActualDigest[_1K]; rc = RTCrDigestFinal(hDigest, s_abActualDigest, cbDigest); if (rc != VINF_SUCCESS) return Error("RTCrDigestFinal failed: %Rrc", rc); if (memcmp(s_abActualDigest, s_abExpectedDigest, cbDigest) == 0) cPassed++; else { Error("%s(%d): Message digest mismatch. Expected %.*RThxs, got %.*RThxs.", ValueUnion.psz, iLine, cbDigest, s_abExpectedDigest, cbDigest, s_abActualDigest); cErrors++; } } RTStrmClose(pFile); if (cErrors > 0) return Error("Failed: %u error%s (%u passed)", cErrors, cErrors == 1 ? "" : "s", cPassed); RTPrintf("Passed %u test%s.\n", cPassed, cPassed == 1 ? "" : "s"); if (RT_FAILURE(rc)) return Error("Failed: %Rrc", rc); break; } default: return Error("Internal error #2\n"); } break; } default: return RTGetOptPrintError(ch, &ValueUnion); } } return 0; }
int rcp_parse(struct rcp_state* state, const char *filename) { unsigned i; uint32_t flags; int rc; struct rcp_parser parser; flags = state->rcps_flags; RT_ZERO(parser); RT_ZERO(*state); state->rcps_flags = flags; parser.rcpp_state = state; /** * for debugging need: with RCP_STANDALONE it's possible * to run simplefied scenarious like * * # cat /etc/resolv.conf | rcp-test-0 * or in lldb * # process launch -i /etc/resolv.conf */ #ifdef RCP_STANDALONE if (filename == NULL) parser.rcpp_stream = g_pStdIn; #else if (filename == NULL) return -1; #endif else { rc = RTStrmOpen(filename, "r", &parser.rcpp_stream); if (RT_FAILURE(rc)) return -1; } rc = rcp_parse_primary(&parser); if (filename != NULL) RTStrmClose(parser.rcpp_stream); if (rc == -1) return -1; #ifdef RT_OS_DARWIN /** * port recolv.conf's option and IP.port are Mac OSX extentions, there're no need to care on * other hosts. */ if (state->rcps_port == 0) state->rcps_port = 53; for(i = 0; (state->rcps_flags & RCPSF_NO_STR2IPCONV) == 0 && i != RCPS_MAX_NAMESERVERS; ++i) { RTNETADDR *addr = &state->rcps_nameserver[i]; if (addr->uPort == 0) addr->uPort = state->rcps_port; } #endif if ( state->rcps_domain == NULL && state->rcps_searchlist[0] != NULL) state->rcps_domain = state->rcps_searchlist[0]; return 0; }
int main(int argc, char **argv) { unsigned cErrors = 0; RTR3InitExe(argc, &argv, 0); if (argc <= 1) { RTPrintf("usage: %s default\n", argv[0]); return 1; } for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "default")) ; else { RTPrintf("Unknown parameter '%s'\n", argv[i]); return 1; } } RTHTTP hHttp; char *pszBuf = NULL; PRTSTREAM CAFile = NULL; int rc = RTHttpCreate(&hHttp); // create certificate file if (RT_SUCCESS(rc)) rc = RTStrmOpen(CAFILE_NAME, "w+b", &CAFile); // fetch root CA certificate (new one, often avoided in cert chains by // using an intermediate cert which is signed by old root) if (RT_SUCCESS(rc)) rc = RTHttpGet(hHttp, "http://www.verisign.com/repository/roots/root-certificates/PCA-3G5.pem", &pszBuf); if (RT_SUCCESS(rc) && pszBuf) { uint8_t *abSha1; size_t cbSha1; uint8_t *abSha512; size_t cbSha512; size_t cbBuf = strlen(pszBuf); const uint8_t abSha1PCA3G5[] = { 0x4e, 0xb6, 0xd5, 0x78, 0x49, 0x9b, 0x1c, 0xcf, 0x5f, 0x58, 0x1e, 0xad, 0x56, 0xbe, 0x3d, 0x9b, 0x67, 0x44, 0xa5, 0xe5 }; const uint8_t abSha512PCA3G5[] = { 0xd4, 0xf8, 0x10, 0x54, 0x72, 0x77, 0x0a, 0x2d, 0xe3, 0x17, 0xb3, 0xcf, 0xed, 0x61, 0xae, 0x5c, 0x5d, 0x3e, 0xde, 0xa1, 0x41, 0x35, 0xb2, 0xdf, 0x60, 0xe2, 0x61, 0xfe, 0x3a, 0xc1, 0x66, 0xa3, 0x3c, 0x88, 0x54, 0x04, 0x4f, 0x1d, 0x13, 0x46, 0xe3, 0x8c, 0x06, 0x92, 0x9d, 0x70, 0x54, 0xc3, 0x44, 0xeb, 0x2c, 0x74, 0x25, 0x9e, 0x5d, 0xfb, 0xd2, 0x6b, 0xa8, 0x9a, 0xf0, 0xb3, 0x6a, 0x01 }; rc = RTHttpCertDigest(hHttp, pszBuf, cbBuf, &abSha1, &cbSha1, &abSha512, &cbSha512); if (RT_SUCCESS(rc)) { if (cbSha1 != sizeof(abSha1PCA3G5)) { RTPrintf("Wrong SHA1 digest size of PCA-3G5\n"); rc = VERR_INTERNAL_ERROR; } else if (memcmp(abSha1PCA3G5, abSha1, cbSha1)) { RTPrintf("Wrong SHA1 digest for PCA-3G5:\n" "Got: %.*Rhxs\n" "Expected: %.*Rhxs\n", cbSha1, abSha1, sizeof(abSha1PCA3G5), abSha1PCA3G5); rc = VERR_INTERNAL_ERROR; } if (cbSha512 != sizeof(abSha512PCA3G5)) { RTPrintf("Wrong SHA512 digest size of PCA-3G5\n"); rc = VERR_INTERNAL_ERROR; } else if (memcmp(abSha512PCA3G5, abSha512, cbSha512)) { RTPrintf("Wrong SHA512 digest for PCA-3G5:\n" "Got: %.*Rhxs\n" "Expected: %.*Rhxs\n", cbSha512, abSha512, sizeof(abSha512PCA3G5), abSha512PCA3G5); rc = VERR_INTERNAL_ERROR; } RTMemFree(abSha1); RTMemFree(abSha512); if (RT_SUCCESS(rc)) rc = RTStrmWrite(CAFile, pszBuf, cbBuf); if (RT_SUCCESS(rc)) rc = RTStrmWrite(CAFile, RTFILE_LINEFEED, strlen(RTFILE_LINEFEED)); } } if (pszBuf) { RTMemFree(pszBuf); pszBuf = NULL; } // fetch root CA certificate (old one, but still very widely used) if (RT_SUCCESS(rc)) rc = RTHttpGet(hHttp, "http://www.verisign.com/repository/roots/root-certificates/PCA-3.pem", &pszBuf); if (RT_SUCCESS(rc) && pszBuf) { uint8_t *abSha1; size_t cbSha1; uint8_t *abSha512; size_t cbSha512; size_t cbBuf = strlen(pszBuf); const uint8_t abSha1PCA3[] = { 0xa1, 0xdb, 0x63, 0x93, 0x91, 0x6f, 0x17, 0xe4, 0x18, 0x55, 0x09, 0x40, 0x04, 0x15, 0xc7, 0x02, 0x40, 0xb0, 0xae, 0x6b }; const uint8_t abSha512PCA3[] = { 0xbb, 0xf7, 0x8a, 0x19, 0x9f, 0x37, 0xee, 0xa2, 0xce, 0xc8, 0xaf, 0xe3, 0xd6, 0x22, 0x54, 0x20, 0x74, 0x67, 0x6e, 0xa5, 0x19, 0xb7, 0x62, 0x1e, 0xc1, 0x2f, 0xd5, 0x08, 0xf4, 0x64, 0xc4, 0xc6, 0xbb, 0xc2, 0xf2, 0x35, 0xe7, 0xbe, 0x32, 0x0b, 0xde, 0xb2, 0xfc, 0x44, 0x92, 0x5b, 0x8b, 0x9b, 0x77, 0xa5, 0x40, 0x22, 0x18, 0x12, 0xcb, 0x3d, 0x0a, 0x67, 0x83, 0x87, 0xc5, 0x45, 0xc4, 0x99 }; rc = RTHttpCertDigest(hHttp, pszBuf, cbBuf, &abSha1, &cbSha1, &abSha512, &cbSha512); if (RT_SUCCESS(rc)) { if (cbSha1 != sizeof(abSha1PCA3)) { RTPrintf("Wrong SHA1 digest size of PCA-3\n"); rc = VERR_INTERNAL_ERROR; } else if (memcmp(abSha1PCA3, abSha1, cbSha1)) { RTPrintf("Wrong SHA1 digest for PCA-3:\n" "Got: %.*Rhxs\n" "Expected: %.*Rhxs\n", cbSha1, abSha1, sizeof(abSha1PCA3), abSha1PCA3); rc = VERR_INTERNAL_ERROR; } if (cbSha512 != sizeof(abSha512PCA3)) { RTPrintf("Wrong SHA512 digest size of PCA-3\n"); rc = VERR_INTERNAL_ERROR; } else if (memcmp(abSha512PCA3, abSha512, cbSha512)) { RTPrintf("Wrong SHA512 digest for PCA-3:\n" "Got: %.*Rhxs\n" "Expected: %.*Rhxs\n", cbSha512, abSha512, sizeof(abSha512PCA3), abSha512PCA3); rc = VERR_INTERNAL_ERROR; } RTMemFree(abSha1); RTMemFree(abSha512); if (RT_SUCCESS(rc)) rc = RTStrmWrite(CAFile, pszBuf, cbBuf); if (RT_SUCCESS(rc)) rc = RTStrmWrite(CAFile, RTFILE_LINEFEED, strlen(RTFILE_LINEFEED)); } } if (pszBuf) { RTMemFree(pszBuf); pszBuf = NULL; } // close certificate file if (CAFile) { RTStrmClose(CAFile); CAFile = NULL; } if (RT_SUCCESS(rc)) rc = RTHttpSetCAFile(hHttp, CAFILE_NAME); if (RT_SUCCESS(rc)) rc = RTHttpGet(hHttp, "https://update.virtualbox.org/query.php?platform=LINUX_32BITS_UBUNTU_12_04&version=4.1.18", &pszBuf); if ( RT_FAILURE(rc) && rc != VERR_HTTP_COULDNT_CONNECT) cErrors++; if (RT_FAILURE(rc)) RTPrintf("Error code: %Rrc\n", rc); else RTPrintf("Success!\n"); RTPrintf("Got: %s\n", pszBuf); if (pszBuf) { RTMemFree(pszBuf); pszBuf = NULL; } RTHttpDestroy(hHttp); // RTFileDelete(CAFILE_NAME); return !!cErrors; }
int main(int argc, char **argv) { unsigned cErrors = 0; RTR3InitExe(argc, &argv, 0); if (argc <= 1) { RTPrintf("usage: %s default\n", argv[0]); return 1; } for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "default")) ; else { RTPrintf("Unknown parameter '%s'\n", argv[i]); return 1; } } RTHTTP hHttp; char *pszBuf = NULL; PRTSTREAM CAFile = NULL; int rc = RTHttpCreate(&hHttp); /* * Create the certificate file */ if (RT_SUCCESS(rc)) rc = RTStrmOpen(CAFILE_NAME, "w+b", &CAFile); if (RT_SUCCESS(rc)) { /* * The old way: */ /* * Fetch the root CA certificate (new one, often avoided in cert chains by * using an intermediate cert which is signed by old root) */ if (RT_SUCCESS(rc)) rc = RTHttpGetText(hHttp, "http://www.verisign.com/repository/roots/root-certificates/PCA-3G5.pem", &pszBuf); if (RT_SUCCESS(rc) && pszBuf) rc = extractPCA3G5(hHttp, CAFile, (uint8_t*)pszBuf, strlen(pszBuf)); else checkError(hHttp, rc, "PCA-3G5.pem"); if (pszBuf) { RTMemFree(pszBuf); pszBuf = NULL; } /* * Fetch the root CA certificate (old one, but still very widely used) */ if (RT_SUCCESS(rc)) rc = RTHttpGetText(hHttp, "http://www.verisign.com/repository/roots/root-certificates/PCA-3.pem", &pszBuf); if (RT_SUCCESS(rc) && pszBuf) rc = extractPCA3(hHttp, CAFile, (uint8_t*)pszBuf, strlen(pszBuf)); else checkError(hHttp, rc, "PCA-3.pem"); if (pszBuf) { RTMemFree(pszBuf); pszBuf = NULL; } RTPrintf("Old way: rc=%Rrc\n", rc); /* * The new way: */ void *pu8Buf; size_t cb; rc = RTHttpGetBinary(hHttp, "http://www.verisign.com/support/roots.zip", &pu8Buf, &cb); if (RT_SUCCESS(rc) && pu8Buf) { void *pvDecomp; size_t cbDecomp; rc = RTZipPkzipMemDecompress(&pvDecomp, &cbDecomp, pu8Buf, cb, "VeriSign Root Certificates/Generation 5 (G5) PCA/VeriSign Class 3 Public Primary Certification Authority - G5.pem"); if (RT_SUCCESS(rc)) { rc = extractPCA3G5(hHttp, CAFile, (uint8_t*)pvDecomp, cbDecomp); RTMemFree(pvDecomp); rc = RTZipPkzipMemDecompress(&pvDecomp, &cbDecomp, pu8Buf, cb, "VeriSign Root Certificates/Generation 1 (G1) PCAs/Class 3 Public Primary Certification Authority.pem"); if (RT_SUCCESS(rc)) { rc = extractPCA3(hHttp, CAFile, (uint8_t*)pvDecomp, cbDecomp); RTMemFree(pvDecomp); } } } else checkError(hHttp, rc, "roots.zip"); RTPrintf("New way: rc=%Rrc\n", rc); } /* * Close the certificate file */ if (CAFile) { RTStrmClose(CAFile); CAFile = NULL; } /* * Use it */ if (RT_SUCCESS(rc)) rc = RTHttpSetCAFile(hHttp, CAFILE_NAME); /* * Now try to do the actual HTTPS request */ if (RT_SUCCESS(rc)) rc = RTHttpGetText(hHttp, "https://update.virtualbox.org/query.php?platform=LINUX_32BITS_UBUNTU_12_04&version=4.1.18", &pszBuf); if ( RT_FAILURE(rc) && rc != VERR_HTTP_COULDNT_CONNECT) cErrors++; if (RT_FAILURE(rc)) RTPrintf("Error code: %Rrc\n", rc); else { RTPrintf("Success!\n"); RTPrintf("Got: %s\n", pszBuf); } if (pszBuf) { RTMemFree(pszBuf); pszBuf = NULL; } RTHttpDestroy(hHttp); // RTFileDelete(CAFILE_NAME); return !!cErrors; }
RTDECL(int) RTCrStoreCertExportAsPem(RTCRSTORE hStore, uint32_t fFlags, const char *pszFilename) { /* * Validate input. */ AssertReturn(!fFlags, VERR_INVALID_FLAGS); /* * Start the enumeration first as this validates the store handle. */ RTCRSTORECERTSEARCH Search; int rc = RTCrStoreCertFindAll(hStore, &Search); if (RT_SUCCESS(rc)) { /* * Open the file for writing. * * Note! We must use text and no binary here, because the base-64 API * below will use host specific EOL markers, not CRLF as PEM * specifies. */ PRTSTREAM hStrm; rc = RTStrmOpen(pszFilename, "w", &hStrm); if (RT_SUCCESS(rc)) { /* * Enumerate the certificates in the store, writing them out one by one. */ size_t cbBase64 = 0; char *pszBase64 = NULL; PCRTCRCERTCTX pCertCtx; while ((pCertCtx = RTCrStoreCertSearchNext(hStore, &Search)) != NULL) { const char *pszMarker; switch (pCertCtx->fFlags & RTCRCERTCTX_F_ENC_MASK) { case RTCRCERTCTX_F_ENC_X509_DER: pszMarker = "CERTIFICATE"; break; case RTCRCERTCTX_F_ENC_TAF_DER: pszMarker = "TRUST ANCHOR"; break; default: pszMarker = NULL; break; } if (pszMarker && pCertCtx->cbEncoded > 0) { /* * Do the base64 conversion first. */ size_t cchEncoded = RTBase64EncodedLength(pCertCtx->cbEncoded); if (cchEncoded < cbBase64) { /* likely */ } else { size_t cbNew = RT_ALIGN(cchEncoded + 64, 128); void *pvNew = RTMemRealloc(pszBase64, cbNew); if (!pvNew) { rc = VERR_NO_MEMORY; break; } cbBase64 = cbNew; pszBase64 = (char *)pvNew; } rc = RTBase64Encode(pCertCtx->pabEncoded, pCertCtx->cbEncoded, pszBase64, cbBase64, &cchEncoded); if (RT_FAILURE(rc)) break; RTStrmPrintf(hStrm, "-----BEGIN %s-----\n", pszMarker); RTStrmWrite(hStrm, pszBase64, cchEncoded); rc = RTStrmPrintf(hStrm, "\n-----END %s-----\n", pszMarker); if (RT_FAILURE(rc)) break; } RTCrCertCtxRelease(pCertCtx); } if (pCertCtx) RTCrCertCtxRelease(pCertCtx); RTMemFree(pszBase64); /* * Flush the output file before closing. */ int rc2 = RTStrmFlush(hStrm); if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) rc = rc2; RTStrmClearError(hStrm); /** @todo fix RTStrmClose... */ rc2 = RTStrmClose(hStrm); if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) rc = rc2; } int rc2 = RTCrStoreCertSearchDestroy(hStore, &Search); AssertRC(rc2); } return rc; }