bool DnDHGSendDataMessage::hasFileUrls(const char *pcszFormat, size_t cbMax) const { DO(("format %s\n", pcszFormat)); /* text/uri also an official variant? */ return RTStrNICmp(pcszFormat, "text/uri-list", cbMax) == 0 || RTStrNICmp(pcszFormat, "x-special/gnome-icon-list", cbMax) == 0; }
static int vbglR3DnDHGProcessSendDataMessage(uint32_t uClientId, uint32_t *puScreenId, char *pszFormat, uint32_t cbFormat, uint32_t *pcbFormatRecv, void **ppvData, uint32_t cbData, size_t *pcbDataRecv) { int rc = vbglR3DnDHGProcessSendDataMessages(uClientId, puScreenId, pszFormat, cbFormat, pcbFormatRecv, ppvData, cbData, pcbDataRecv); if (RT_SUCCESS(rc)) { /* Check if this is a uri-event */ if (RTStrNICmp(pszFormat, "text/uri-list", *pcbFormatRecv) == 0) rc = vbglR3DnDHGProcessURIMessages(uClientId, puScreenId, pszFormat, cbFormat, pcbFormatRecv, ppvData, cbData, pcbDataRecv); } return rc; }
GLboolean renderspu_SystemVBoxCreateWindow(VisualInfo *pVisInfo, GLboolean fShowIt, WindowInfo *pWinInfo) { CRASSERT(pVisInfo); CRASSERT(pWinInfo); /* VirtualBox is the only frontend which support 3D right now. */ char pszName[256]; if (RTProcGetExecutablePath(pszName, sizeof(pszName))) /* Check for VirtualBox and VirtualBoxVM */ if (RTStrNICmp(RTPathFilename(pszName), "VirtualBox", 10) != 0) return GL_FALSE; pWinInfo->visual = pVisInfo; pWinInfo->window = NULL; pWinInfo->nativeWindow = NULL; pWinInfo->currentCtx = NULL; #ifdef __LP64__ NativeNSViewRef pParentWin = (NativeNSViewRef)render_spu_parent_window_id; #else /* __LP64__ */ NativeNSViewRef pParentWin = (NativeNSViewRef)(uint32_t)render_spu_parent_window_id; #endif /* __LP64__ */ cocoaViewCreate(&pWinInfo->window, pWinInfo, pParentWin, pVisInfo->visAttribs); if (fShowIt) renderspu_SystemShowWindow(pWinInfo, fShowIt); return GL_TRUE; }
RTDECL(bool) RTUriIsSchemeMatch(const char *pszUri, const char *pszScheme) { AssertPtrReturn(pszUri, false); size_t const cchScheme = strlen(pszScheme); return RTStrNICmp(pszUri, pszScheme, cchScheme) == 0 && pszUri[cchScheme] == ':'; }
DECLINLINE(bool) tftpIsAcceptableOption(const char *pszOptionName) { int idxOptDesc = 0; AssertPtrReturn(pszOptionName, false); AssertReturn(RTStrNLen(pszOptionName,10) >= 4, false); AssertReturn(RTStrNLen(pszOptionName,10) < 8, false); for(idxOptDesc = 0; idxOptDesc < RT_ELEMENTS(g_TftpTransferFmtDesc); ++idxOptDesc) { if (!RTStrNICmp(pszOptionName, g_TftpTransferFmtDesc[idxOptDesc].pszName, 10)) return true; } for(idxOptDesc = 0; idxOptDesc < RT_ELEMENTS(g_TftpDesc); ++idxOptDesc) { if (!RTStrNICmp(pszOptionName, g_TftpDesc[idxOptDesc].pszName, 10)) return true; } return false; }
RTR3DECL(bool) RTUriHasScheme(const char *pszUri, const char *pszScheme) { bool fRes = false; char *pszTmp = RTUriScheme(pszUri); if (pszTmp) { fRes = RTStrNICmp(pszScheme, pszTmp, strlen(pszTmp)) == 0; RTStrFree(pszTmp); } return fRes; }
RTDECL(int) RTStrVersionCompare(const char *pszVer1, const char *pszVer2) { AssertPtr(pszVer1); AssertPtr(pszVer2); /* * Do a parallel parse of the strings. */ while (*pszVer1 || *pszVer2) { const char *pszBlock1 = pszVer1; size_t cchBlock1; int32_t iVal1; bool fNumeric1 = rtStrVersionParseBlock(&pszVer1, &iVal1, &cchBlock1); const char *pszBlock2 = pszVer2; size_t cchBlock2; int32_t iVal2; bool fNumeric2 = rtStrVersionParseBlock(&pszVer2, &iVal2, &cchBlock2); if (fNumeric1 && fNumeric2) { if (iVal1 != iVal2) return iVal1 < iVal2 ? -1 : 1; } else if ( fNumeric1 != fNumeric2 && ( fNumeric1 ? iVal1 == 0 && cchBlock2 == 0 : iVal2 == 0 && cchBlock1 == 0) ) { /*else: 1.0 == 1.0.0.0.0. */; } else if ( fNumeric1 != fNumeric2 && (fNumeric1 ? iVal1 : iVal2) < 0) { /* Pre-release indicators are smaller than all other strings. */ return fNumeric1 ? -1 : 1; } else { int iDiff = RTStrNICmp(pszBlock1, pszBlock2, RT_MIN(cchBlock1, cchBlock2)); if (!iDiff && cchBlock1 != cchBlock2) iDiff = cchBlock1 < cchBlock2 ? -1 : 1; if (iDiff) return iDiff < 0 ? -1 : 1; } } return 0; }
/* * This function returns index of option descriptor in passed descriptor array * @param piIdxOpt returned index value * @param paTftpDesc array of known Tftp descriptors * @param caTftpDesc size of array of tftp descriptors * @param pszOpt name of option */ DECLINLINE(int) tftpFindDesciptorIndexByName(int *piIdxOpt, PCTFTPOPTIONDESC paTftpDesc, int caTftpDesc, const char *pszOptName) { int rc = VINF_SUCCESS; int idxOption = 0; AssertReturn(piIdxOpt, VERR_INVALID_PARAMETER); AssertReturn(paTftpDesc, VERR_INVALID_PARAMETER); AssertReturn(pszOptName, VERR_INVALID_PARAMETER); for (idxOption = 0; idxOption < caTftpDesc; ++idxOption) { if (!RTStrNICmp(pszOptName, paTftpDesc[idxOption].pszName, 10)) { *piIdxOpt = idxOption; return rc; } } rc = VERR_NOT_FOUND; return rc; }
RTR3DECL(char *) RTUriFileNPath(const char *pszUri, uint32_t uFormat, size_t cchMax) { AssertPtrReturn(pszUri, NULL); size_t iPos1; size_t cbLen = RT_MIN(strlen(pszUri), cchMax); /* Find the end of the scheme. */ if (!rtUriFindSchemeEnd(pszUri, 0, cbLen, &iPos1)) return NULL; /* no URI */ else ++iPos1; /* Skip ':' */ /* Check that this is a file Uri */ if (RTStrNICmp(pszUri, "file:", iPos1) != 0) return NULL; size_t iPos2; size_t iPos3 = iPos1; /* Skip if no authority is found */ /* Find the start of the authority. */ if (rtUriCheckAuthorityStart(pszUri, iPos1, cbLen - iPos1, &iPos2)) { /* Find the end of the authority. If not found, then there is no path * component, cause the authority is the rest of the string. */ if (!rtUriFindAuthorityEnd(pszUri, iPos2, cbLen - iPos2, &iPos3)) return NULL; /* no path! */ } size_t iPos4; /* Find the start of the path */ if (rtUriCheckPathStart(pszUri, iPos3, cbLen - iPos3, &iPos4)) { uint32_t uFIntern = uFormat; /* Auto is based on the current OS. */ if (uFormat == URI_FILE_FORMAT_AUTO) #ifdef RT_OS_WINDOWS uFIntern = URI_FILE_FORMAT_WIN; #else /* RT_OS_WINDOWS */ uFIntern = URI_FILE_FORMAT_UNIX; #endif /* !RT_OS_WINDOWS */ if ( uFIntern != URI_FILE_FORMAT_UNIX && pszUri[iPos4] == '/') ++iPos4; /* Search for the end of the scheme. */ size_t iPos5 = cbLen; rtUriFindPathEnd(pszUri, iPos4, cbLen - iPos4, &iPos5); if (iPos5 > iPos4) /* Length check */ { char *pszPath = rtUriPercentDecodeN(&pszUri[iPos4], iPos5 - iPos4); if (uFIntern == URI_FILE_FORMAT_UNIX) return RTPathChangeToUnixSlashes(pszPath, true); else if (uFIntern == URI_FILE_FORMAT_WIN) return RTPathChangeToDosSlashes(pszPath, true); else { RTStrFree(pszPath); AssertMsgFailed(("Unknown uri file format %u", uFIntern)); return NULL; } } } return NULL; }
RTDECL(char *) RTStrIStr(const char *pszHaystack, const char *pszNeedle) { /* Any NULL strings means NULL return. (In the RTStrCmp tradition.) */ if (!pszHaystack) return NULL; if (!pszNeedle) return NULL; /* The empty string matches everything. */ if (!*pszNeedle) return (char *)pszHaystack; /* * The search strategy is to pick out the first char of the needle, fold it, * and match it against the haystack code point by code point. When encountering * a matching code point we use RTStrNICmp for the remainder (if any) of the needle. */ const char * const pszNeedleStart = pszNeedle; RTUNICP Cp0; RTStrGetCpEx(&pszNeedle, &Cp0); /* pszNeedle is advanced one code point. */ size_t const cchNeedle = strlen(pszNeedle); size_t const cchNeedleCp0= pszNeedle - pszNeedleStart; RTUNICP const Cp0Lower = RTUniCpToLower(Cp0); RTUNICP const Cp0Upper = RTUniCpToUpper(Cp0); if ( Cp0Lower == Cp0Upper && Cp0Lower == Cp0) { /* Cp0 is not a case sensitive char. */ for (;;) { RTUNICP Cp; RTStrGetCpEx(&pszHaystack, &Cp); if (!Cp) break; if ( Cp == Cp0 && !RTStrNICmp(pszHaystack, pszNeedle, cchNeedle)) return (char *)pszHaystack - cchNeedleCp0; } } else if ( Cp0Lower == Cp0 || Cp0Upper != Cp0) { /* Cp0 is case sensitive */ for (;;) { RTUNICP Cp; RTStrGetCpEx(&pszHaystack, &Cp); if (!Cp) break; if ( ( Cp == Cp0Upper || Cp == Cp0Lower) && !RTStrNICmp(pszHaystack, pszNeedle, cchNeedle)) return (char *)pszHaystack - cchNeedleCp0; } } else { /* Cp0 is case sensitive and folds to two difference chars. (paranoia) */ for (;;) { RTUNICP Cp; RTStrGetCpEx(&pszHaystack, &Cp); if (!Cp) break; if ( ( Cp == Cp0 || Cp == Cp0Upper || Cp == Cp0Lower) && !RTStrNICmp(pszHaystack, pszNeedle, cchNeedle)) return (char *)pszHaystack - cchNeedleCp0; } } return NULL; }
/* XXX: Having fIPv6 we might emprove adress verification comparing address length * with INET[6]_ADDRLEN */ int netPfStrToPf(const char *pcszStrPortForward, int fIPv6, PPORTFORWARDRULE pPfr) { char *pszName; int proto; char *pszHostAddr; char *pszGuestAddr; uint16_t u16HostPort; uint16_t u16GuestPort; bool fTcpProto = false; char *pszRawBegin = NULL; char *pszRaw = NULL; int idxRaw = 0; int cbToken = 0; int cbRaw = 0; int rc = VINF_SUCCESS; AssertPtrReturn(pcszStrPortForward, VERR_INVALID_PARAMETER); AssertPtrReturn(pPfr, VERR_INVALID_PARAMETER); RT_ZERO(*pPfr); pszHostAddr = &pPfr->szPfrHostAddr[0]; pszGuestAddr = &pPfr->szPfrGuestAddr[0]; pszName = &pPfr->szPfrName[0]; cbRaw = strlen(pcszStrPortForward); /* Minimal rule ":tcp:[]:0:[]:0" has got lenght 14 */ AssertReturn(cbRaw > 14, VERR_INVALID_PARAMETER); pszRaw = RTStrDup(pcszStrPortForward); AssertPtrReturn(pszRaw, VERR_NO_MEMORY); pszRawBegin = pszRaw; /* name */ if (pszRaw[idxRaw] == PF_FIELD_SEPARATOR) idxRaw = 1; /* begin of the next segment */ else { char *pszEndOfName = RTStrStr(pszRaw + 1, PF_STR_FIELD_SEPARATOR); if (!pszEndOfName) goto invalid_parameter; cbToken = (pszEndOfName) - pszRaw; /* don't take : into account */ /* XXX it's unacceptable to have only name entry in PF */ AssertReturn(cbToken < cbRaw, VERR_INVALID_PARAMETER); if ( cbToken < 0 || (size_t)cbToken >= PF_NAMELEN) goto invalid_parameter; RTStrCopy(pszName, RT_MIN((size_t)cbToken + 1, PF_NAMELEN), pszRaw); pszRaw += cbToken; /* move to separator */ cbRaw -= cbToken; } AssertReturn(pszRaw[0] == PF_FIELD_SEPARATOR, VERR_INVALID_PARAMETER); /* protocol */ pszRaw++; /* skip separator */ cbRaw--; idxRaw = 0; if ( ( (fTcpProto = (RTStrNICmp(pszRaw, "tcp", 3) == 0)) || RTStrNICmp(pszRaw, "udp", 3) == 0) && pszRaw[3] == PF_FIELD_SEPARATOR) { proto = (fTcpProto ? IPPROTO_TCP : IPPROTO_UDP); idxRaw = 3; } else goto invalid_parameter; pszRaw += idxRaw; cbRaw -= idxRaw; idxRaw = netPfStrAddressPortPairParse(pszRaw, cbRaw, pszHostAddr, INET6_ADDRSTRLEN, true, &u16HostPort); if (idxRaw < 0) return VERR_INVALID_PARAMETER; pszRaw += idxRaw; cbRaw -= idxRaw; Assert(pszRaw[0] == PF_FIELD_SEPARATOR); idxRaw = netPfStrAddressPortPairParse(pszRaw, cbRaw, pszGuestAddr, INET6_ADDRSTRLEN, false, &u16GuestPort); if (idxRaw < 0) goto invalid_parameter; /* XXX: fill the rule */ pPfr->fPfrIPv6 = fIPv6; pPfr->iPfrProto = proto; pPfr->u16PfrHostPort = u16HostPort; if (*pszGuestAddr == '\0') goto invalid_parameter; /* guest address should be defined */ pPfr->u16PfrGuestPort = u16GuestPort; Log(("name: %s\n" "proto: %d\n" "host address: %s\n" "host port: %d\n" "guest address: %s\n" "guest port:%d\n", pszName, proto, pszHostAddr, u16HostPort, pszGuestAddr, u16GuestPort)); RTStrFree(pszRawBegin); return VINF_SUCCESS; invalid_parameter: RTStrFree(pszRawBegin); if (pPfr) RT_ZERO(*pPfr); return VERR_INVALID_PARAMETER; }
/** * Searches for a long option. * * @returns Pointer to a matching option. * @param pszOption The alleged long option. * @param paOptions Option array. * @param cOptions Number of items in the array. * @param fFlags Init flags. */ static PCRTGETOPTDEF rtGetOptSearchLong(const char *pszOption, PCRTGETOPTDEF paOptions, size_t cOptions, uint32_t fFlags) { PCRTGETOPTDEF pOpt = paOptions; while (cOptions-- > 0) { if (pOpt->pszLong) { if ((pOpt->fFlags & RTGETOPT_REQ_MASK) != RTGETOPT_REQ_NOTHING) { /* * A value is required with the argument. We're trying to be * understanding here and will permit any of the following: * --long12:value, --long12=value, --long12 value, * --long:value, --long=value, --long value, * * If the option is index, then all trailing chars must be * digits. For error reporting reasons we also match where * there is no index. */ size_t cchLong = strlen(pOpt->pszLong); if ( !strncmp(pszOption, pOpt->pszLong, cchLong) || ( pOpt->fFlags & RTGETOPT_FLAG_ICASE && !RTStrNICmp(pszOption, pOpt->pszLong, cchLong))) { if (pOpt->fFlags & RTGETOPT_FLAG_INDEX) while (RT_C_IS_DIGIT(pszOption[cchLong])) cchLong++; if ( pszOption[cchLong] == '\0' || pszOption[cchLong] == ':' || pszOption[cchLong] == '=') return pOpt; } } else if (pOpt->fFlags & RTGETOPT_FLAG_INDEX) { /* * The option takes an index but no value. * As above, we also match where there is no index. */ size_t cchLong = strlen(pOpt->pszLong); if ( !strncmp(pszOption, pOpt->pszLong, cchLong) || ( pOpt->fFlags & RTGETOPT_FLAG_ICASE && !RTStrNICmp(pszOption, pOpt->pszLong, cchLong))) { while (RT_C_IS_DIGIT(pszOption[cchLong])) cchLong++; if (pszOption[cchLong] == '\0') return pOpt; } } else if ( !strcmp(pszOption, pOpt->pszLong) || ( pOpt->fFlags & RTGETOPT_FLAG_ICASE && !RTStrICmp(pszOption, pOpt->pszLong))) return pOpt; } pOpt++; } if (!(fFlags & RTGETOPTINIT_FLAGS_NO_STD_OPTS)) for (uint32_t i = 0; i < RT_ELEMENTS(g_aStdOptions); i++) if ( !strcmp(pszOption, g_aStdOptions[i].pszLong) || ( g_aStdOptions[i].fFlags & RTGETOPT_FLAG_ICASE && !RTStrICmp(pszOption, g_aStdOptions[i].pszLong))) return &g_aStdOptions[i]; return NULL; }
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; }
/** * Resolves imported functions, esp. system calls from NTDLL. * * This crap is necessary because there are sandboxing products out there that * will mess with system calls we make, just like any other wannabe userland * rootkit. Kudos to microsoft for not providing a generic system call hook API * in the kernel mode, which I guess is what forcing these kind of products to * do ugly userland hacks that doesn't really hold water. */ DECLHIDDEN(void) supR3HardenedWinInitImports(void) { /* * Find the DLLs we will be needing first (forwarders). */ for (uint32_t iDll = 0; iDll < RT_ELEMENTS(g_aSupNtImpDlls); iDll++) { supR3HardenedFindOrLoadModule(&g_aSupNtImpDlls[iDll]); if (g_aSupNtImpDlls[iDll].pbImageBase) supR3HardenedParseModule(&g_aSupNtImpDlls[iDll]); } /* * Resolve the functions. */ for (uint32_t iDll = 0; iDll < RT_ELEMENTS(g_aSupNtImpDlls); iDll++) for (uint32_t i = 0; i < g_aSupNtImpDlls[iDll].cImports; i++) { const char *pszForwarder = supR3HardenedResolveImport(&g_aSupNtImpDlls[iDll], &g_aSupNtImpDlls[iDll].paImports[i], false); if (pszForwarder) { const char *pszDot = strchr(pszForwarder, '.'); size_t cchDllName = pszDot - pszForwarder; SUPHNTIMPFUNC Tmp = g_aSupNtImpDlls[iDll].paImports[i]; Tmp.pszName = pszDot + 1; if (cchDllName == sizeof("ntdll") - 1 && RTStrNICmp(pszForwarder, RT_STR_TUPLE("ntdll")) == 0) supR3HardenedResolveImport(&g_aSupNtImpDlls[0], &Tmp, false); else if (cchDllName == sizeof("kernelbase") - 1 && RTStrNICmp(pszForwarder, RT_STR_TUPLE("kernelbase")) == 0) supR3HardenedResolveImport(&g_aSupNtImpDlls[1], &Tmp, false); else SUPHNTIMP_ERROR(false, 18, "supR3HardenedWinInitImports", kSupInitOp_Misc, VERR_MODULE_NOT_FOUND, "%ls: Failed to resolve forwarder '%s'.", g_aSupNtImpDlls[iDll].pwszName, pszForwarder); } } /* * Do system calls directly. */ supR3HardenedWinInitSyscalls(false); /* * Use the on disk image to avoid export table patching. Currently * ignoring errors here as can live normally without this step. */ for (uint32_t iDll = 0; iDll < RT_ELEMENTS(g_aSupNtImpDlls); iDll++) if (g_aSupNtImpDlls[iDll].cPatchedExports > 0) { PSUPHNTLDRCACHEENTRY pLdrEntry; int rc = supHardNtLdrCacheOpen(g_aSupNtImpDlls[iDll].pszName, &pLdrEntry); if (RT_SUCCESS(rc)) { uint8_t *pbBits; rc = supHardNtLdrCacheEntryGetBits(pLdrEntry, &pbBits, (uintptr_t)g_aSupNtImpDlls[iDll].pbImageBase, NULL, NULL, NULL /*pErrInfo*/); if (RT_SUCCESS(rc)) for (uint32_t i = 0; i < g_aSupNtImpDlls[iDll].cImports; i++) { RTLDRADDR uValue; rc = RTLdrGetSymbolEx(pLdrEntry->hLdrMod, pbBits, (uintptr_t)g_aSupNtImpDlls[iDll].pbImageBase, UINT32_MAX, g_aSupNtImpDlls[iDll].paImports[i].pszName, &uValue); if (RT_SUCCESS(rc)) *g_aSupNtImpDlls[iDll].paImports[i].ppfnImport = (PFNRT)(uintptr_t)uValue; } } } #if 0 /* Win7/32 ntdll!LdrpDebugFlags. */ *(uint8_t *)&g_aSupNtImpDlls[0].pbImageBase[0xdd770] = 0x3; #endif }
RTDECL(int) RTUriFilePathEx(const char *pszUri, uint32_t fPathStyle, char **ppszPath, size_t cbPath, size_t *pcchPath) { /* * Validate and adjust input. */ if (pcchPath) { AssertPtrReturn(pcchPath, VERR_INVALID_POINTER); *pcchPath = ~(size_t)0; } AssertPtrReturn(ppszPath, VERR_INVALID_POINTER); AssertReturn(!(fPathStyle & ~RTPATH_STR_F_STYLE_MASK) && fPathStyle != RTPATH_STR_F_STYLE_RESERVED, VERR_INVALID_FLAGS); if (fPathStyle == RTPATH_STR_F_STYLE_HOST) fPathStyle = RTPATH_STYLE; AssertPtrReturn(pszUri, VERR_INVALID_POINTER); /* * Check that this is a file URI. */ if (RTStrNICmp(pszUri, RT_STR_TUPLE("file:")) == 0) { /* likely */ } else return VERR_URI_NOT_FILE_SCHEME; /* * We may have a number of variations here, mostly thanks to * various windows software. First the canonical variations: * - file:///C:/Windows/System32/kernel32.dll * - file:///C|/Windows/System32/kernel32.dll * - file:///C:%5CWindows%5CSystem32%5Ckernel32.dll * - file://localhost/C:%5CWindows%5CSystem32%5Ckernel32.dll * - file://cifsserver.dev/systemshare%5CWindows%5CSystem32%5Ckernel32.dll * - file://cifsserver.dev:139/systemshare%5CWindows%5CSystem32%5Ckernel32.dll (not quite sure here, but whatever) * * Legacy variant without any slashes after the schema: * - file:C:/Windows/System32/kernel32.dll * - file:C|/Windows/System32%5Ckernel32.dll * - file:~/.bashrc * \--path-/ * * Legacy variant with exactly one slashes after the schema: * - file:/C:/Windows/System32%5Ckernel32.dll * - file:/C|/Windows/System32/kernel32.dll * - file:/usr/bin/env * \---path---/ * * Legacy variant with two slashes after the schema and an unescaped DOS path: * - file://C:/Windows/System32\kernel32.dll (**) * - file://C|/Windows/System32\kernel32.dll * \---path---------------------/ * -- authority, with ':' as non-working port separator * * Legacy variant with exactly four slashes after the schema and an unescaped DOS path. * - file:////C:/Windows\System32\user32.dll * * Legacy variant with four or more slashes after the schema and an unescaped UNC path: * - file:////cifsserver.dev/systemshare/System32%\kernel32.dll * - file://///cifsserver.dev/systemshare/System32\kernel32.dll * \---path--------------------------------------------/ * * The the two unescaped variants shouldn't be handed to rtUriParse, which * is good as we cannot actually handle the one marked by (**). So, handle * those two special when parsing. */ RTURIPARSED Parsed; int rc; size_t cSlashes = 0; while (pszUri[5 + cSlashes] == '/') cSlashes++; if ( (cSlashes == 2 || cSlashes == 4) && RT_C_IS_ALPHA(pszUri[5 + cSlashes]) && (pszUri[5 + cSlashes + 1] == ':' || pszUri[5 + cSlashes + 1] == '|')) { RT_ZERO(Parsed); /* RTURIPARSED_F_CONTAINS_ESCAPED_CHARS is now clear. */ Parsed.offPath = 5 + cSlashes; Parsed.cchPath = strlen(&pszUri[Parsed.offPath]); rc = RTStrValidateEncoding(&pszUri[Parsed.offPath]); } else if (cSlashes >= 4) { RT_ZERO(Parsed); Parsed.fFlags = cSlashes > 4 ? RTURIPARSED_F_CONTAINS_ESCAPED_CHARS : 0; Parsed.offPath = 5 + cSlashes - 2; Parsed.cchPath = strlen(&pszUri[Parsed.offPath]); rc = RTStrValidateEncoding(&pszUri[Parsed.offPath]); } else rc = rtUriParse(pszUri, &Parsed); if (RT_SUCCESS(rc)) { /* * Ignore localhost as hostname (it's implicit). */ static char const s_szLocalhost[] = "localhost"; if ( Parsed.cchAuthorityHost == sizeof(s_szLocalhost) - 1U && RTStrNICmp(&pszUri[Parsed.offAuthorityHost], RT_STR_TUPLE(s_szLocalhost)) == 0) { Parsed.cchAuthorityHost = 0; Parsed.cchAuthority = 0; } /* * Ignore leading path slash/separator if we detect a DOS drive letter * and we don't have a host name. */ if ( Parsed.cchPath >= 3 && Parsed.cchAuthorityHost == 0 && pszUri[Parsed.offPath] == '/' /* Leading path slash/separator. */ && ( pszUri[Parsed.offPath + 2] == ':' /* Colon after drive letter. */ || pszUri[Parsed.offPath + 2] == '|') /* Colon alternative. */ && RT_C_IS_ALPHA(pszUri[Parsed.offPath + 1]) ) /* Drive letter. */ { Parsed.offPath++; Parsed.cchPath--; } /* * Calculate the size of the encoded result. * * Since we're happily returning "C:/Windows/System32/kernel.dll" * style paths when the caller requested UNIX style paths, we will * return straight UNC paths too ("//cifsserver/share/dir/file"). */ size_t cchDecodedHost = 0; size_t cbResult; if (Parsed.fFlags & RTURIPARSED_F_CONTAINS_ESCAPED_CHARS) { cchDecodedHost = rtUriCalcDecodedLength(&pszUri[Parsed.offAuthorityHost], Parsed.cchAuthorityHost); cbResult = cchDecodedHost + rtUriCalcDecodedLength(&pszUri[Parsed.offPath], Parsed.cchPath) + 1; } else { cchDecodedHost = 0; cbResult = Parsed.cchAuthorityHost + Parsed.cchPath + 1; } if (pcchPath) *pcchPath = cbResult - 1; if (cbResult > 1) { /* * Prepare the necessary buffer space for the result. */ char *pszDst; char *pszFreeMe = NULL; if (!cbPath || *ppszPath == NULL) { cbPath = RT_MAX(cbPath, cbResult); *ppszPath = pszFreeMe = pszDst = RTStrAlloc(cbPath); AssertReturn(pszDst, VERR_NO_STR_MEMORY); } else if (cbResult <= cbPath) pszDst = *ppszPath; else return VERR_BUFFER_OVERFLOW; /* * Compose the result. */ if (Parsed.fFlags & RTURIPARSED_F_CONTAINS_ESCAPED_CHARS) { rc = rtUriDecodeIntoBuffer(&pszUri[Parsed.offAuthorityHost],Parsed.cchAuthorityHost, pszDst, cchDecodedHost + 1); Assert(RT_SUCCESS(rc) && strlen(pszDst) == cchDecodedHost); if (RT_SUCCESS(rc)) rc = rtUriDecodeIntoBuffer(&pszUri[Parsed.offPath], Parsed.cchPath, &pszDst[cchDecodedHost], cbResult - cchDecodedHost); Assert(RT_SUCCESS(rc) && strlen(pszDst) == cbResult - 1); } else { memcpy(pszDst, &pszUri[Parsed.offAuthorityHost], Parsed.cchAuthorityHost); memcpy(&pszDst[Parsed.cchAuthorityHost], &pszUri[Parsed.offPath], Parsed.cchPath); pszDst[cbResult - 1] = '\0'; } if (RT_SUCCESS(rc)) { /* * Convert colon DOS driver letter colon alternative. * We do this regardless of the desired path style. */ if ( RT_C_IS_ALPHA(pszDst[0]) && pszDst[1] == '|') pszDst[1] = ':'; /* * Fix slashes. */ if (fPathStyle == RTPATH_STR_F_STYLE_DOS) RTPathChangeToDosSlashes(pszDst, true); else if (fPathStyle == RTPATH_STR_F_STYLE_UNIX) RTPathChangeToUnixSlashes(pszDst, true); /** @todo not quite sure how this actually makes sense... */ else AssertFailed(); return rc; } /* bail out */ RTStrFree(pszFreeMe); } else rc = VERR_PATH_ZERO_LENGTH; } return rc; }