Changeset 57613 in vbox
- Timestamp:
- Sep 4, 2015 2:19:44 AM (9 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 2 deleted
- 21 edited
- 1 moved
-
include/iprt/crypto/store.h (modified) (6 diffs)
-
include/iprt/dir.h (modified) (1 diff)
-
include/iprt/err.h (modified) (2 diffs)
-
include/iprt/file.h (modified) (1 diff)
-
include/iprt/fs.h (modified) (2 diffs)
-
include/iprt/http.h (modified) (12 diffs)
-
include/iprt/mangling.h (modified) (5 diffs)
-
include/iprt/path.h (modified) (2 diffs)
-
src/VBox/Frontends/VirtualBox/src/net/UINetworkReply.cpp (modified) (19 diffs)
-
src/VBox/Runtime/Makefile.kmk (modified) (2 diffs)
-
src/VBox/Runtime/common/crypto/RTCrStoreCertAddFromFile.cpp (deleted)
-
src/VBox/Runtime/common/crypto/RTCrStoreCertAddFromStore.cpp (deleted)
-
src/VBox/Runtime/common/crypto/RTCrStoreCertAddWantedFromFishingExpedition.cpp (added)
-
src/VBox/Runtime/common/crypto/store-cert-add-basic.cpp (moved) (moved from trunk/src/VBox/Runtime/common/crypto/RTCrStoreCertAddFromDir.cpp ) (5 diffs)
-
src/VBox/Runtime/common/crypto/store.cpp (modified) (1 diff)
-
src/VBox/Runtime/common/crypto/x509-internal.h (modified) (1 diff)
-
src/VBox/Runtime/common/misc/http.cpp (modified) (20 diffs)
-
src/VBox/Runtime/common/path/RTPathEnsureTrailingSeparator.cpp (modified) (1 diff)
-
src/VBox/Runtime/common/path/RTPathGlob.cpp (added)
-
src/VBox/Runtime/generic/RTCrStoreCreateSnapshotById-generic.cpp (modified) (1 diff)
-
src/VBox/Runtime/generic/createtemp-generic.cpp (modified) (1 diff)
-
src/VBox/Runtime/generic/fs-stubs-generic.cpp (modified) (2 diffs)
-
src/VBox/Runtime/r3/nt/fs-nt.cpp (modified) (1 diff)
-
src/VBox/Runtime/r3/posix/fs-posix.cpp (modified) (2 diffs)
-
src/VBox/Runtime/r3/win/fs-win.cpp (modified) (1 diff)
-
src/VBox/Runtime/testcase/Makefile.kmk (modified) (2 diffs)
-
src/VBox/Runtime/testcase/tstRTPathGlob.cpp (added)
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/crypto/store.h
r57584 r57613 29 29 #include <iprt/crypto/x509.h> 30 30 #include <iprt/crypto/taf.h> 31 #include <iprt/sha.h> 31 32 32 33 … … 56 57 /** Pointer to a certificate store search. */ 57 58 typedef RTCRSTORECERTSEARCH *PRTCRSTORECERTSEARCH; 59 60 61 /** 62 * Info about a wanted certificate. 63 * 64 * All the search criteria are optional, but for a safe and efficient search 65 * it's recommended to specify all possible ones. If none are given, the search 66 * function will fail. 67 * 68 * For use with RTCrStoreCertAddFromFishingExpedition and others. 69 */ 70 typedef struct RTCRCERTWANTED 71 { 72 /** The certificate subject name, optional. 73 * The format is: "C=US, ST=California, L=Redwood Shores, O=Oracle Corporation" */ 74 const char *pszSubject; 75 /** The size of the DER (ASN.1) encoded certificate, optional (0). */ 76 uint16_t cbEncoded; 77 /** Set if abSha1 contains a valid SHA-1 fingerprint. */ 78 bool fSha1Fingerprint; 79 /** Set if abSha512 contains a valid SHA-512 fingerprint. */ 80 bool fSha512Fingerprint; 81 /** The SHA-1 fingerprint (of the encoded data). */ 82 uint8_t abSha1[RTSHA1_HASH_SIZE]; 83 /** The SHA-512 fingerprint (of the encoded data). */ 84 uint8_t abSha512[RTSHA512_HASH_SIZE]; 85 /** User pointer for directly associating other data with the entry. 86 * Subclassing the structure isn't possible because it's passed as an array. */ 87 void const *pvUser; 88 } RTCRCERTWANTED; 89 /** Pointer to a const certificat wanted structure. */ 90 typedef RTCRCERTWANTED const *PCRTCRCERTWANTED; 58 91 59 92 … … 162 195 PCRTSTRTUPLE paSuffixes, size_t cSuffixes, PRTERRINFO pErrInfo); 163 196 197 RTDECL(int) RTCrStoreCertAddWantedFromDir(RTCRSTORE hStore, uint32_t fFlags, 198 const char *pszDir, PCRTSTRTUPLE paSuffixes, size_t cSuffixes, 199 PCRTCRCERTWANTED paWanted, size_t cWanted, bool *pafFound, PRTERRINFO pErrInfo); 200 164 201 /** 165 202 * Adds certificates from the specified file. … … 183 220 RTDECL(int) RTCrStoreCertAddFromFile(RTCRSTORE hStore, uint32_t fFlags, const char *pszFilename, PRTERRINFO pErrInfo); 184 221 222 RTDECL(int) RTCrStoreCertAddWantedFromFile(RTCRSTORE hStore, uint32_t fFlags, const char *pszFilename, 223 PCRTCRCERTWANTED paWanted, size_t cWanted, bool *pafFound, PRTERRINFO pErrInfo); 224 185 225 /** 186 226 * Adds certificates from the specified java key store file. … … 229 269 */ 230 270 RTDECL(int) RTCrStoreCertAddFromStore(RTCRSTORE hStore, uint32_t fFlags, RTCRSTORE hStoreSrc); 271 272 RTDECL(int) RTCrStoreCertAddWantedFromStore(RTCRSTORE hStore, uint32_t fFlags, RTCRSTORE hSrcStore, 273 PCRTCRCERTWANTED paWanted, size_t cWanted, bool *pafFound); 274 275 RTDECL(int) RTCrStoreCertCheckWanted(RTCRSTORE hStore, PCRTCRCERTWANTED paWanted, size_t cWanted, bool *pafFound); 276 277 278 RTDECL(int) RTCrStoreCertAddWantedFromFishingExpedition(RTCRSTORE hStore, uint32_t fFlags, 279 PCRTCRCERTWANTED paWanted, size_t cWanted, 280 bool *pafFound, PRTERRINFO pErrInfo); 231 281 232 282 /** … … 240 290 */ 241 291 RTDECL(int) RTCrStoreCertExportAsPem(RTCRSTORE hStore, uint32_t fFlags, const char *pszFilename); 292 293 /** 294 * Counts the number of certificates in the store. 295 * 296 * @returns Certificate count on success, UINT32_MAX on failure. 297 * @param hStore The store which certificates should be counted. 298 */ 299 RTDECL(uint32_t) RTCrStoreCertCount(RTCRSTORE hStore); 242 300 243 301 RTDECL(int) RTCrStoreCertFindAll(RTCRSTORE hStore, PRTCRSTORECERTSEARCH pSearch); -
trunk/include/iprt/dir.h
r56291 r57613 236 236 * 237 237 * This is the RTFS_TYPE_MASK stuff shifted down 12 bits and 238 * identical to the BSD/LINUX ABI. 238 * identical to the BSD/LINUX ABI. See RTFS_TYPE_DIRENTRYTYPE_SHIFT. 239 239 */ 240 240 typedef enum RTDIRENTRYTYPE -
trunk/include/iprt/err.h
r57516 r57613 2478 2478 /** @name RTCrDigest status codes. 2479 2479 * @{ */ 2480 /** OpenSSL failed to initialize the digest algorithm context n. */2480 /** OpenSSL failed to initialize the digest algorithm context. */ 2481 2481 #define VERR_CR_DIGEST_OSSL_DIGEST_INIT_ERROR (-24200) 2482 2482 /** OpenSSL failed to clone the digest algorithm context. */ … … 2484 2484 /** @} */ 2485 2485 2486 /** @name RTPath status codes. 2487 * @{ */ 2488 /** Unknown glob variable. */ 2489 #define VERR_PATH_MATCH_UNKNOWN_VARIABLE (-24400) 2490 /** The specified glob variable must be first in the pattern. */ 2491 #define VERR_PATH_MATCH_VARIABLE_MUST_BE_FIRST (-24401) 2492 /** Hit unimplemented glob pattern matching feature. */ 2493 #define VERR_PATH_MATCH_FEATURE_NOT_IMPLEMENTED (-24402) 2494 /** Unknown character class in glob pattern. */ 2495 #define VERR_PATH_GLOB_UNKNOWN_CHAR_CLASS (-24403) 2496 /** @} */ 2497 2486 2498 /* SED-END */ 2487 2499 -
trunk/include/iprt/file.h
r57004 r57613 778 778 RTDECL(int) RTFileCreateTempSecure(char *pszTemplate); 779 779 780 /** 781 * Opens a new file with a unique name in the temp directory. 782 * 783 * @returns iprt status code. 784 * @param pszTemplate The file name template on input. The actual file 785 * name on success. Empty string on failure. 786 * @param fMode The mode to create the file with. Use 0600 unless 787 * you have reason not to. 788 * 789 * @remarks If actual control over the filename or location is required, we'll 790 * create an extended edition of this API. 791 */ 792 RTDECL(int) RTFileOpenTemp(PRTFILE pFile, char *pszFilename, size_t cbFilename, uint64_t fOpen); 793 780 794 781 795 /** @page pg_rt_filelock RT File locking API description -
trunk/include/iprt/fs.h
r56291 r57613 117 117 /** Type mask (S_IFMT). */ 118 118 #define RTFS_TYPE_MASK 0170000U 119 /** The shift count to convert between RTFS_TYPE_MASK and DIRENTRYTYPE. */ 120 #define RTFS_TYPE_DIRENTRYTYPE_SHIFT 12 119 121 120 122 /** Unix attribute mask. */ … … 593 595 RTR3DECL(int) RTFsQueryProperties(const char *pszFsPath, PRTFSPROPERTIES pProperties); 594 596 597 /** 598 * Checks if the given volume is case sensitive or not. 599 * 600 * This may be misleading in some cases as we lack the necessary APIs to query 601 * the information on some system (or choose not to use them) and are instead 602 * returning the general position on case sensitive file name of the system. 603 * 604 * @returns @c true if case sensitive, @c false if not. 605 * @param pszFsPath Path within the mounted file system. 606 */ 607 RTR3DECL(bool) RTFsIsCaseSensitive(const char *pszFsPath); 595 608 596 609 /** -
trunk/include/iprt/http.h
r57577 r57613 1 1 /* $Id$ */ 2 2 /** @file 3 * IPRT - Simple HTTP CommunicationAPI.3 * IPRT - Simple HTTP/HTTPS Client API. 4 4 */ 5 5 … … 32 32 RT_C_DECLS_BEGIN 33 33 34 /** @defgroup grp_rt_http RTHttp - Simple HTTP API34 /** @defgroup grp_rt_http RTHttp - Simple HTTP/HTTPS Client API 35 35 * @ingroup grp_rt 36 36 * @{ … … 38 38 39 39 /** @todo the following three definitions may move the iprt/types.h later. */ 40 /** RTHTTP interfacehandle. */40 /** HTTP/HTTPS client handle. */ 41 41 typedef R3PTRTYPE(struct RTHTTPINTERNAL *) RTHTTP; 42 /** Pointer to a RTHTTP interfacehandle. */43 typedef RTHTTP *PRTHTTP;44 /** Nil RTHTTP interfacehandle. */42 /** Pointer to a HTTP/HTTPS client handle. */ 43 typedef RTHTTP *PRTHTTP; 44 /** Nil HTTP/HTTPS client handle. */ 45 45 #define NIL_RTHTTP ((RTHTTP)0) 46 46 47 47 48 48 /** 49 * Creates a HTTP interface handle.49 * Creates a HTTP client instance. 50 50 * 51 51 * @returns iprt status code. … … 56 56 57 57 /** 58 * Destroys a HTTP interface handle.58 * Destroys a HTTP client instance. 59 59 * 60 60 * @param hHttp Handle to the HTTP interface. … … 80 80 * @returns iprt status code. 81 81 * 82 * @param hHttp HTTP interface handle.83 * @param p cszUrlURL.82 * @param hHttp The HTTP client instance. 83 * @param pszUrl URL. 84 84 * @param ppszNotUtf8 Where to return the poitner to the HTTP response. 85 85 * The string is of course zero terminated. Use … … 99 99 * containing embedded zero's, use RTHttpGetBinary instead. 100 100 */ 101 RTR3DECL(int) RTHttpGetText(RTHTTP hHttp, const char *p cszUrl, char **ppszNotUtf8);101 RTR3DECL(int) RTHttpGetText(RTHTTP hHttp, const char *pszUrl, char **ppszNotUtf8); 102 102 103 103 /** … … 113 113 * @returns iprt status code. 114 114 * 115 * @param hHttp HTTP interface handle.116 * @param p cszUrlThe URL.115 * @param hHttp The HTTP client instance. 116 * @param pszUrl The URL. 117 117 * @param ppvResponse Where to store the HTTP response data. Use 118 118 * RTHttpFreeResponse to free. 119 119 * @param pcb Size of the returned buffer. 120 120 */ 121 RTR3DECL(int) RTHttpGetBinary(RTHTTP hHttp, const char *p cszUrl, void **ppvResponse, size_t *pcb);121 RTR3DECL(int) RTHttpGetBinary(RTHTTP hHttp, const char *pszUrl, void **ppvResponse, size_t *pcb); 122 122 123 123 /** … … 133 133 * @returns iprt status code. 134 134 * 135 * @param hHttp HTTP interface handle.135 * @param hHttp The HTTP client instance. 136 136 * @param pszUrl The URL. 137 137 * @param pszDstFile The destination file name. … … 146 146 * @returns iprt status code. 147 147 * 148 * @param hHttp HTTP interface handle.148 * @param hHttp The HTTP client instance. 149 149 */ 150 150 RTR3DECL(int) RTHttpAbort(RTHTTP hHttp); … … 154 154 * 155 155 * @returns iprt status code. 156 * @param hHttp HTTP interface handle.156 * @param hHttp The HTTP client instance. 157 157 */ 158 158 RTR3DECL(int) RTHttpUseSystemProxySettings(RTHTTP hHttp); … … 163 163 * @returns iprt status code. 164 164 * 165 * @param hHttp HTTP interface handle.166 * @param p cszProxyURL of the proxy.165 * @param hHttp The HTTP client instance. 166 * @param pszProxy URL of the proxy. 167 167 * @param uPort port number of the proxy, use 0 for not specifying a port. 168 * @param p cszUserUsername, pass NULL for no authentication.169 * @param p cszPwdPassword, pass NULL for no authentication.170 */ 171 RTR3DECL(int) RTHttpSetProxy(RTHTTP hHttp, const char *p cszProxyUrl, uint32_t uPort,172 const char *p cszProxyUser, const char *pcszProxyPwd);168 * @param pszProxyUser Username, pass NULL for no authentication. 169 * @param pszProxyPwd Password, pass NULL for no authentication. 170 */ 171 RTR3DECL(int) RTHttpSetProxy(RTHTTP hHttp, const char *pszProxyUrl, uint32_t uPort, 172 const char *pszProxyUser, const char *pszProxyPwd); 173 173 174 174 /** … … 177 177 * @returns iprt status code. 178 178 * 179 * @param hHttp HTTP interface handle.179 * @param hHttp The HTTP client instance. 180 180 * @param cHeaders Number of custom headers. 181 * @param p cszHeadersArray of headers in form "foo: bar".181 * @param papszHeaders Array of headers in form "foo: bar". 182 182 */ 183 183 RTR3DECL(int) RTHttpSetHeaders(RTHTTP hHttp, size_t cHeaders, const char * const *papszHeaders); 184 184 185 185 /** 186 * Tells the HTTP client instance to gather system CA certificates into a 187 * temporary file and use it for HTTPS connections. 188 * 189 * This will be called automatically if a 'https' URL is presented and 190 * RTHttpSetCaFile hasn't been called yet. 191 * 192 * @returns IPRT status code. 193 * @param hHttp The HTTP client instance. 194 * @param pErrInfo Where to store additional error/warning information. 195 * Optional. 196 */ 197 RTR3DECL(int) RTHttpUseTemporaryCaFile(RTHTTP hHttp, PRTERRINFO pErrInfo); 198 199 /** 186 200 * Set a custom certification authority file, containing root certificates. 187 201 * 188 202 * @returns iprt status code. 189 203 * 190 * @param hHttp HTTP interface handle. 191 * @param pcszCAFile File name containing root certificates. 192 */ 193 RTR3DECL(int) RTHttpSetCAFile(RTHTTP hHttp, const char *pcszCAFile); 194 204 * @param hHttp The HTTP client instance. 205 * @param pszCAFile File name containing root certificates. 206 * 207 * @remarks For portable HTTPS support, use RTHttpGatherCaCertsInFile and pass 208 */ 209 RTR3DECL(int) RTHttpSetCAFile(RTHTTP hHttp, const char *pszCAFile); 210 211 /** 212 * Gathers certificates into a cryptographic (certificate) store 213 * 214 * This is a just a combination of RTHttpGatherCaCertsInStore and 215 * RTCrStoreCertExportAsPem. 216 * 217 * @returns IPRT status code. 218 * @param hStore The certificate store to gather the certificates 219 * in. 220 * @param fFlags RTHTTPGATHERCACERT_F_XXX. 221 * @param pErrInfo Where to store additional error/warning information. 222 * Optional. 223 */ 224 RTR3DECL(int) RTHttpGatherCaCertsInStore(RTCRSTORE hStore, uint32_t fFlags, PRTERRINFO pErrInfo); 225 226 /** 227 * Gathers certificates into a file that can be used with RTHttpSetCAFile. 228 * 229 * This is a just a combination of RTHttpGatherCaCertsInStore and 230 * RTCrStoreCertExportAsPem. 231 * 232 * @returns IPRT status code. 233 * @param pszCaFile The output file. 234 * @param fFlags RTHTTPGATHERCACERT_F_XXX. 235 * @param pErrInfo Where to store additional error/warning information. 236 * Optional. 237 */ 238 RTR3DECL(int) RTHttpGatherCaCertsInFile(const char *pszCaFile, uint32_t fFlags, PRTERRINFO pErrInfo); 195 239 196 240 /** @} */ -
trunk/include/iprt/mangling.h
r57584 r57613 603 603 # define RTFileOpenF RT_MANGLER(RTFileOpenF) 604 604 # define RTFileOpenV RT_MANGLER(RTFileOpenV) 605 # define RTFileOpenTemp RT_MANGLER(RTFileOpenTemp) 605 606 # define RTFileQueryFsSizes RT_MANGLER(RTFileQueryFsSizes) 606 607 # define RTFileQueryInfo RT_MANGLER(RTFileQueryInfo) … … 628 629 # define RTFileWriteAt RT_MANGLER(RTFileWriteAt) 629 630 # define RTFilesystemVfsFromFile RT_MANGLER(RTFilesystemVfsFromFile) 631 # define RTFsIsCaseSensitive RT_MANGLER(RTFsIsCaseSensitive) 630 632 # define RTFsQueryProperties RT_MANGLER(RTFsQueryProperties) 631 633 # define RTFsQuerySerial RT_MANGLER(RTFsQuerySerial) … … 1061 1063 # define RTPathGetCurrentOnDrive RT_MANGLER(RTPathGetCurrentOnDrive) 1062 1064 # define RTPathGetMode RT_MANGLER(RTPathGetMode) 1065 # define RTPathGlob RT_MANGLER(RTPathGlob) 1066 # define RTPathGlobFree RT_MANGLER(RTPathGlobFree) 1063 1067 # define RTPathHasSuffix RT_MANGLER(RTPathHasSuffix) 1064 1068 # define RTPathHasPath RT_MANGLER(RTPathHasPath) … … 2892 2896 # define RTCrStoreCertAddEncoded RT_MANGLER(RTCrStoreCertAddEncoded) 2893 2897 # define RTCrStoreCertByIssuerAndSerialNo RT_MANGLER(RTCrStoreCertByIssuerAndSerialNo) 2898 # define RTCrStoreCertCount RT_MANGLER(RTCrStoreCertCount) 2894 2899 # define RTCrStoreCertFindAll RT_MANGLER(RTCrStoreCertFindAll) 2895 2900 # define RTCrStoreCertFindBySubjectOrAltSubjectByRfc5280 RT_MANGLER(RTCrStoreCertFindBySubjectOrAltSubjectByRfc5280) … … 2907 2912 # define RTCrStoreCertAddFromJavaKeyStoreInMem RT_MANGLER(RTCrStoreCertAddFromJavaKeyStoreInMem) 2908 2913 # define RTCrStoreCertAddFromStore RT_MANGLER(RTCrStoreCertAddFromStore) 2914 # define RTCrStoreCertAddWantedFromDir RT_MANGLER(RTCrStoreCertAddWantedFromDir) 2915 # define RTCrStoreCertAddWantedFromFile RT_MANGLER(RTCrStoreCertAddWantedFromFile) 2916 # define RTCrStoreCertAddWantedFromStore RT_MANGLER(RTCrStoreCertAddWantedFromStore) 2917 # define RTCrStoreCertAddWantedFromFishingExpedition RT_MANGLER(RTCrStoreCertAddWantedFromFishingExpedition) 2918 # define RTCrStoreCertCheckWanted RT_MANGLER(RTCrStoreCertCheckWanted) 2909 2919 # define RTCrStoreCertExportAsPem RT_MANGLER(RTCrStoreCertExportAsPem) 2910 2920 # define RTErrInfoAdd RT_MANGLER(RTErrInfoAdd) -
trunk/include/iprt/path.h
r57572 r57613 601 601 * The first component is the root, volume or UNC specifier, if present. Use 602 602 * RTPATH_PROP_HAS_ROOT_SPEC() on RTPATHPARSED::fProps to determine its 603 * pre cense.603 * presence. 604 604 * 605 605 * Other than the root component, no component will include directory separators … … 1172 1172 RTDECL(int) RTPathTemp(char *pszPath, size_t cchPath); 1173 1173 1174 1175 /** 1176 * RTPathGlobl result entry. 1177 */ 1178 typedef struct RTPATHGLOBENTRY 1179 { 1180 /** List entry. */ 1181 struct RTPATHGLOBENTRY *pNext; 1182 /** RTDIRENTRYTYPE value. */ 1183 uint8_t uType; 1184 /** Unused explicit padding. */ 1185 uint8_t bUnused; 1186 /** The length of the path. */ 1187 uint16_t cchPath; 1188 /** The path to the file (variable length). */ 1189 char szPath[1]; 1190 } RTPATHGLOBENTRY; 1191 /** Pointer to a GLOB result entry. */ 1192 typedef RTPATHGLOBENTRY *PRTPATHGLOBENTRY; 1193 /** Pointer to a const GLOB result entry. */ 1194 typedef RTPATHGLOBENTRY const *PCRTPATHGLOBENTRY; 1195 /** Pointer to a GLOB result entry pointer. */ 1196 typedef PCRTPATHGLOBENTRY *PPCRTPATHGLOBENTRY; 1197 1198 /** 1199 * Performs wildcard expansion on a path pattern. 1200 * 1201 * @returns IPRT status code. 1202 * 1203 * @param pszPattern The pattern to expand. 1204 * @param fFlags RTPATHGLOB_F_XXX. 1205 * @param ppHead Where to return the head of the result list. This 1206 * is always set to NULL on failure. 1207 * @param pcResults Where to return the number of the result. Optional. 1208 */ 1209 RTDECL(int) RTPathGlob(const char *pszPattern, uint32_t fFlags, PPCRTPATHGLOBENTRY ppHead, uint32_t *pcResults); 1210 1211 /** @name RTPATHGLOB_F_XXX - RTPathGlob flags 1212 * @{ */ 1213 /** Case insensitive. */ 1214 #define RTPATHGLOB_F_IGNORE_CASE RT_BIT_32(0) 1215 /** Do not expand \${EnvOrSpecialVariable} in the pattern. */ 1216 #define RTPATHGLOB_F_NO_VARIABLES RT_BIT_32(1) 1217 /** Do not interpret a leading tilde as a home directory reference. */ 1218 #define RTPATHGLOB_F_NO_TILDE RT_BIT_32(2) 1219 /** Only return the first match. */ 1220 #define RTPATHGLOB_F_FIRST_ONLY RT_BIT_32(3) 1221 /** Only match directories (implied if pattern ends with slash). */ 1222 #define RTPATHGLOB_F_ONLY_DIRS RT_BIT_32(4) 1223 /** Do not match directories. (Can't be used with RTPATHGLOB_F_ONLY_DIRS or 1224 * patterns containing a trailing slash.) */ 1225 #define RTPATHGLOB_F_NO_DIRS RT_BIT_32(5) 1226 /** Disables the '**' wildcard pattern for matching zero or more subdirs. */ 1227 #define RTPATHGLOB_F_NO_STARSTAR RT_BIT_32(6) 1228 /** Mask of valid flags. */ 1229 #define RTPATHGLOB_F_MASK UINT32_C(0x0000007f) 1230 /** @} */ 1231 1232 /** 1233 * Frees the results produced by RTPathGlob. 1234 * 1235 * @param pHead What RTPathGlob returned. NULL ignored. 1236 */ 1237 RTDECL(void) RTPathGlobFree(PCRTPATHGLOBENTRY pHead); 1238 1239 1174 1240 /** 1175 1241 * Query information about a file system object. -
trunk/src/VBox/Frontends/VirtualBox/src/net/UINetworkReply.cpp
r57581 r57613 72 72 73 73 private: 74 /** @name Helpers - HTTP stuff 75 * @{ */ 76 int applyProxyRules(); 77 int applyHttpsCertificates(); 78 int applyRawHeaders(); 79 int performMainRequest(); 80 /** @} */ 81 82 /* Helper: Main thread runner: */ 83 void run(); 84 74 85 /** Info about wanted certificate. */ 75 86 typedef struct CERTINFO 76 87 { 77 /** The certificate subject name. */78 const char *pszSubject;79 /** The size of the DER (ASN.1) encoded certificate. */80 uint16_t cbEncoded;81 88 /** Gives the s_aCerts index this certificate is an alternative edition of, 82 89 * UINT8_MAX if no alternative. This is a complication caused by VeriSign … … 87 94 /** Set if mandatory. */ 88 95 bool fMandatory; 89 /** The SHA-1 fingerprint (of the encoded data). */90 uint8_t abSha1[RTSHA1_HASH_SIZE];91 /** The SHA-512 fingerprint (of the encoded data). */92 uint8_t abSha512[RTSHA512_HASH_SIZE];93 96 /** Filename in the zip file we download (PEM). */ 94 97 const char *pszZipFile; … … 97 100 } CERTINFO; 98 101 99 100 /** @name Helpers - HTTP stuff101 * @{ */102 int applyProxyRules();103 int applyHttpsCertificates();104 int applyRawHeaders();105 int performMainRequest();106 /** @} */107 108 /* Helper: Main thread runner: */109 void run();110 111 102 /** @name Static helpers for HTTP and Certificates handling. 112 103 * @{ */ … … 114 105 static int applyProxyRules(RTHTTP hHttp, const QString &strHostName, int iPort); 115 106 static int applyRawHeaders(RTHTTP hHttp, const QList<QByteArray> &headers, const QNetworkRequest &request); 116 static bool allCertsFound(uint64_t fFoundCerts, bool fOnlyMandatory);117 static uint64_t certEntryFoundMask(uint32_t iCert);118 static bool checkCertificatesInFile(const char *pszCaCertFile);119 static bool checkCertificatesInStore(RTCRSTORE hStore, unsigned *pcCertificates = NULL);120 static int downloadCertificates(RTHTTP hHttp, const char *pszCaCertFile);107 static unsigned countCertsFound(bool const *pafFoundCerts); 108 static bool areAllCertsFound(bool const *pafFoundCerts, bool fOnlyMandatory); 109 static void refreshCertificates(RTHTTP hHttp, RTCRSTORE hOldStore, bool *pafFoundCerts, const char *pszCaCertFile); 110 static void downloadMissingCertificates(RTCRSTORE hNewStore, bool *pafNewFoundCerts, RTHTTP hHttp, 111 PRTERRINFOSTATIC pStaticErrInfo); 121 112 static int convertVerifyAndAddPemCertificateToStore(RTCRSTORE hStore, void const *pvResponse, 122 size_t cbResponse, const CERTINFO *pCertInfo); 123 static int retrieveCertificatesFromSystem(const char *pszCaCertFile); 113 size_t cbResponse, PCRTCRCERTWANTED pWantedCert); 124 114 /** @} */ 125 115 … … 135 125 136 126 static const QString s_strCertificateFileName; 137 static const CERTINFO s_aCerts[3]; 127 static const RTCRCERTWANTED s_aCerts[3]; 128 static const CERTINFO s_CertInfoPcaCls3Gen1Md2; 129 static const CERTINFO s_CertInfoPcaCls3Gen1Sha1; 130 static const CERTINFO s_CertInfoPcaCls3Gen5; 131 }; 132 133 /*static*/ const UINetworkReplyPrivateThread::CERTINFO UINetworkReplyPrivateThread::s_CertInfoPcaCls3Gen1Sha1 = 134 { 135 /*.iAlternativeTo =*/ 1, 136 /*.fMandatory =*/ false, 137 /*.pszZipFile =*/ 138 "VeriSign Root Certificates/Generation 1 (G1) PCAs/Class 3 Public Primary Certification Authority.pem", 139 /*.apszUrls[3] =*/ 140 { 141 "http://www.symantec.com/content/en/us/enterprise/verisign/roots/Class-3-Public-Primary-Certification-Authority.pem", 142 "http://www.verisign.com/repository/roots/root-certificates/PCA-3.pem", /* dead */ 143 NULL, 144 "http://update.virtualbox.org/cacerts-symantec-PCA-3-pem-has-gone-missing-again" /* attention getter */ 145 } 146 }; 147 148 /*static*/ const UINetworkReplyPrivateThread::CERTINFO UINetworkReplyPrivateThread::s_CertInfoPcaCls3Gen1Md2 = 149 { 150 /*.iAlternativeTo =*/ 0, 151 /*.fMandatory =*/ false, 152 /*.pszZipFile =*/ NULL, 153 /*.apszUrls[3] =*/ { NULL, NULL, NULL }, 154 }; 155 156 /*static*/ const UINetworkReplyPrivateThread::CERTINFO UINetworkReplyPrivateThread::s_CertInfoPcaCls3Gen5 = 157 { 158 /*.iAlternativeTo =*/ UINT8_MAX, 159 /*.fMandatory =*/ true, 160 /*.pszZipFile =*/ 161 "VeriSign Root Certificates/Generation 5 (G5) PCA/VeriSign Class 3 Public Primary Certification Authority - G5.pem", 162 /*.apszUrls[3] =*/ 163 { 164 "http://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem", 165 "http://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class-3-Public-Primary-Certification-Authority-G5.pem", /* (in case they correct above typo) */ 166 "http://www.verisign.com/repository/roots/root-certificates/PCA-3G5.pem", /* dead */ 167 "http://update.virtualbox.org/cacerts-symantec-PCA-3G5-pem-has-gone-missing-again" /* attention getter */ 168 } 138 169 }; 139 170 … … 141 172 /** 142 173 * Details on the certificates we are after. 174 * The pvUser member points to a UINetworkReplyPrivateThread::CERTINFO. 143 175 */ 144 /* static */ const UINetworkReplyPrivateThread::CERTINFOUINetworkReplyPrivateThread::s_aCerts[3] =176 /* static */ const RTCRCERTWANTED UINetworkReplyPrivateThread::s_aCerts[3] = 145 177 { 146 178 /*[0] =*/ /* The reissued version with the SHA-1 signature. */ 147 179 /** @todo r=bird: Why do we need this certificate? Neither update.virtualbox.org nor www.virtualbox.org uses it... ElCapitan doesn't ship this. */ 148 180 { 149 /*.pszSubject =*/ 150 "C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority", 151 /*.cbEncoded =*/ 0x240, 152 /*.iAlternativeTo =*/ 1, 153 /*.fMandatory =*/ false, 154 /*.abSha1 =*/ 181 /*.pszSubject =*/ "C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority", 182 /*.cbEncoded =*/ 0x240, 183 /*.Sha1Fingerprint =*/ true, 184 /*.Sha512Fingerprint =*/ true, 185 /*.abSha1 =*/ 155 186 { 156 187 0xa1, 0xdb, 0x63, 0x93, 0x91, 0x6f, 0x17, 0xe4, 0x18, 0x55, 157 188 0x09, 0x40, 0x04, 0x15, 0xc7, 0x02, 0x40, 0xb0, 0xae, 0x6b 158 189 }, 159 /*.abSha512 =*/190 /*.abSha512 =*/ 160 191 { 161 192 0xbb, 0xf7, 0x8a, 0x19, 0x9f, 0x37, 0xee, 0xa2, … … 168 199 0x0a, 0x67, 0x83, 0x87, 0xc5, 0x45, 0xc4, 0x99 169 200 }, 170 /*.pszZipFile =*/ 171 "VeriSign Root Certificates/Generation 1 (G1) PCAs/Class 3 Public Primary Certification Authority.pem", 172 /*.apszUrls[3] =*/ 173 { 174 "http://www.symantec.com/content/en/us/enterprise/verisign/roots/Class-3-Public-Primary-Certification-Authority.pem", 175 "http://www.verisign.com/repository/roots/root-certificates/PCA-3.pem", /* dead */ 176 NULL, 177 "http://update.virtualbox.org/cacerts-symantec-PCA-3-pem-has-gone-missing-again" /* attention getter */ 178 }, 201 /*.pvUser */ &UINetworkReplyPrivateThread::s_CertInfoPcaCls3Gen1Sha1 179 202 }, 180 203 /*[1] =*/ /* The original version with the MD2 signature. */ 181 204 { 182 /*.pszSubject =*/ 183 "C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority", 184 /*.cbEncoded =*/ 0x240, 185 /*.iAlternativeTo =*/ 0, 186 /*.fMandatory =*/ false, 187 /*.abSha1 =*/ 205 /*.pszSubject =*/ "C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority", 206 /*.cbEncoded =*/ 0x240, 207 /*.Sha1Fingerprint =*/ true, 208 /*.Sha512Fingerprint =*/ true, 209 /*.abSha1 =*/ 188 210 { 189 211 0x74, 0x2c, 0x31, 0x92, 0xe6, 0x07, 0xe4, 0x24, 0xeb, 0x45, 190 212 0x49, 0x54, 0x2b, 0xe1, 0xbb, 0xc5, 0x3e, 0x61, 0x74, 0xe2 191 213 }, 192 /*.abSha512 =*/214 /*.abSha512 =*/ 193 215 { 194 216 0x7c, 0x2f, 0x94, 0x22, 0x5f, 0x67, 0x98, 0x89, … … 201 223 0xc8, 0x0c, 0x5a, 0xe7, 0x8b, 0x33, 0xf2, 0xaa 202 224 }, 203 /*.pszZipFile =*/ NULL, 204 /*.apszUrls[3] =*/ { NULL, NULL, NULL }, 225 /*.pvUser */ &UINetworkReplyPrivateThread::s_CertInfoPcaCls3Gen1Md2 205 226 }, 206 227 /*[2] =*/ 207 228 { 208 /*.pszSubject =*/229 /*.pszSubject =*/ 209 230 "C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 2006 VeriSign, Inc. - For authorized use only, " 210 231 "CN=VeriSign Class 3 Public Primary Certification Authority - G5", 211 /*.cbEncoded =*/0x4d7,212 /*. iAlternativeTo =*/ UINT8_MAX,213 /*. fMandatory =*/true,214 /*.abSha1 =*/232 /*.cbEncoded =*/ 0x4d7, 233 /*.Sha1Fingerprint =*/ true, 234 /*.Sha512Fingerprint =*/ true, 235 /*.abSha1 =*/ 215 236 { 216 237 0x4e, 0xb6, 0xd5, 0x78, 0x49, 0x9b, 0x1c, 0xcf, 0x5f, 0x58, 217 238 0x1e, 0xad, 0x56, 0xbe, 0x3d, 0x9b, 0x67, 0x44, 0xa5, 0xe5 218 239 }, 219 /*.abSha512 =*/240 /*.abSha512 =*/ 220 241 { 221 242 0xd4, 0xf8, 0x10, 0x54, 0x72, 0x77, 0x0a, 0x2d, … … 228 249 0xd2, 0x6b, 0xa8, 0x9a, 0xf0, 0xb3, 0x6a, 0x01 229 250 }, 230 /*.pszZipFile =*/ 231 "VeriSign Root Certificates/Generation 5 (G5) PCA/VeriSign Class 3 Public Primary Certification Authority - G5.pem", 232 /*.apszUrls[3] =*/ 233 { 234 "http://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem", 235 "http://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class-3-Public-Primary-Certification-Authority-G5.pem", /* (in case they correct above typo) */ 236 "http://www.verisign.com/repository/roots/root-certificates/PCA-3G5.pem", /* dead */ 237 "http://update.virtualbox.org/cacerts-symantec-PCA-3G5-pem-has-gone-missing-again" /* attention getter */ 238 }, 251 /*.pvUser */ &UINetworkReplyPrivateThread::s_CertInfoPcaCls3Gen5 239 252 }, 240 253 }; … … 288 301 289 302 /* 290 * Check that the certificate file is recent and contains the necessary certificates. 303 * Check the state of our CA certificate file, it's one of the following: 304 * - Missing, recreate from scratch (= refresh). 305 * - Everything is there and it is less than 28 days old, do nothing. 306 * - Everything is there but it's older than 28 days, refresh. 307 * - Missing certificates and is older than 1 min, refresh. 308 * 309 * Start by creating a store for loading the current state into, as we'll 310 * be need that for the refresh. 291 311 */ 292 int rc; 293 if (checkCertificatesInFile(pszCaCertFile)) 294 rc = RTHttpSetCAFile(m_hHttp, pszCaCertFile); 295 else 296 { 312 RTCRSTORE hCurStore = NIL_RTCRSTORE; 313 int rc = RTCrStoreCreateInMem(&hCurStore, 256); 314 if (RT_SUCCESS(rc)) 315 { 316 bool fRefresh = true; 317 bool afCertsFound[RT_ELEMENTS(s_aCerts)]; 318 RT_ZERO(afCertsFound); 319 297 320 /* 298 * Need to create/update the CA certificate file. Try see if the necessary 299 * certificates are to be found somewhere on the local system, then fall back 300 * to downloading them. 321 * Load the file if it exists. 322 * 323 * To effect regular updates, we need the modification date of the file, 324 * so we use RTPathQueryInfoEx here and not RTFileExists. 301 325 */ 302 rc = retrieveCertificatesFromSystem(pszCaCertFile); 303 if (RT_FAILURE(rc)) 304 rc = downloadCertificates(m_hHttp, pszCaCertFile); 305 326 RTFSOBJINFO Info; 327 int rc = RTPathQueryInfoEx(pszCaCertFile, &Info, RTFSOBJATTRADD_NOTHING, RTPATH_F_FOLLOW_LINK); 328 if ( RT_SUCCESS(rc) 329 && RTFS_IS_FILE(Info.Attr.fMode)) 330 { 331 RTERRINFOSTATIC StaticErrInfo; 332 rc = RTCrStoreCertAddFromFile(hCurStore, RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR, pszCaCertFile, 333 RTErrInfoInitStatic(&StaticErrInfo)); 334 if (RTErrInfoIsSet(&StaticErrInfo.Core)) 335 LogRel(("checkCertificates: %s\n", StaticErrInfo.Core.pszMsg)); 336 else 337 AssertRC(rc); 338 339 /* 340 * Scan the store the for certificates we need, then see what we 341 * need to do wrt file age. 342 */ 343 rc = RTCrStoreCertCheckWanted(hCurStore, s_aCerts, RT_ELEMENTS(s_aCerts), afCertsFound); 344 AssertRC(rc); 345 RTTIMESPEC RefreshAge; 346 uint32_t cSecRefresh = rc == VINF_SUCCESS ? 28 * RT_SEC_1DAY /* all found */ : 60 /* stuff missing */; 347 fRefresh = RTTimeSpecCompare(&Info.ModificationTime, RTTimeSpecSubSeconds(RTTimeNow(&RefreshAge), cSecRefresh)) <= 0; 348 } 349 350 /* 351 * Refresh the file if necessary. 352 */ 353 if (fRefresh) 354 refreshCertificates(m_hHttp, hCurStore, afCertsFound, pszCaCertFile); 355 356 RTCrStoreRelease(hCurStore); 357 358 /* 359 * Final verdict. 360 */ 361 if (areAllCertsFound(afCertsFound, true /*fOnlyMandatory*/)) 362 rc = VINF_SUCCESS; 363 else 364 rc = VERR_NOT_FOUND; /** @todo r=bird: Why not try and let RTHttpGet* bitch if the necessary certs are missing? */ 365 366 /* 367 * Set our custom CA file. 368 */ 306 369 if (RT_SUCCESS(rc)) 307 370 rc = RTHttpSetCAFile(m_hHttp, pszCaCertFile); 308 371 } 309 310 372 return rc; 311 373 } … … 426 488 427 489 /** 428 * Checks if the certificates we desire are all present in the given file, and 429 * that the file is recent enough (not for downloaded certs). 490 * Counts the number of certificates found in a search result array. 430 491 * 431 * @returns true if fine, false if not. 432 * @param pszCaCertFile The path to the certificate file. 492 * @returns Number of wanted certifcates we've found. 493 * @param pafFoundCerts Array parallel to s_aCerts with the status of 494 * each wanted certificate. 433 495 */ 434 /*static*/ bool 435 UINetworkReplyPrivateThread::checkCertificatesInFile(const char *pszCaCertFile) 436 { 437 bool fFoundCerts = false; 438 439 /* 440 * Check whether the file exists. 441 */ 442 RTFSOBJINFO Info; 443 int rc = RTPathQueryInfoEx(pszCaCertFile, &Info, RTFSOBJATTRADD_NOTHING, RTPATH_F_FOLLOW_LINK); 444 if ( RT_SUCCESS(rc) 445 && RTFS_IS_FILE(Info.Attr.fMode)) 446 { 447 /* 448 * Load the CA certificate file into a store and use 449 * checkCertificatesInStore to do the real work. 450 */ 451 RTCRSTORE hStore; 452 int rc = RTCrStoreCreateInMem(&hStore, 256); 453 if (RT_SUCCESS(rc)) 454 { 455 RTERRINFOSTATIC StaticErrInfo; 456 rc = RTCrStoreCertAddFromFile(hStore, RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR, pszCaCertFile, 457 RTErrInfoInitStatic(&StaticErrInfo)); 458 if (RTErrInfoIsSet(&StaticErrInfo.Core)) 459 LogRel(("checkCertificates: %s\n", StaticErrInfo.Core.pszMsg)); 460 else 461 AssertRC(rc); 462 463 unsigned cCertificates = 0; 464 fFoundCerts = checkCertificatesInStore(hStore, &cCertificates); 465 466 RTCrStoreRelease(hStore); 467 468 /* 469 * If there are more than two certificates in the database, we're looking 470 * at a mirror of the system CA stores. Refresh our snapshot once every 28 days. 471 */ 472 RTTIMESPEC MaxAge; 473 if ( fFoundCerts 474 && cCertificates > 2 475 && RTTimeSpecCompare(&Info.ModificationTime, RTTimeSpecSubSeconds(RTTimeNow(&MaxAge), 28 *24*3600)) < 0) 476 fFoundCerts = false; 477 } 478 } 479 480 return fFoundCerts; 496 /*static*/ unsigned 497 UINetworkReplyPrivateThread::countCertsFound(bool const *pafFoundCerts) 498 { 499 unsigned cFound = 0; 500 for (uint32_t i = 0; i < RT_ELEMENTS(s_aCerts); i++) 501 cFound += pafFoundCerts[i]; 502 return cFound; 481 503 } 482 504 … … 485 507 * 486 508 * @returns true if we have, false if we haven't. 487 * @param fFoundCerts The mask of found certificates (see488 * certEntryFoundMask).509 * @param pafFoundCerts Array parallel to s_aCerts with the status of 510 * each wanted certificate. 489 511 * @param fOnlyMandatory Only require mandatory certificates to be 490 512 * present. If false, all certificates must be … … 492 514 */ 493 515 /*static*/ bool 494 UINetworkReplyPrivateThread::allCertsFound(uint64_t fFoundCerts, bool fOnlyMandatory) 495 { 496 AssertCompile(RT_ELEMENTS(s_aCerts) < 64); 497 498 /* Add non-mandatory flags before comparing. */ 499 if ( fOnlyMandatory 500 && fFoundCerts != RT_BIT_64(RT_ELEMENTS(s_aCerts)) - UINT64_C(1)) 516 UINetworkReplyPrivateThread::areAllCertsFound(bool const *pafFoundCerts, bool fOnlyMandatory) 517 { 518 if (fOnlyMandatory) 519 { 501 520 for (uint32_t i = 0; i < RT_ELEMENTS(s_aCerts); i++) 502 if (!s_aCerts[i].fMandatory) 503 fFoundCerts |= RT_BIT_64(i); 504 505 return fFoundCerts == RT_BIT_64(RT_ELEMENTS(s_aCerts)) - UINT64_C(1); 506 } 507 508 /** 509 * Calculates the 64-bit 'found' mask for a certificate entry. 510 * 511 * @returns 64-bit mask. 512 * @param iCert The certificate entry. 513 */ 514 /*static*/ uint64_t 515 UINetworkReplyPrivateThread::certEntryFoundMask(uint32_t iCert) 516 { 517 Assert(iCert < RT_ELEMENTS(s_aCerts)); 518 uint64_t fMask = RT_BIT_64(iCert); 519 521 if ( !pafFoundCerts[i] 522 && ((const CERTINFO *)s_aCerts[i].pvUser)->fMandatory) 523 return false; 524 } 525 else 526 for (uint32_t i = 0; i < RT_ELEMENTS(s_aCerts); i++) 527 if (!pafFoundCerts[i]) 528 return false; 529 return true; 530 } 531 532 /*static*/ void 533 UINetworkReplyPrivateThread::refreshCertificates(RTHTTP hHttp, RTCRSTORE hOldStore, bool *pafOldFoundCerts, 534 const char *pszCaCertFile) 535 { 520 536 /* 521 * Tedium: Also mark certificates that this is an alternative to, we only need 522 * the public key once. 537 * Collect the standard assortment of SSL certificates. 523 538 */ 524 uint8_t iAlt = s_aCerts[iCert].iAlternativeTo; 525 if (iAlt != UINT8_MAX) 526 { 527 unsigned cMax = 10; 528 do 529 { 530 Assert(iAlt < RT_ELEMENTS(s_aCerts)); 531 Assert(cMax > 1); 532 Assert(strcmp(s_aCerts[iAlt].pszSubject, s_aCerts[iCert].pszSubject) == 0); 533 fMask |= RT_BIT_64(iAlt); 534 iAlt = s_aCerts[iAlt].iAlternativeTo; 535 } while (iAlt != iCert && cMax-- > 0); 536 } 537 538 return fMask; 539 } 540 541 /** 542 * Checks if the certificates we desire are all present in the given store. 543 * 544 * @returns true if present, false if not. 545 * @param hStore The store to examine. 546 * @param pcCertificates Where to return the number of certificates in 547 * the store. Optional. 548 */ 549 /* static */ bool 550 UINetworkReplyPrivateThread::checkCertificatesInStore(RTCRSTORE hStore, unsigned *pcCertificates /* = NULL*/) 551 { 552 if (pcCertificates) 553 *pcCertificates = 0; 554 555 /* 556 * Enumerate the store, checking for the certificates we need. 557 */ 558 RTCRSTORECERTSEARCH Search; 559 int rc = RTCrStoreCertFindAll(hStore, &Search); 539 uint32_t cHint = RTCrStoreCertCount(hOldStore); 540 RTCRSTORE hNewStore; 541 int rc = RTCrStoreCreateInMem(&hNewStore, cHint > 32 && cHint < _32K ? cHint + 16 : 256); 560 542 if (RT_SUCCESS(rc)) 561 543 { 562 uint64_t fFoundCerts = 0; 563 unsigned cCertificates = 0; 564 PCRTCRCERTCTX pCertCtx; 565 while ((pCertCtx = RTCrStoreCertSearchNext(hStore, &Search)) != NULL) 566 { 567 if ( (pCertCtx->fFlags & RTCRCERTCTX_F_ENC_MASK) == RTCRCERTCTX_F_ENC_X509_DER 568 && pCertCtx->cbEncoded > 0 569 && pCertCtx->pCert) 544 RTERRINFOSTATIC StaticErrInfo; 545 rc = RTHttpGatherCaCertsInStore(hNewStore, 0 /*fFlags*/, RTErrInfoInitStatic(&StaticErrInfo)); 546 if (RTErrInfoIsSet(&StaticErrInfo.Core)) 547 LogRel(("refreshCertificates/#1: %s\n", StaticErrInfo.Core.pszMsg)); 548 else 549 AssertLogRelRC(rc); 550 551 if (RT_SUCCESS(rc)) 552 { 553 /* 554 * Check and see what we've got. If we haven't got all we desire, 555 * try add it from the previous store. 556 */ 557 bool afNewFoundCerts[RT_ELEMENTS(s_aCerts)]; 558 RT_ZERO(afNewFoundCerts); /* paranoia */ 559 560 rc = RTCrStoreCertCheckWanted(hNewStore, s_aCerts, RT_ELEMENTS(s_aCerts), afNewFoundCerts); 561 AssertLogRelRC(rc); 562 Assert(rc != VINF_SUCCESS || areAllCertsFound(afNewFoundCerts, false /*fOnlyMandatory*/)); 563 if (rc != VINF_SUCCESS) 570 564 { 571 cCertificates++; 572 573 /* 574 * It is a X.509 certificate. Check if it matches any of those we're looking for. 575 */ 576 for (uint32_t i = 0; i < RT_ELEMENTS(s_aCerts); i++) 577 if ( pCertCtx->cbEncoded == s_aCerts[i].cbEncoded 578 && RTCrX509Name_MatchWithString(&pCertCtx->pCert->TbsCertificate.Subject, s_aCerts[i].pszSubject)) 579 { 580 if (RTSha1Check(pCertCtx->pabEncoded, pCertCtx->cbEncoded, s_aCerts[i].abSha1)) 581 { 582 if (RTSha512Check(pCertCtx->pabEncoded, pCertCtx->cbEncoded, s_aCerts[i].abSha512)) 583 { 584 fFoundCerts |= certEntryFoundMask(i); 585 break; 586 } 587 } 588 } 565 rc = RTCrStoreCertAddWantedFromStore(hNewStore, 566 RTCRCERTCTX_F_ADD_IF_NOT_FOUND | RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR, 567 hOldStore, s_aCerts, RT_ELEMENTS(s_aCerts), afNewFoundCerts); 568 AssertLogRelRC(rc); 569 Assert(rc != VINF_SUCCESS || areAllCertsFound(afNewFoundCerts, false /*fOnlyMandatory*/)); 589 570 } 590 RTCrCertCtxRelease(pCertCtx); 571 572 /* 573 * If that didn't help, seek out certificates in more obscure places, 574 * like java, mozilla and mutt. 575 */ 576 if (rc != VINF_SUCCESS) 577 { 578 rc = RTCrStoreCertAddWantedFromFishingExpedition(hNewStore, 579 RTCRCERTCTX_F_ADD_IF_NOT_FOUND 580 | RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR, 581 s_aCerts, RT_ELEMENTS(s_aCerts), afNewFoundCerts, 582 RTErrInfoInitStatic(&StaticErrInfo)); 583 if (RTErrInfoIsSet(&StaticErrInfo.Core)) 584 LogRel(("refreshCertificates/#2: %s\n", StaticErrInfo.Core.pszMsg)); 585 Assert(rc != VINF_SUCCESS || areAllCertsFound(afNewFoundCerts, false /*fOnlyMandatory*/)); 586 } 587 588 /* 589 * If that didn't help, try download the certificates. 590 */ 591 if (rc != VINF_SUCCESS) 592 downloadMissingCertificates(hNewStore, afNewFoundCerts, hHttp, &StaticErrInfo); 593 594 /* 595 * If we've got the same or better hit rate than the old store, 596 * replace the CA certs file. 597 */ 598 if ( areAllCertsFound(afNewFoundCerts, false /*fOnlyMandatory*/) 599 || ( countCertsFound(afNewFoundCerts) >= countCertsFound(pafOldFoundCerts) 600 && areAllCertsFound(afNewFoundCerts, true /*fOnlyMandatory*/) 601 >= areAllCertsFound(pafOldFoundCerts, true /*fOnlyMandatory*/) ) ) 602 { 603 rc = RTCrStoreCertExportAsPem(hNewStore, 0 /*fFlags*/, pszCaCertFile); 604 if (RT_SUCCESS(rc)) 605 memcpy(pafOldFoundCerts, afNewFoundCerts, sizeof(afNewFoundCerts)); 606 else 607 RT_ZERO(pafOldFoundCerts); 608 } 591 609 } 592 int rc2 = RTCrStoreCertSearchDestroy(hStore, &Search); AssertRC(rc2); 593 594 /* 595 * Set the certificate count. 596 */ 597 if (pcCertificates) 598 *pcCertificates = cCertificates; 599 600 /* 601 * Did we locate all of them? 602 */ 603 if (allCertsFound(fFoundCerts, true /* fOnlyMandatory */)) /** @todo combine the two certificate retrieval approaches */ 604 return true; 605 } 606 AssertRC(rc); 607 return false; 608 } 609 610 /*static*/ int 611 UINetworkReplyPrivateThread::downloadCertificates(RTHTTP hHttp, const char *pszCaCertFile) 612 { 613 /* 614 * Prepare temporary certificate store. 615 */ 616 RTCRSTORE hStore; 617 int rc = RTCrStoreCreateInMem(&hStore, RT_ELEMENTS(s_aCerts)); 618 AssertRCReturn(rc, rc); 619 620 /* 621 * Accounts for certificates we've downloaded, verified and added to the store. 622 */ 623 uint64_t fFoundCerts = 0; 624 AssertCompile(RT_ELEMENTS(s_aCerts) < 64); 610 RTCrStoreRelease(hNewStore); 611 } 612 } 613 614 /*static*/ void 615 UINetworkReplyPrivateThread::downloadMissingCertificates(RTCRSTORE hNewStore, bool *pafNewFoundCerts, RTHTTP hHttp, 616 PRTERRINFOSTATIC pStaticErrInfo) 617 { 618 int rc; 625 619 626 620 /* … … 640 634 { 641 635 for (uint32_t i = 0; i < RT_ELEMENTS(s_aCerts); i++) 642 if ( s_aCerts[i].pszZipFile)636 if (!pafNewFoundCerts[i]) 643 637 { 644 void *pvFile; 645 size_t cbFile; 646 rc = RTZipPkzipMemDecompress(&pvFile, &cbFile, pvRootsZip, cbRootsZip, s_aCerts[i].pszZipFile); 647 if (RT_SUCCESS(rc)) 638 CERTINFO const *pInfo = (CERTINFO const *)s_aCerts[i].pvUser; 639 if (pInfo->pszZipFile) 648 640 { 649 rc = convertVerifyAndAddPemCertificateToStore(hStore, pvFile, cbFile, &s_aCerts[i]); 650 RTMemFree(pvFile); 641 void *pvFile; 642 size_t cbFile; 643 rc = RTZipPkzipMemDecompress(&pvFile, &cbFile, pvRootsZip, cbRootsZip, pInfo->pszZipFile); 651 644 if (RT_SUCCESS(rc)) 652 fFoundCerts |= certEntryFoundMask(i); 645 { 646 rc = convertVerifyAndAddPemCertificateToStore(hNewStore, pvFile, cbFile, &s_aCerts[i]); 647 RTMemFree(pvFile); 648 if (RT_SUCCESS(rc)) 649 { 650 /* 651 * Successfully added. Mark it as found and return if we've got them all. 652 */ 653 pafNewFoundCerts[i] = true; 654 if (areAllCertsFound(pafNewFoundCerts, false /* fOnlyMandatory */)) 655 { 656 RTHttpFreeResponse(pvRootsZip); 657 return; 658 } 659 } 660 } 653 661 } 654 662 } 655 663 RTHttpFreeResponse(pvRootsZip); 656 if (allCertsFound(fFoundCerts, false /* fOnlyMandatory */))657 break;658 664 } 659 665 } 660 666 661 667 /* 662 * Fallback:Try download certificates separately.668 * Try download certificates separately. 663 669 */ 664 if (allCertsFound(fFoundCerts, false /* fOnlyMandatory */)) 665 for (uint32_t i = 0; i < RT_ELEMENTS(s_aCerts); i++) 666 if (!(fFoundCerts & RT_BIT_64(i))) 667 for (uint32_t iUrl = 0; iUrl < RT_ELEMENTS(s_aCerts[i].apszUrls); i++) 668 if (s_aCerts[i].apszUrls[iUrl]) 670 for (uint32_t i = 0; i < RT_ELEMENTS(s_aCerts); i++) 671 if (!pafNewFoundCerts[i]) 672 { 673 CERTINFO const *pInfo = (CERTINFO const *)s_aCerts[i].pvUser; 674 for (uint32_t iUrl = 0; iUrl < RT_ELEMENTS(pInfo->apszUrls); i++) 675 if (pInfo->apszUrls[iUrl]) 676 { 677 void *pvResponse; 678 size_t cbResponse; 679 rc = RTHttpGetBinary(hHttp, pInfo->apszUrls[iUrl], &pvResponse, &cbResponse); 680 if (RT_SUCCESS(rc)) 669 681 { 670 void *pvResponse; 671 size_t cbResponse; 672 rc = RTHttpGetBinary(hHttp, s_aCerts[i].apszUrls[iUrl], &pvResponse, &cbResponse); 682 rc = convertVerifyAndAddPemCertificateToStore(hNewStore, pvResponse, cbResponse, &s_aCerts[i]); 683 RTHttpFreeResponse(pvResponse); 673 684 if (RT_SUCCESS(rc)) 674 685 { 675 rc = convertVerifyAndAddPemCertificateToStore(hStore, pvResponse, cbResponse, &s_aCerts[i]); 676 RTHttpFreeResponse(pvResponse); 677 if (RT_SUCCESS(rc)) 678 { 679 fFoundCerts |= certEntryFoundMask(i); 680 break; 681 } 686 pafNewFoundCerts[i] = true; 687 break; 682 688 } 683 689 } 684 685 /* 686 * See if we've got the certificates we want, save it we do. 687 */ 688 if (allCertsFound(fFoundCerts, true /*fOnlyMandatory*/)) 689 rc = RTCrStoreCertExportAsPem(hStore, 0 /*fFlags*/, pszCaCertFile); 690 else if (RT_SUCCESS(rc)) 691 rc = VERR_NOT_FOUND; 692 693 RTCrStoreRelease(hStore); 694 return rc; 690 } 691 } 695 692 } 696 693 … … 703 700 * @param pvResponse The raw PEM certificate file bytes. 704 701 * @param cbResponse The number of bytes. 705 * @param p CertInfoThe certificate info (we use hashes and encoded702 * @param pWantedCert The certificate info (we use hashes and encoded 706 703 * size). 707 704 */ … … 709 706 UINetworkReplyPrivateThread::convertVerifyAndAddPemCertificateToStore(RTCRSTORE hStore, 710 707 void const *pvResponse, size_t cbResponse, 711 const CERTINFO *pCertInfo)708 PCRTCRCERTWANTED pWantedCert) 712 709 { 713 710 /* … … 730 727 rc = VERR_NOT_FOUND; 731 728 for (PCRTCRPEMSECTION pCur = pSectionHead; pCur; pCur = pCur->pNext) 732 if (pCur->cbData == p CertInfo->cbEncoded)729 if (pCur->cbData == pWantedCert->cbEncoded) 733 730 { 734 if ( RTSha1Check(pCur->pbData, pCur->cbData, p CertInfo->abSha1)735 && RTSha512Check(pCur->pbData, pCur->cbData, p CertInfo->abSha512))731 if ( RTSha1Check(pCur->pbData, pCur->cbData, pWantedCert->abSha1) 732 && RTSha512Check(pCur->pbData, pCur->cbData, pWantedCert->abSha512)) 736 733 { 737 734 /* … … 754 751 else 755 752 LogRel(("convertVerifyAndAddPemCertificateToStore: cbData=%#zx expected %#zx\n", 756 pCur->cbData, p CertInfo->cbEncoded));753 pCur->cbData, pWantedCert->cbEncoded)); 757 754 758 755 RTCrPemFreeSections(pSectionHead); … … 760 757 return rc; 761 758 } 762 763 /**764 * Tries to retrieve an up to date list of certificates from the system that765 * includes the necessary certs.766 *767 * @returns IPRT status code, success indicating that we've found what we need.768 * @param pszCaCertFile Where to store the certificates.769 */770 /*static*/ int771 UINetworkReplyPrivateThread::retrieveCertificatesFromSystem(const char *pszCaCertFile)772 {773 /*774 * Duplicate the user and system stores.775 */776 RTERRINFOSTATIC StaticErrInfo;777 RTCRSTORE hUserStore;778 int rc = RTCrStoreCreateSnapshotById(&hUserStore, RTCRSTOREID_USER_TRUSTED_CAS_AND_CERTIFICATES,779 RTErrInfoInitStatic(&StaticErrInfo));780 if (RT_FAILURE(rc))781 hUserStore = NIL_RTCRSTORE;782 if (RTErrInfoIsSet(&StaticErrInfo.Core))783 LogRel(("retrieveCertificatesFromSystem/#1: %s\n", StaticErrInfo.Core.pszMsg));784 785 RTCRSTORE hSystemStore;786 rc = RTCrStoreCreateSnapshotById(&hSystemStore, RTCRSTOREID_SYSTEM_TRUSTED_CAS_AND_CERTIFICATES,787 RTErrInfoInitStatic(&StaticErrInfo));788 if (RT_FAILURE(rc))789 hUserStore = NIL_RTCRSTORE;790 if (RTErrInfoIsSet(&StaticErrInfo.Core))791 LogRel(("retrieveCertificatesFromSystem/#2: %s\n", StaticErrInfo.Core.pszMsg));792 793 /*794 * Merge the two.795 */796 int rc2 = RTCrStoreCertAddFromStore(hUserStore, RTCRCERTCTX_F_ADD_IF_NOT_FOUND | RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR,797 hSystemStore);798 AssertRC(rc2);799 RTCrStoreRelease(hSystemStore);800 hSystemStore = NIL_RTCRSTORE;801 802 /*803 * See if we've got the certificates we want, save it we do.804 */805 if (checkCertificatesInStore(hUserStore))806 rc = RTCrStoreCertExportAsPem(hUserStore, 0 /*fFlags*/, pszCaCertFile);807 else808 rc = VERR_NOT_FOUND;809 RTCrStoreRelease(hUserStore);810 return rc;811 }812 813 759 814 760 -
trunk/src/VBox/Runtime/Makefile.kmk
r57586 r57613 368 368 common/crypto/store.cpp \ 369 369 common/crypto/store-inmem.cpp \ 370 common/crypto/RTCrStoreCertAddFromFile.cpp \ 371 common/crypto/RTCrStoreCertAddFromDir.cpp \ 372 common/crypto/RTCrStoreCertAddFromStore.cpp \ 370 common/crypto/store-cert-add-basic.cpp \ 373 371 common/crypto/RTCrStoreCertAddFromJavaKeyStore.cpp \ 372 common/crypto/RTCrStoreCertAddWantedFromFishingExpedition.cpp \ 374 373 common/crypto/RTCrStoreCertExportAsPem.cpp \ 375 374 common/dbg/dbg.cpp \ … … 465 464 common/path/RTPathExt.cpp \ 466 465 common/path/RTPathFilename.cpp \ 466 common/path/RTPathGlob.cpp \ 467 467 common/path/RTPathHasExt.cpp \ 468 468 common/path/RTPathHasPath.cpp \ -
trunk/src/VBox/Runtime/common/crypto/store-cert-add-basic.cpp
r57607 r57613 33 33 34 34 #include <iprt/assert.h> 35 #include <iprt/crypto/pem.h> 35 36 #include <iprt/dir.h> 36 37 #include <iprt/err.h> 38 #include <iprt/file.h> 39 #include <iprt/mem.h> 37 40 #include <iprt/path.h> 41 #include <iprt/sha.h> 38 42 #include <iprt/string.h> 43 44 #include "x509-internal.h" 45 46 47 /********************************************************************************************************************************* 48 * Global Variables * 49 *********************************************************************************************************************************/ 50 /** BEGIN CERTIFICATE / END CERTIFICATE. */ 51 static RTCRPEMMARKERWORD const g_aWords_Certificate[] = 52 { 53 { RT_STR_TUPLE("CERTIFICATE") } 54 }; 55 56 /** BEGIN TRUSTED CERTIFICATE / END TRUSTED CERTIFICATE. */ 57 static RTCRPEMMARKERWORD const g_aWords_TrustedCertificate[] = 58 { 59 { RT_STR_TUPLE("TRUSTED") }, 60 { RT_STR_TUPLE("CERTIFICATE") } 61 }; 62 63 /** BEGIN X509 CERTIFICATE / END X509 CERTIFICATE. (old) */ 64 static RTCRPEMMARKERWORD const g_aWords_X509Certificate[] = 65 { 66 { RT_STR_TUPLE("X509") }, 67 { RT_STR_TUPLE("CERTIFICATE") } 68 }; 69 70 /** 71 * X509 Certificate markers. 72 * 73 * @remark See crypto/pem/pem.h in OpenSSL for a matching list. 74 */ 75 RTCRPEMMARKER const g_aX509CertificateMarkers[3] = 76 { 77 { g_aWords_Certificate, RT_ELEMENTS(g_aWords_Certificate) }, 78 { g_aWords_TrustedCertificate, RT_ELEMENTS(g_aWords_TrustedCertificate) }, 79 { g_aWords_X509Certificate, RT_ELEMENTS(g_aWords_X509Certificate) } 80 }; 81 82 83 84 /** 85 * Checks if we've found all the certificates already. 86 * 87 * @returns true if all found, false if not. 88 * @param afFound Indicator array. 89 * @param cWanted Number of wanted certificates. 90 */ 91 DECLINLINE(bool) rtCrStoreAllDone(bool const *afFound, size_t cWanted) 92 { 93 while (cWanted-- > 0) 94 if (!afFound[cWanted]) 95 return false; 96 return true; 97 } 98 99 100 /** 101 * Checks if the given certificate specs matches the given wanted poster. 102 * 103 * @returns true if match, false if not. 104 * @param pWanted The certificate wanted poster. 105 * @param cbEncoded The candidate certificate encoded size. 106 * @param paSha1 The candidate certificate SHA-1 fingerprint. 107 * @param paSha512 The candidate certificate SHA-512 fingerprint. 108 * @param pCert The decoded candidate certificate, optional. If not 109 * given the result will be uncertain. 110 */ 111 DECLINLINE(bool) rtCrStoreIsCertEqualToWanted(PCRTCRCERTWANTED pWanted, 112 size_t cbEncoded, 113 uint8_t const pabSha1[RTSHA1_HASH_SIZE], 114 uint8_t const pabSha512[RTSHA512_HASH_SIZE], 115 PCRTCRX509CERTIFICATE pCert) 116 { 117 if ( pWanted->cbEncoded != cbEncoded 118 && pWanted->cbEncoded != 0) 119 return false; 120 121 if ( pWanted->fSha1Fingerprint 122 && memcmp(pWanted->abSha1, pabSha1, RTSHA1_HASH_SIZE) != 0) 123 return false; 124 125 if ( pWanted->fSha512Fingerprint 126 && memcmp(pWanted->abSha512, pabSha512, RTSHA512_HASH_SIZE) != 0) 127 return false; 128 129 if ( pWanted->pszSubject 130 && pCert 131 && !RTCrX509Name_MatchWithString(&pCert->TbsCertificate.Subject, pWanted->pszSubject)) 132 return false; 133 134 return true; 135 } 136 137 138 /** 139 * Checks if a certificate is wanted. 140 * 141 * @returns true if match, false if not. 142 * @param paWanted The certificate wanted posters. 143 * @param cWanted The number of wanted posters. 144 * @param apfFound Found initicators running paralell to @a paWanted. 145 * @param cbEncoded The candidate certificate encoded size. 146 * @param paSha1 The candidate certificate SHA-1 fingerprint. 147 * @param paSha512 The candidate certificate SHA-512 fingerprint. 148 * @param pCert The decoded candidate certificate, optional. If not 149 * given the result will be uncertain. 150 */ 151 DECLINLINE(bool) rtCrStoreIsCertWanted(PCRTCRCERTWANTED paWanted, size_t cWanted, bool const *pafFound, size_t cbEncoded, 152 uint8_t const pabSha1[RTSHA1_HASH_SIZE], uint8_t const pabSha512[RTSHA512_HASH_SIZE], 153 PCRTCRX509CERTIFICATE pCert) 154 { 155 for (size_t iCert = 0; iCert < cWanted; iCert++) 156 if (!pafFound[iCert]) 157 if (rtCrStoreIsCertEqualToWanted(&paWanted[iCert], cbEncoded, pabSha1, pabSha512, pCert)) 158 return true; 159 return false; 160 } 161 162 163 /** 164 * Marks a certificate as found after it has been added to the store. 165 * 166 * May actually mark several certificates as found if there are duplicates or 167 * ambiguities in the wanted list. 168 * 169 * @returns true if all have been found, false if more to search for. 170 * 171 * @param apfFound Found initicators running paralell to @a paWanted. 172 * This is what this function updates. 173 * @param paWanted The certificate wanted posters. 174 * @param cWanted The number of wanted posters. 175 * @param cbEncoded The candidate certificate encoded size. 176 * @param paSha1 The candidate certificate SHA-1 fingerprint. 177 * @param paSha512 The candidate certificate SHA-512 fingerprint. 178 * @param pCert The decoded candidate certificate, optional. If not 179 * given the result will be uncertain. 180 */ 181 static bool rtCrStoreMarkCertFound(bool *pafFound, PCRTCRCERTWANTED paWanted, size_t cWanted, size_t cbEncoded, 182 uint8_t const pabSha1[RTSHA1_HASH_SIZE], uint8_t const pabSha512[RTSHA512_HASH_SIZE], 183 PCRTCRX509CERTIFICATE pCert) 184 { 185 size_t cFound = 0; 186 for (size_t iCert = 0; iCert < cWanted; iCert++) 187 if (pafFound[iCert]) 188 cFound++; 189 else if (rtCrStoreIsCertEqualToWanted(&paWanted[iCert], cbEncoded, pabSha1, pabSha512, pCert)) 190 { 191 pafFound[iCert] = true; 192 cFound++; 193 } 194 return cFound == cWanted; 195 } 196 197 198 RTDECL(int) RTCrStoreCertAddFromStore(RTCRSTORE hStore, uint32_t fFlags, RTCRSTORE hStoreSrc) 199 { 200 /* 201 * Validate input. 202 */ 203 AssertReturn(!(fFlags & ~(RTCRCERTCTX_F_ADD_IF_NOT_FOUND | RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR)), VERR_INVALID_FLAGS); 204 205 /* 206 * Enumerate all the certificates in the source store, adding them to the destination. 207 */ 208 RTCRSTORECERTSEARCH Search; 209 int rc = RTCrStoreCertFindAll(hStoreSrc, &Search); 210 if (RT_SUCCESS(rc)) 211 { 212 PCRTCRCERTCTX pCertCtx; 213 while ((pCertCtx = RTCrStoreCertSearchNext(hStoreSrc, &Search)) != NULL) 214 { 215 int rc2 = RTCrStoreCertAddEncoded(hStore, pCertCtx->fFlags | (fFlags & RTCRCERTCTX_F_ADD_IF_NOT_FOUND), 216 pCertCtx->pabEncoded, pCertCtx->cbEncoded, NULL); 217 if (RT_FAILURE(rc2)) 218 { 219 rc = rc2; 220 if (!(fFlags & RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR)) 221 break; 222 } 223 RTCrCertCtxRelease(pCertCtx); 224 } 225 226 int rc2 = RTCrStoreCertSearchDestroy(hStoreSrc, &Search); AssertRC(rc2); 227 } 228 return rc; 229 } 230 RT_EXPORT_SYMBOL(RTCrStoreCertAddFromStore); 231 232 233 RTDECL(int) RTCrStoreCertAddWantedFromStore(RTCRSTORE hStore, uint32_t fFlags, RTCRSTORE hSrcStore, 234 PCRTCRCERTWANTED paWanted, size_t cWanted, bool *pafFound) 235 { 236 /* 237 * Validate input a little. 238 */ 239 AssertReturn(!(fFlags & ~(RTCRCERTCTX_F_ADD_IF_NOT_FOUND | RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR)), VERR_INVALID_FLAGS); 240 fFlags |= RTCRCERTCTX_F_ADD_IF_NOT_FOUND; /* forced */ 241 242 AssertReturn(cWanted, VERR_NOT_FOUND); 243 for (uint32_t i = 0; i < cWanted; i++) 244 { 245 AssertReturn(!paWanted[i].pszSubject || *paWanted[i].pszSubject, VERR_INVALID_PARAMETER); 246 AssertReturn( paWanted[i].pszSubject 247 || paWanted[i].fSha1Fingerprint 248 || paWanted[i].fSha512Fingerprint, 249 VERR_INVALID_PARAMETER); 250 } 251 252 /* 253 * Make sure we've got a result array. 254 */ 255 bool *pafFoundFree = NULL; 256 if (!pafFound) 257 { 258 pafFound = pafFoundFree = (bool *)RTMemTmpAllocZ(sizeof(bool) * cWanted); 259 AssertReturn(pafFound, VERR_NO_TMP_MEMORY); 260 } 261 262 /* 263 * Enumerate the store entries. 264 */ 265 RTCRSTORECERTSEARCH Search; 266 int rc = RTCrStoreCertFindAll(hSrcStore, &Search); 267 if (RT_SUCCESS(rc)) 268 { 269 rc = VWRN_NOT_FOUND; 270 PCRTCRCERTCTX pCertCtx; 271 while ((pCertCtx = RTCrStoreCertSearchNext(hSrcStore, &Search)) != NULL) 272 { 273 if ( (pCertCtx->fFlags & RTCRCERTCTX_F_ENC_MASK) == RTCRCERTCTX_F_ENC_X509_DER 274 && pCertCtx->cbEncoded > 0 275 && pCertCtx->pCert) 276 { 277 /* 278 * If the certificate is wanted, try add it to the store. 279 */ 280 uint8_t abSha1[RTSHA1_HASH_SIZE]; 281 RTSha1(pCertCtx->pabEncoded, pCertCtx->cbEncoded, abSha1); 282 uint8_t abSha512[RTSHA512_HASH_SIZE]; 283 RTSha1(pCertCtx->pabEncoded, pCertCtx->cbEncoded, abSha512); 284 if (rtCrStoreIsCertWanted(paWanted, cWanted, pafFound, pCertCtx->cbEncoded, abSha1, abSha512, pCertCtx->pCert)) 285 { 286 int rc2 = RTCrStoreCertAddEncoded(hStore, 287 RTCRCERTCTX_F_ENC_X509_DER | (fFlags & RTCRCERTCTX_F_ADD_IF_NOT_FOUND), 288 pCertCtx->pabEncoded, pCertCtx->cbEncoded, NULL /*pErrInfo*/); 289 if (RT_SUCCESS(rc2)) 290 { 291 /* 292 * Mark it as found, stop if we've found all. 293 */ 294 if (rtCrStoreMarkCertFound(pafFound, paWanted, cWanted, 295 pCertCtx->cbEncoded, abSha1, abSha512, pCertCtx->pCert)) 296 { 297 if (RT_SUCCESS(rc)) 298 rc = VINF_SUCCESS; 299 RTCrCertCtxRelease(pCertCtx); 300 break; 301 } 302 } 303 else 304 { 305 /* 306 * Some error adding the certificate. Since it cannot be anything with 307 * the encoding, it must be something with the store or resources, so 308 * always return the error status. 309 */ 310 rc = rc2; 311 if (!(fFlags & RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR)) 312 { 313 RTCrCertCtxRelease(pCertCtx); 314 break; 315 } 316 } 317 } 318 } 319 RTCrCertCtxRelease(pCertCtx); 320 } 321 int rc2 = RTCrStoreCertSearchDestroy(hSrcStore, &Search); 322 AssertRC(rc2); 323 } 324 325 if (pafFoundFree) 326 RTMemTmpFree(pafFoundFree); 327 return rc; 328 } 329 RT_EXPORT_SYMBOL(RTCrStoreCertAddWantedFromStore); 330 331 332 RTDECL(int) RTCrStoreCertCheckWanted(RTCRSTORE hStore, PCRTCRCERTWANTED paWanted, size_t cWanted, bool *pafFound) 333 { 334 /* 335 * Validate input a little. 336 */ 337 AssertReturn(cWanted, VERR_NOT_FOUND); 338 for (uint32_t i = 0; i < cWanted; i++) 339 { 340 AssertReturn(!paWanted[i].pszSubject || *paWanted[i].pszSubject, VERR_INVALID_PARAMETER); 341 AssertReturn( paWanted[i].pszSubject 342 || paWanted[i].fSha1Fingerprint 343 || paWanted[i].fSha512Fingerprint, 344 VERR_INVALID_PARAMETER); 345 } 346 AssertPtrReturn(pafFound, VERR_INVALID_POINTER); 347 348 /* 349 * Clear the found array. 350 */ 351 for (uint32_t iCert = 0; iCert < cWanted; iCert++) 352 pafFound[iCert] = false; 353 354 /* 355 * Enumerate the store entries. 356 */ 357 RTCRSTORECERTSEARCH Search; 358 int rc = RTCrStoreCertFindAll(hStore, &Search); 359 if (RT_SUCCESS(rc)) 360 { 361 rc = VWRN_NOT_FOUND; 362 PCRTCRCERTCTX pCertCtx; 363 while ((pCertCtx = RTCrStoreCertSearchNext(hStore, &Search)) != NULL) 364 { 365 if ( (pCertCtx->fFlags & RTCRCERTCTX_F_ENC_MASK) == RTCRCERTCTX_F_ENC_X509_DER 366 && pCertCtx->cbEncoded > 0 367 && pCertCtx->pCert) 368 { 369 /* 370 * Hash it and check if it's wanted. Stop when we've found all. 371 */ 372 uint8_t abSha1[RTSHA1_HASH_SIZE]; 373 RTSha1(pCertCtx->pabEncoded, pCertCtx->cbEncoded, abSha1); 374 uint8_t abSha512[RTSHA512_HASH_SIZE]; 375 RTSha1(pCertCtx->pabEncoded, pCertCtx->cbEncoded, abSha512); 376 if (rtCrStoreMarkCertFound(pafFound, paWanted, cWanted, pCertCtx->cbEncoded, abSha1, abSha512, pCertCtx->pCert)) 377 { 378 rc = VINF_SUCCESS; 379 RTCrCertCtxRelease(pCertCtx); 380 break; 381 } 382 } 383 RTCrCertCtxRelease(pCertCtx); 384 } 385 int rc2 = RTCrStoreCertSearchDestroy(hStore, &Search); 386 AssertRC(rc2); 387 } 388 389 return rc; 390 } 391 RT_EXPORT_SYMBOL(RTCrStoreCertAddWantedFromStore); 392 393 394 RTDECL(int) RTCrStoreCertAddFromFile(RTCRSTORE hStore, uint32_t fFlags, const char *pszFilename, PRTERRINFO pErrInfo) 395 { 396 AssertReturn(!(fFlags & ~(RTCRCERTCTX_F_ADD_IF_NOT_FOUND | RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR)), VERR_INVALID_FLAGS); 397 398 size_t cbContent; 399 void *pvContent; 400 int rc = RTFileReadAllEx(pszFilename, 0, 64U*_1M, RTFILE_RDALL_O_DENY_WRITE, &pvContent, &cbContent); 401 if (RT_SUCCESS(rc)) 402 { 403 /* 404 * Is it a java key store file? 405 */ 406 if ( cbContent > 32 407 && ((uint32_t const *)pvContent)[0] == RT_H2BE_U32_C(UINT32_C(0xfeedfeed)) /* magic */ 408 && ((uint32_t const *)pvContent)[1] == RT_H2BE_U32_C(UINT32_C(0x00000002)) /* version */ ) 409 rc = RTCrStoreCertAddFromJavaKeyStoreInMem(hStore, fFlags, pvContent, cbContent, pszFilename, pErrInfo); 410 /* 411 * No assume PEM or DER encoded binary certificate. 412 */ 413 else 414 { 415 PCRTCRPEMSECTION pSectionHead; 416 rc = RTCrPemParseContent(pvContent, cbContent, 417 (fFlags & RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR) 418 ? RTCRPEMREADFILE_F_CONTINUE_ON_ENCODING_ERROR : 0, 419 g_aX509CertificateMarkers, RT_ELEMENTS(g_aX509CertificateMarkers), 420 &pSectionHead, pErrInfo); 421 if (RT_SUCCESS(rc)) 422 { 423 PCRTCRPEMSECTION pCurSec = pSectionHead; 424 while (pCurSec) 425 { 426 int rc2 = RTCrStoreCertAddEncoded(hStore, 427 RTCRCERTCTX_F_ENC_X509_DER | (fFlags & RTCRCERTCTX_F_ADD_IF_NOT_FOUND), 428 pCurSec->pbData, pCurSec->cbData, 429 !RTErrInfoIsSet(pErrInfo) ? pErrInfo : NULL); 430 if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) 431 { 432 rc = rc2; 433 if (!(fFlags & RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR)) 434 break; 435 } 436 pCurSec = pCurSec->pNext; 437 } 438 439 RTCrPemFreeSections(pSectionHead); 440 } 441 } 442 RTFileReadAllFree(pvContent, cbContent); 443 } 444 else 445 rc = RTErrInfoSetF(pErrInfo, rc, "RTFileReadAllEx failed with %Rrc on '%s'", rc, pszFilename); 446 return rc; 447 } 448 RT_EXPORT_SYMBOL(RTCrStoreCertAddFromFile); 449 450 451 RTDECL(int) RTCrStoreCertAddWantedFromFile(RTCRSTORE hStore, uint32_t fFlags, const char *pszFilename, 452 PCRTCRCERTWANTED paWanted, size_t cWanted, bool *pafFound, PRTERRINFO pErrInfo) 453 { 454 /* 455 * Validate input a little. 456 */ 457 AssertReturn(!(fFlags & ~(RTCRCERTCTX_F_ADD_IF_NOT_FOUND | RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR)), VERR_INVALID_FLAGS); 458 fFlags |= RTCRCERTCTX_F_ADD_IF_NOT_FOUND; /* forced */ 459 460 AssertReturn(cWanted, VERR_NOT_FOUND); 461 for (uint32_t i = 0; i < cWanted; i++) 462 { 463 AssertReturn(!paWanted[i].pszSubject || *paWanted[i].pszSubject, VERR_INVALID_PARAMETER); 464 AssertReturn( paWanted[i].pszSubject 465 || paWanted[i].fSha1Fingerprint 466 || paWanted[i].fSha512Fingerprint, 467 VERR_INVALID_PARAMETER); 468 } 469 470 /* 471 * Make sure we've got a result array. 472 */ 473 bool *pafFoundFree = NULL; 474 if (!pafFound) 475 { 476 pafFound = pafFoundFree = (bool *)RTMemTmpAllocZ(sizeof(bool) * cWanted); 477 AssertReturn(pafFound, VERR_NO_TMP_MEMORY); 478 } 479 480 size_t cbContent; 481 void *pvContent; 482 int rc = RTFileReadAllEx(pszFilename, 0, 64U*_1M, RTFILE_RDALL_O_DENY_WRITE, &pvContent, &cbContent); 483 if (RT_SUCCESS(rc)) 484 { 485 /* 486 * Is it a java key store file? If so, load it into a tmp store 487 * which we can search. Don't want to duplicate the JKS reader code. 488 */ 489 if ( cbContent > 32 490 && ((uint32_t const *)pvContent)[0] == RT_H2BE_U32_C(UINT32_C(0xfeedfeed)) /* magic */ 491 && ((uint32_t const *)pvContent)[1] == RT_H2BE_U32_C(UINT32_C(0x00000002)) /* version */ ) 492 { 493 RTCRSTORE hTmpStore; 494 rc = RTCrStoreCreateInMem(&hTmpStore, 64); 495 if (RT_SUCCESS(rc)) 496 { 497 rc = RTCrStoreCertAddFromJavaKeyStoreInMem(hStore, fFlags, pvContent, cbContent, pszFilename, pErrInfo); 498 if (RT_SUCCESS(rc)) 499 rc = RTCrStoreCertAddWantedFromStore(hStore, fFlags, hTmpStore, paWanted, cWanted, pafFound); 500 RTCrStoreRelease(hTmpStore); 501 } 502 else 503 rc = RTErrInfoSet(pErrInfo, rc, "Error creating temporary crypto store"); 504 } 505 /* 506 * No assume PEM or DER encoded binary certificate. Inspect them one by one. 507 */ 508 else 509 { 510 PCRTCRPEMSECTION pSectionHead; 511 rc = RTCrPemParseContent(pvContent, cbContent, 512 (fFlags & RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR) 513 ? RTCRPEMREADFILE_F_CONTINUE_ON_ENCODING_ERROR : 0, 514 g_aX509CertificateMarkers, RT_ELEMENTS(g_aX509CertificateMarkers), 515 &pSectionHead, pErrInfo); 516 if (RT_SUCCESS(rc)) 517 { 518 rc = VWRN_NOT_FOUND; 519 for (PCRTCRPEMSECTION pCurSec = pSectionHead; pCurSec; pCurSec = pCurSec->pNext) 520 { 521 if (!pCurSec->cbData) 522 continue; 523 524 /* 525 * See if this is a binary blob we might be interested in. 526 */ 527 uint8_t abSha1[RTSHA1_HASH_SIZE]; 528 RTSha1(pCurSec->pbData, pCurSec->cbData, abSha1); 529 uint8_t abSha512[RTSHA512_HASH_SIZE]; 530 RTSha1(pCurSec->pbData, pCurSec->cbData, abSha512); 531 if (!rtCrStoreIsCertWanted(paWanted, cWanted, pafFound, pCurSec->cbData, abSha1, abSha512, NULL)) 532 continue; 533 534 /* 535 * Decode the certificate so we can match the subject string. 536 */ 537 RTASN1CURSORPRIMARY Cursor; 538 RTAsn1CursorInitPrimary(&Cursor, pCurSec->pbData, (uint32_t)pCurSec->cbData, 539 !RTErrInfoIsSet(pErrInfo) ? pErrInfo : NULL, 540 &g_RTAsn1DefaultAllocator, RTASN1CURSOR_FLAGS_DER, "InMem"); 541 RTCRX509CERTIFICATE X509Cert; 542 int rc2 = RTCrX509Certificate_DecodeAsn1(&Cursor.Cursor, 0, &X509Cert, "Cert"); 543 if (RT_SUCCESS(rc2)) 544 { 545 rc2 = RTCrX509Certificate_CheckSanity(&X509Cert, 0, !RTErrInfoIsSet(pErrInfo) ? pErrInfo : NULL, "Cert"); 546 if (RT_SUCCESS(rc2)) 547 { 548 if (rtCrStoreIsCertWanted(paWanted, cWanted, pafFound, pCurSec->cbData, abSha1, abSha512, &X509Cert)) 549 { 550 /* 551 * The certificate is wanted, now add it to the store. 552 */ 553 rc2 = RTCrStoreCertAddEncoded(hStore, 554 RTCRCERTCTX_F_ENC_X509_DER 555 | (fFlags & RTCRCERTCTX_F_ADD_IF_NOT_FOUND), 556 pCurSec->pbData, pCurSec->cbData, 557 !RTErrInfoIsSet(pErrInfo) ? pErrInfo : NULL); 558 if (RT_SUCCESS(rc2)) 559 { 560 /* 561 * Mark it as found, stop if we've found all. 562 */ 563 if (rtCrStoreMarkCertFound(pafFound, paWanted, cWanted, 564 pCurSec->cbData, abSha1, abSha512, &X509Cert)) 565 { 566 RTAsn1VtDelete(&X509Cert.SeqCore.Asn1Core); 567 rc = VINF_SUCCESS; 568 break; 569 } 570 } 571 } 572 } 573 else 574 Assert(!pErrInfo || RTErrInfoIsSet(pErrInfo)); 575 RTAsn1VtDelete(&X509Cert.SeqCore.Asn1Core); 576 } 577 else if (!RTErrInfoIsSet(pErrInfo)) 578 RTErrInfoSetF(pErrInfo, rc2, "RTCrX509Certificate_DecodeAsn1 failed"); 579 580 /* 581 * Stop on error, if requested. Otherwise, let pErrInfo keep it. 582 */ 583 if (RT_FAILURE(rc2) && !(fFlags & RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR)) 584 { 585 rc = rc2; 586 break; 587 } 588 } /* For each PEM section. */ 589 590 RTCrPemFreeSections(pSectionHead); 591 } 592 } 593 RTFileReadAllFree(pvContent, cbContent); 594 } 595 else 596 rc = RTErrInfoSetF(pErrInfo, rc, "RTFileReadAllEx failed with %Rrc on '%s'", rc, pszFilename); 597 598 if (pafFoundFree) 599 RTMemTmpFree(pafFoundFree); 600 return rc; 601 } 602 RT_EXPORT_SYMBOL(RTCrStoreCertAddWantedFromFile); 39 603 40 604 … … 88 652 if (cchPath > 0) 89 653 { 90 size_t const cb Filename = sizeof(szPath) - cchPath;654 size_t const cbMaxFilename = sizeof(szPath) - cchPath; 91 655 92 656 /* … … 109 673 if (RT_SUCCESS(rc2)) 110 674 { 111 if ( !RTDirEntryIsStdDotLink(&u.DirEntry) 675 if ( ( u.DirEntry.enmType == RTDIRENTRYTYPE_FILE 676 || u.DirEntry.enmType == RTDIRENTRYTYPE_SYMLINK 677 || ( u.DirEntry.enmType == RTDIRENTRYTYPE_UNKNOWN 678 && !RTDirEntryIsStdDotLink(&u.DirEntry)) ) 112 679 && rtCrStoreIsSuffixMatch(&u.DirEntry, paSuffixes, cSuffixes) ) 113 680 { 114 if (u.DirEntry.cbName < cb Filename)681 if (u.DirEntry.cbName < cbMaxFilename) 115 682 { 116 683 memcpy(&szPath[cchPath], u.DirEntry.szName, u.DirEntry.cbName + 1); … … 131 698 } 132 699 } 133 else if ( u.DirEntry.enmType == RTDIRENTRYTYPE_FILE 134 || u.DirEntry.enmType == RTDIRENTRYTYPE_SYMLINK 135 || u.DirEntry.enmType == RTDIRENTRYTYPE_UNKNOWN) 700 else 136 701 { 137 702 rc = RTErrInfoAddF(pErrInfo, VERR_FILENAME_TOO_LONG, … … 160 725 return rc; 161 726 } 162 163 727 RT_EXPORT_SYMBOL(RTCrStoreCertAddFromDir); 728 729 730 RTDECL(int) RTCrStoreCertAddWantedFromDir(RTCRSTORE hStore, uint32_t fFlags, 731 const char *pszDir, PCRTSTRTUPLE paSuffixes, size_t cSuffixes, 732 PCRTCRCERTWANTED paWanted, size_t cWanted, bool *pafFound, PRTERRINFO pErrInfo) 733 { 734 /* 735 * Validate input a little. 736 */ 737 AssertReturn(*pszDir, VERR_PATH_ZERO_LENGTH); 738 AssertReturn(!(fFlags & ~(RTCRCERTCTX_F_ADD_IF_NOT_FOUND | RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR)), VERR_INVALID_FLAGS); 739 fFlags |= RTCRCERTCTX_F_ADD_IF_NOT_FOUND; /* forced */ 740 741 AssertReturn(cWanted, VERR_NOT_FOUND); 742 for (uint32_t i = 0; i < cWanted; i++) 743 { 744 AssertReturn(!paWanted[i].pszSubject || *paWanted[i].pszSubject, VERR_INVALID_PARAMETER); 745 AssertReturn( paWanted[i].pszSubject 746 || paWanted[i].fSha1Fingerprint 747 || paWanted[i].fSha512Fingerprint, 748 VERR_INVALID_PARAMETER); 749 } 750 751 /* 752 * Prepare for constructing path to the files in the directory, so that we 753 * can open them. 754 */ 755 char szPath[RTPATH_MAX]; 756 int rc = RTStrCopy(szPath, sizeof(szPath), pszDir); 757 if (RT_SUCCESS(rc)) 758 { 759 size_t cchPath = RTPathEnsureTrailingSeparator(szPath, sizeof(szPath)); 760 if (cchPath > 0) 761 { 762 size_t const cbMaxFilename = sizeof(szPath) - cchPath; 763 764 /* 765 * Enumerate the directory. 766 */ 767 PRTDIR hDir; 768 rc = RTDirOpen(&hDir, pszDir); 769 if (RT_SUCCESS(rc)) 770 { 771 rc = VWRN_NOT_FOUND; 772 for (;;) 773 { 774 /* Read the next entry. */ 775 union 776 { 777 RTDIRENTRY DirEntry; 778 uint8_t abPadding[RT_OFFSETOF(RTDIRENTRY, szName) + RTPATH_MAX]; 779 } u; 780 size_t cbEntry = sizeof(u); 781 int rc2 = RTDirRead(hDir, &u.DirEntry, &cbEntry); 782 if (RT_SUCCESS(rc2)) 783 { 784 if ( ( u.DirEntry.enmType == RTDIRENTRYTYPE_FILE 785 || u.DirEntry.enmType == RTDIRENTRYTYPE_SYMLINK 786 || ( u.DirEntry.enmType == RTDIRENTRYTYPE_UNKNOWN 787 && !RTDirEntryIsStdDotLink(&u.DirEntry)) ) 788 && rtCrStoreIsSuffixMatch(&u.DirEntry, paSuffixes, cSuffixes) ) 789 { 790 if (u.DirEntry.cbName < cbMaxFilename) 791 { 792 memcpy(&szPath[cchPath], u.DirEntry.szName, u.DirEntry.cbName); 793 szPath[cchPath + u.DirEntry.cbName] = '\0'; 794 if (u.DirEntry.enmType != RTDIRENTRYTYPE_FILE) 795 RTDirQueryUnknownType(szPath, true /*fFollowSymlinks*/, &u.DirEntry.enmType); 796 if (u.DirEntry.enmType == RTDIRENTRYTYPE_FILE) 797 { 798 rc2 = RTCrStoreCertAddWantedFromFile(hStore, fFlags, szPath, 799 paWanted, cWanted, pafFound, pErrInfo); 800 if (rc2 == VINF_SUCCESS) 801 { 802 Assert(rtCrStoreAllDone(pafFound, cWanted)); 803 if (RT_SUCCESS(rc)) 804 rc = VINF_SUCCESS; 805 break; 806 } 807 if (RT_FAILURE(rc2) && !(fFlags & RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR)) 808 { 809 rc = rc2; 810 break; 811 } 812 } 813 } 814 else 815 { 816 /* 817 * pErrInfo keeps the status code unless it's fatal. 818 */ 819 RTErrInfoAddF(pErrInfo, VERR_FILENAME_TOO_LONG, 820 " Too long filename (%u bytes)", u.DirEntry.cbName); 821 if (!(fFlags & RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR)) 822 { 823 rc = VERR_FILENAME_TOO_LONG; 824 break; 825 } 826 } 827 } 828 } 829 else 830 { 831 if (rc2 != VERR_NO_MORE_FILES) 832 { 833 RTErrInfoAddF(pErrInfo, rc2, "RTDirRead failed: %Rrc", rc2); 834 if (!(fFlags & RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR)) 835 rc = rc2; 836 } 837 break; 838 } 839 } 840 RTDirClose(hDir); 841 } 842 } 843 else 844 rc = VERR_FILENAME_TOO_LONG; 845 } 846 return rc; 847 } 848 RT_EXPORT_SYMBOL(RTCrStoreCertAddWantedFromDir); 849 -
trunk/src/VBox/Runtime/common/crypto/store.cpp
r57572 r57613 288 288 289 289 290 RTDECL(uint32_t) RTCrStoreCertCount(RTCRSTORE hStore) 291 { 292 PRTCRSTOREINT pThis = (PRTCRSTOREINT)hStore; 293 AssertPtrReturn(pThis, UINT32_MAX); 294 AssertReturn(pThis->u32Magic == RTCRSTOREINT_MAGIC, UINT32_MAX); 295 296 RTCRSTORECERTSEARCH Search; 297 int rc = pThis->pProvider->pfnCertFindAll(pThis->pvProvider, &Search); 298 AssertRCReturn(rc, UINT32_MAX); 299 300 301 uint32_t cCerts = 0; 302 PCRTCRCERTCTX pCur; 303 while ((pCur = pThis->pProvider->pfnCertSearchNext(pThis->pvProvider, &Search)) != NULL) 304 { 305 RTCrCertCtxRelease(pCur); 306 cCerts++; 307 } 308 309 return cCerts; 310 } 311 312 290 313 #ifdef IPRT_WITH_OPENSSL 291 314 /* -
trunk/src/VBox/Runtime/common/crypto/x509-internal.h
r56290 r57613 29 29 #define ___common_crypto_x509_internal_h 30 30 31 #include <iprt/crypto/pem.h> 32 extern RTCRPEMMARKER const g_aX509CertificateMarkers[3]; 33 31 34 #define RTASN1TMPL_TEMPLATE_FILE "../common/crypto/x509-template.h" 32 35 #include <iprt/asn1-generator-internal-header.h> -
trunk/src/VBox/Runtime/common/misc/http.cpp
r57577 r57613 32 32 #include "internal/iprt.h" 33 33 34 #include <iprt/asm.h> 34 35 #include <iprt/assert.h> 36 #include <iprt/crypto/store.h> 35 37 #include <iprt/env.h> 36 38 #include <iprt/err.h> 39 #include <iprt/file.h> 37 40 #include <iprt/mem.h> 41 #include <iprt/path.h> 42 #include <iprt/stream.h> 38 43 #include <iprt/string.h> 39 #include <iprt/file.h> 40 #include <iprt/stream.h>44 45 #include "internal/magics.h" 41 46 42 47 #include <curl/curl.h> 43 #include "internal/magics.h"44 48 45 49 … … 47 51 * Structures and Typedefs * 48 52 *********************************************************************************************************************************/ 53 /** 54 * Internal HTTP client instance. 55 */ 49 56 typedef struct RTHTTPINTERNAL 50 57 { … … 52 59 uint32_t u32Magic; 53 60 /** cURL handle. */ 54 CURL *pCurl;61 CURL *pCurl; 55 62 /** The last response code. */ 56 63 long lLastResp; 57 /** custom headers */ 58 struct curl_slist *pHeaders; 59 /** CA certificate for HTTPS authentication check. */ 60 char *pcszCAFile; 64 /** Custom headers/ */ 65 struct curl_slist *pHeaders; 66 /** CA certificate file for HTTPS authentication. */ 67 char *pszCaFile; 68 /** Whether to delete the CA on destruction. */ 69 bool fDeleteCaFile; 61 70 /** Abort the current HTTP request if true. */ 62 bool fAbort; 71 bool volatile fAbort; 72 /** Set if someone is preforming an HTTP operation. */ 73 bool volatile fBusy; 63 74 /** The location field for 301 responses. */ 64 char *pszRedirLocation; 75 char *pszRedirLocation; 76 77 /** Output callback data. */ 78 union 79 { 80 /** For file destination. */ 81 RTFILE hFile; 82 /** For memory destination. */ 83 struct 84 { 85 /** The current size (sans terminator char). */ 86 size_t cb; 87 /** The currently allocated size. */ 88 size_t cbAllocated; 89 /** Pointer to the buffer. */ 90 uint8_t *pb; 91 } Mem; 92 } Output; 93 /** Output callback status. */ 94 int rcOutput; 95 /** Download size hint set by the progress callback. */ 96 uint64_t cbDownloadHint; 65 97 } RTHTTPINTERNAL; 98 /** Pointer to an internal HTTP client instance. */ 66 99 typedef RTHTTPINTERNAL *PRTHTTPINTERNAL; 67 68 typedef struct RTHTTPMEMCHUNK69 {70 uint8_t *pu8Mem;71 size_t cb;72 } RTHTTPMEMCHUNK;73 typedef RTHTTPMEMCHUNK *PRTHTTPMEMCHUNK;74 100 75 101 … … 77 103 * Defined Constants And Macros * 78 104 *********************************************************************************************************************************/ 79 #define CURL_FAILED(rcCurl) (RT_UNLIKELY(rcCurl != CURLE_OK)) 105 /** @def RTHTTP_MAX_MEM_DOWNLOAD 106 * The max size we are allowed to download to a memory buffer. 107 * 108 * @remarks The minus 1 is for the trailing zero terminator we always add. 109 */ 110 #if ARCH_BITS == 64 111 # define RTHTTP_MAX_MEM_DOWNLOAD_SIZE (UINT32_C(64)*_1M - 1) 112 #else 113 # define RTHTTP_MAX_MEM_DOWNLOAD_SIZE (UINT32_C(32)*_1M - 1) 114 #endif 115 116 /** Checks whether a cURL return code indicates success. */ 117 #define CURL_SUCCESS(rcCurl) RT_LIKELY(rcCurl == CURLE_OK) 118 /** Checks whether a cURL return code indicates failure. */ 119 #define CURL_FAILURE(rcCurl) RT_UNLIKELY(rcCurl != CURLE_OK) 80 120 81 121 /** Validates a handle and returns VERR_INVALID_HANDLE if not valid. */ … … 97 137 98 138 139 /********************************************************************************************************************************* 140 * Internal Functions * 141 *********************************************************************************************************************************/ 142 static void rtHttpUnsetCaFile(PRTHTTPINTERNAL pThis); 143 144 99 145 RTR3DECL(int) RTHttpCreate(PRTHTTP phHttp) 100 146 { 101 147 AssertPtrReturn(phHttp, VERR_INVALID_PARAMETER); 102 148 149 /** @todo r=bird: rainy day: curl_global_init is not thread safe, only a 150 * problem if multiple threads get here at the same time. */ 151 int rc = VERR_HTTP_INIT_FAILED; 103 152 CURLcode rcCurl = curl_global_init(CURL_GLOBAL_ALL); 104 if (CURL_FAILED(rcCurl)) 105 return VERR_HTTP_INIT_FAILED; 106 107 CURL *pCurl = curl_easy_init(); 108 if (!pCurl) 109 return VERR_HTTP_INIT_FAILED; 110 111 PRTHTTPINTERNAL pHttpInt = (PRTHTTPINTERNAL)RTMemAllocZ(sizeof(RTHTTPINTERNAL)); 112 if (!pHttpInt) 113 return VERR_NO_MEMORY; 114 115 pHttpInt->u32Magic = RTHTTP_MAGIC; 116 pHttpInt->pCurl = pCurl; 117 118 *phHttp = (RTHTTP)pHttpInt; 153 if (!CURL_FAILURE(rcCurl)) 154 { 155 CURL *pCurl = curl_easy_init(); 156 if (pCurl) 157 { 158 PRTHTTPINTERNAL pThis = (PRTHTTPINTERNAL)RTMemAllocZ(sizeof(RTHTTPINTERNAL)); 159 if (pThis) 160 { 161 pThis->u32Magic = RTHTTP_MAGIC; 162 pThis->pCurl = pCurl; 163 164 *phHttp = (RTHTTP)pThis; 165 166 return VINF_SUCCESS; 167 } 168 rc = VERR_NO_MEMORY; 169 } 170 else 171 rc = VERR_HTTP_INIT_FAILED; 172 } 173 curl_global_cleanup(); 174 return rc; 175 } 176 177 178 RTR3DECL(void) RTHttpDestroy(RTHTTP hHttp) 179 { 180 if (hHttp == NIL_RTHTTP) 181 return; 182 183 PRTHTTPINTERNAL pThis = hHttp; 184 RTHTTP_VALID_RETURN_VOID(pThis); 185 186 Assert(!pThis->fBusy); 187 188 pThis->u32Magic = RTHTTP_MAGIC_DEAD; 189 190 curl_easy_cleanup(pThis->pCurl); 191 pThis->pCurl = NULL; 192 193 if (pThis->pHeaders) 194 curl_slist_free_all(pThis->pHeaders); 195 196 rtHttpUnsetCaFile(pThis); 197 Assert(!pThis->pszCaFile); 198 199 if (pThis->pszRedirLocation) 200 RTStrFree(pThis->pszRedirLocation); 201 202 RTMemFree(pThis); 203 204 curl_global_cleanup(); 205 } 206 207 208 RTR3DECL(int) RTHttpAbort(RTHTTP hHttp) 209 { 210 PRTHTTPINTERNAL pThis = hHttp; 211 RTHTTP_VALID_RETURN(pThis); 212 213 pThis->fAbort = true; 119 214 120 215 return VINF_SUCCESS; … … 122 217 123 218 124 RTR3DECL(void) RTHttpDestroy(RTHTTP hHttp)125 {126 if (!hHttp)127 return;128 129 PRTHTTPINTERNAL pHttpInt = hHttp;130 RTHTTP_VALID_RETURN_VOID(pHttpInt);131 132 pHttpInt->u32Magic = RTHTTP_MAGIC_DEAD;133 134 curl_easy_cleanup(pHttpInt->pCurl);135 136 if (pHttpInt->pHeaders)137 curl_slist_free_all(pHttpInt->pHeaders);138 139 if (pHttpInt->pcszCAFile)140 RTStrFree(pHttpInt->pcszCAFile);141 142 if (pHttpInt->pszRedirLocation)143 RTStrFree(pHttpInt->pszRedirLocation);144 145 RTMemFree(pHttpInt);146 147 curl_global_cleanup();148 }149 150 151 static DECLCALLBACK(size_t) rtHttpWriteData(void *pvBuf, size_t cb, size_t n, void *pvUser)152 {153 PRTHTTPMEMCHUNK pMem = (PRTHTTPMEMCHUNK)pvUser;154 size_t cbAll = cb * n;155 156 pMem->pu8Mem = (uint8_t*)RTMemRealloc(pMem->pu8Mem, pMem->cb + cbAll + 1);157 if (pMem->pu8Mem)158 {159 memcpy(&pMem->pu8Mem[pMem->cb], pvBuf, cbAll);160 pMem->cb += cbAll;161 pMem->pu8Mem[pMem->cb] = '\0';162 }163 return cbAll;164 }165 166 167 static DECLCALLBACK(int) rtHttpProgress(void *pData, double DlTotal, double DlNow, double UlTotal, double UlNow)168 {169 PRTHTTPINTERNAL pHttpInt = (PRTHTTPINTERNAL)pData;170 AssertReturn(pHttpInt->u32Magic == RTHTTP_MAGIC, 1);171 172 return pHttpInt->fAbort ? 1 : 0;173 }174 175 176 RTR3DECL(int) RTHttpAbort(RTHTTP hHttp)177 {178 PRTHTTPINTERNAL pHttpInt = hHttp;179 RTHTTP_VALID_RETURN(pHttpInt);180 181 pHttpInt->fAbort = true;182 183 return VINF_SUCCESS;184 }185 186 187 219 RTR3DECL(int) RTHttpGetRedirLocation(RTHTTP hHttp, char **ppszRedirLocation) 188 220 { 189 PRTHTTPINTERNAL pHttpInt = hHttp; 190 RTHTTP_VALID_RETURN(pHttpInt); 191 192 if (!pHttpInt->pszRedirLocation) 221 PRTHTTPINTERNAL pThis = hHttp; 222 RTHTTP_VALID_RETURN(pThis); 223 Assert(!pThis->fBusy); 224 225 if (!pThis->pszRedirLocation) 193 226 return VERR_HTTP_NOT_FOUND; 194 227 195 *ppszRedirLocation = RTStrDup(pHttpInt->pszRedirLocation); 196 return VINF_SUCCESS; 228 return RTStrDupEx(ppszRedirLocation, pThis->pszRedirLocation); 197 229 } 198 230 … … 200 232 RTR3DECL(int) RTHttpUseSystemProxySettings(RTHTTP hHttp) 201 233 { 202 PRTHTTPINTERNAL p HttpInt= hHttp;203 RTHTTP_VALID_RETURN(p HttpInt);234 PRTHTTPINTERNAL pThis = hHttp; 235 RTHTTP_VALID_RETURN(pThis); 204 236 205 237 /* … … 213 245 if (!strncmp(szProxy, RT_STR_TUPLE("http://"))) 214 246 { 215 rcCurl = curl_easy_setopt(p HttpInt->pCurl, CURLOPT_PROXY, &szProxy[sizeof("http://") - 1]);216 if (CURL_FAIL ED(rcCurl))247 rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_PROXY, &szProxy[sizeof("http://") - 1]); 248 if (CURL_FAILURE(rcCurl)) 217 249 return VERR_INVALID_PARAMETER; 218 rcCurl = curl_easy_setopt(p HttpInt->pCurl, CURLOPT_PROXYPORT, 80);219 if (CURL_FAIL ED(rcCurl))250 rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_PROXYPORT, 80); 251 if (CURL_FAILURE(rcCurl)) 220 252 return VERR_INVALID_PARAMETER; 221 253 } 222 254 else 223 255 { 224 rcCurl = curl_easy_setopt(p HttpInt->pCurl, CURLOPT_PROXY, &szProxy[sizeof("http://") - 1]);225 if (CURL_FAIL ED(rcCurl))256 rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_PROXY, &szProxy[sizeof("http://") - 1]); 257 if (CURL_FAILURE(rcCurl)) 226 258 return VERR_INVALID_PARAMETER; 227 259 } … … 237 269 const char *pcszProxyUser, const char *pcszProxyPwd) 238 270 { 239 PRTHTTPINTERNAL p HttpInt= hHttp;240 RTHTTP_VALID_RETURN(p HttpInt);271 PRTHTTPINTERNAL pThis = hHttp; 272 RTHTTP_VALID_RETURN(pThis); 241 273 AssertPtrReturn(pcszProxy, VERR_INVALID_PARAMETER); 242 274 243 int rcCurl = curl_easy_setopt(p HttpInt->pCurl, CURLOPT_PROXY, pcszProxy);244 if (CURL_FAIL ED(rcCurl))275 int rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_PROXY, pcszProxy); 276 if (CURL_FAILURE(rcCurl)) 245 277 return VERR_INVALID_PARAMETER; 246 278 247 279 if (uPort != 0) 248 280 { 249 rcCurl = curl_easy_setopt(p HttpInt->pCurl, CURLOPT_PROXYPORT, (long)uPort);250 if (CURL_FAIL ED(rcCurl))281 rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_PROXYPORT, (long)uPort); 282 if (CURL_FAILURE(rcCurl)) 251 283 return VERR_INVALID_PARAMETER; 252 284 } … … 254 286 if (pcszProxyUser && pcszProxyPwd) 255 287 { 256 rcCurl = curl_easy_setopt(p HttpInt->pCurl, CURLOPT_PROXYUSERNAME, pcszProxyUser);257 if (CURL_FAIL ED(rcCurl))288 rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_PROXYUSERNAME, pcszProxyUser); 289 if (CURL_FAILURE(rcCurl)) 258 290 return VERR_INVALID_PARAMETER; 259 291 260 rcCurl = curl_easy_setopt(p HttpInt->pCurl, CURLOPT_PROXYPASSWORD, pcszProxyPwd);261 if (CURL_FAIL ED(rcCurl))292 rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_PROXYPASSWORD, pcszProxyPwd); 293 if (CURL_FAILURE(rcCurl)) 262 294 return VERR_INVALID_PARAMETER; 263 295 } … … 269 301 RTR3DECL(int) RTHttpSetHeaders(RTHTTP hHttp, size_t cHeaders, const char * const *papszHeaders) 270 302 { 271 PRTHTTPINTERNAL p HttpInt= hHttp;272 RTHTTP_VALID_RETURN(p HttpInt);303 PRTHTTPINTERNAL pThis = hHttp; 304 RTHTTP_VALID_RETURN(pThis); 273 305 274 306 if (!cHeaders) 275 307 { 276 if (p HttpInt->pHeaders)277 curl_slist_free_all(p HttpInt->pHeaders);278 p HttpInt->pHeaders = 0;308 if (pThis->pHeaders) 309 curl_slist_free_all(pThis->pHeaders); 310 pThis->pHeaders = 0; 279 311 return VINF_SUCCESS; 280 312 } … … 284 316 pHeaders = curl_slist_append(pHeaders, papszHeaders[i]); 285 317 286 p HttpInt->pHeaders = pHeaders;287 int rcCurl = curl_easy_setopt(p HttpInt->pCurl, CURLOPT_HTTPHEADER, pHeaders);288 if (CURL_FAIL ED(rcCurl))318 pThis->pHeaders = pHeaders; 319 int rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_HTTPHEADER, pHeaders); 320 if (CURL_FAILURE(rcCurl)) 289 321 return VERR_INVALID_PARAMETER; 290 322 … … 293 325 294 326 295 RTR3DECL(int) RTHttpSetCAFile(RTHTTP hHttp, const char *pcszCAFile) 296 { 297 PRTHTTPINTERNAL pHttpInt = hHttp; 298 RTHTTP_VALID_RETURN(pHttpInt); 299 300 if (pHttpInt->pcszCAFile) 301 RTStrFree(pHttpInt->pcszCAFile); 302 pHttpInt->pcszCAFile = RTStrDup(pcszCAFile); 303 if (!pHttpInt->pcszCAFile) 304 return VERR_NO_MEMORY; 305 327 /** 328 * Set the CA file to NULL, deleting any temporary file if necessary. 329 * 330 * @param pThis The HTTP/HTTPS client instance. 331 */ 332 static void rtHttpUnsetCaFile(PRTHTTPINTERNAL pThis) 333 { 334 if (pThis->pszCaFile) 335 { 336 if (pThis->fDeleteCaFile) 337 { 338 int rc2 = RTFileDelete(pThis->pszCaFile); 339 AssertMsg(RT_SUCCESS(rc2) || !RTFileExists(pThis->pszCaFile), ("rc=%Rrc '%s'\n", rc2, pThis->pszCaFile)); 340 } 341 RTStrFree(pThis->pszCaFile); 342 pThis->pszCaFile = NULL; 343 } 344 } 345 346 347 RTR3DECL(int) RTHttpSetCAFile(RTHTTP hHttp, const char *pszCaFile) 348 { 349 PRTHTTPINTERNAL pThis = hHttp; 350 RTHTTP_VALID_RETURN(pThis); 351 352 rtHttpUnsetCaFile(pThis); 353 354 pThis->fDeleteCaFile = false; 355 if (pszCaFile) 356 return RTStrDupEx(&pThis->pszCaFile, pszCaFile); 306 357 return VINF_SUCCESS; 307 358 } 359 360 361 RTR3DECL(int) RTHttpUseTemporaryCaFile(RTHTTP hHttp, PRTERRINFO pErrInfo) 362 { 363 PRTHTTPINTERNAL pThis = hHttp; 364 RTHTTP_VALID_RETURN(pThis); 365 366 /* 367 * Create a temporary file. 368 */ 369 int rc = VERR_NO_STR_MEMORY; 370 char *pszCaFile = RTStrAlloc(RTPATH_MAX); 371 if (pszCaFile) 372 { 373 RTFILE hFile; 374 rc = RTFileOpenTemp(&hFile, pszCaFile, RTPATH_MAX, 375 RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE | (0600 << RTFILE_O_CREATE_MODE_SHIFT)); 376 if (RT_SUCCESS(rc)) 377 { 378 /* 379 * Gather certificates into a temporary store and export them to the temporary file. 380 */ 381 RTCRSTORE hStore; 382 rc = RTCrStoreCreateInMem(&hStore, 256); 383 if (RT_SUCCESS(rc)) 384 { 385 rc = RTHttpGatherCaCertsInStore(hStore, 0 /*fFlags*/, pErrInfo); 386 if (RT_SUCCESS(rc)) 387 /** @todo Consider adding an API for exporting to a RTFILE... */ 388 rc = RTCrStoreCertExportAsPem(hStore, 0 /*fFlags*/, pszCaFile); 389 RTCrStoreRelease(hStore); 390 } 391 RTFileClose(hFile); 392 if (RT_SUCCESS(rc)) 393 { 394 /* 395 * Set the CA file for the instance. 396 */ 397 rtHttpUnsetCaFile(pThis); 398 399 pThis->fDeleteCaFile = true; 400 pThis->pszCaFile = pszCaFile; 401 return VINF_SUCCESS; 402 } 403 404 int rc2 = RTFileDelete(pszCaFile); 405 AssertRC(rc2); 406 } 407 else 408 RTErrInfoAddF(pErrInfo, rc, "Error creating temorary file: %Rrc", rc); 409 410 RTStrFree(pszCaFile); 411 } 412 return rc; 413 } 414 415 416 RTR3DECL(int) RTHttpGatherCaCertsInStore(RTCRSTORE hStore, uint32_t fFlags, PRTERRINFO pErrInfo) 417 { 418 uint32_t const cBefore = RTCrStoreCertCount(hStore); 419 AssertReturn(cBefore != UINT32_MAX, VERR_INVALID_HANDLE); 420 421 /* 422 * Add the user store, quitely ignoring any errors. 423 */ 424 RTCRSTORE hSrcStore; 425 int rcUser = RTCrStoreCreateSnapshotById(&hSrcStore, RTCRSTOREID_USER_TRUSTED_CAS_AND_CERTIFICATES, pErrInfo); 426 if (RT_SUCCESS(rcUser)) 427 { 428 rcUser = RTCrStoreCertAddFromStore(hStore, RTCRCERTCTX_F_ADD_IF_NOT_FOUND | RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR, 429 hSrcStore); 430 RTCrStoreRelease(hSrcStore); 431 } 432 433 /* 434 * Ditto for the system store. 435 */ 436 int rcSystem = RTCrStoreCreateSnapshotById(&hSrcStore, RTCRSTOREID_USER_TRUSTED_CAS_AND_CERTIFICATES, pErrInfo); 437 if (RT_SUCCESS(rcSystem)) 438 { 439 rcSystem = RTCrStoreCertAddFromStore(hStore, RTCRCERTCTX_F_ADD_IF_NOT_FOUND | RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR, 440 hSrcStore); 441 RTCrStoreRelease(hSrcStore); 442 } 443 444 /* 445 * If the number of certificates increased, we consider it a success. 446 */ 447 if (RTCrStoreCertCount(hStore) > cBefore) 448 { 449 if (RT_FAILURE(rcSystem)) 450 return -rcSystem; 451 if (RT_FAILURE(rcUser)) 452 return -rcUser; 453 return rcSystem != VINF_SUCCESS ? rcSystem : rcUser; 454 } 455 456 if (RT_FAILURE(rcSystem)) 457 return rcSystem; 458 if (RT_FAILURE(rcUser)) 459 return rcSystem; 460 return VERR_NOT_FOUND; 461 } 462 463 464 RTR3DECL(int) RTHttpGatherCaCertsInFile(const char *pszCaFile, uint32_t fFlags, PRTERRINFO pErrInfo) 465 { 466 RTCRSTORE hStore; 467 int rc = RTCrStoreCreateInMem(&hStore, 256); 468 if (RT_SUCCESS(rc)) 469 { 470 rc = RTHttpGatherCaCertsInStore(hStore, fFlags, pErrInfo); 471 if (RT_SUCCESS(rc)) 472 rc = RTCrStoreCertExportAsPem(hStore, 0 /*fFlags*/, pszCaFile); 473 RTCrStoreRelease(hStore); 474 } 475 return rc; 476 } 477 308 478 309 479 … … 312 482 * 313 483 * @returns IPRT status code. 314 * @param p HttpInt HTTPinstance.315 * @param rcCurl What curl returned.316 */ 317 static int rtHttpGetCalcStatus(PRTHTTPINTERNAL p HttpInt, int rcCurl)484 * @param pThis The HTTP/HTTPS client instance. 485 * @param rcCurl What curl returned. 486 */ 487 static int rtHttpGetCalcStatus(PRTHTTPINTERNAL pThis, int rcCurl) 318 488 { 319 489 int rc = VERR_INTERNAL_ERROR; 320 490 321 if (p HttpInt->pszRedirLocation)322 { 323 RTStrFree(p HttpInt->pszRedirLocation);324 p HttpInt->pszRedirLocation = NULL;491 if (pThis->pszRedirLocation) 492 { 493 RTStrFree(pThis->pszRedirLocation); 494 pThis->pszRedirLocation = NULL; 325 495 } 326 496 if (rcCurl == CURLE_OK) 327 497 { 328 curl_easy_getinfo(p HttpInt->pCurl, CURLINFO_RESPONSE_CODE, &pHttpInt->lLastResp);329 switch (p HttpInt->lLastResp)498 curl_easy_getinfo(pThis->pCurl, CURLINFO_RESPONSE_CODE, &pThis->lLastResp); 499 switch (pThis->lLastResp) 330 500 { 331 501 case 200: … … 338 508 { 339 509 const char *pszRedirect; 340 curl_easy_getinfo(p HttpInt->pCurl, CURLINFO_REDIRECT_URL, &pszRedirect);510 curl_easy_getinfo(pThis->pCurl, CURLINFO_REDIRECT_URL, &pszRedirect); 341 511 size_t cb = strlen(pszRedirect); 342 512 if (cb > 0 && cb < 2048) 343 p HttpInt->pszRedirLocation = RTStrDup(pszRedirect);513 pThis->pszRedirLocation = RTStrDup(pszRedirect); 344 514 rc = VERR_HTTP_REDIRECTED; 345 515 break; … … 399 569 400 570 /** 571 * cURL callback for reporting progress, we use it for checking for abort. 572 */ 573 static int rtHttpProgress(void *pData, double rdTotalDownload, double rdDownloaded, double rdTotalUpload, double rdUploaded) 574 { 575 PRTHTTPINTERNAL pThis = (PRTHTTPINTERNAL)pData; 576 AssertReturn(pThis->u32Magic == RTHTTP_MAGIC, 1); 577 578 pThis->cbDownloadHint = (uint64_t)rdTotalDownload; 579 580 return pThis->fAbort ? 1 : 0; 581 } 582 583 584 /** 585 * Whether we're likely to need SSL to handle the give URL. 586 * 587 * @returns true if we need, false if we probably don't. 588 * @param pszUrl The URL. 589 */ 590 static bool rtHttpNeedSsl(const char *pszUrl) 591 { 592 return RTStrNICmp(pszUrl, RT_STR_TUPLE("https:")) == 0; 593 } 594 595 596 /** 597 * Applies recoded settings to the cURL instance before doing work. 598 * 599 * @returns IPRT status code. 600 * @param pThis The HTTP/HTTPS client instance. 601 * @param pszUrl The URL. 602 */ 603 static int rtHttpApplySettings(PRTHTTPINTERNAL pThis, const char *pszUrl) 604 { 605 /* 606 * The URL. 607 */ 608 int rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_URL, pszUrl); 609 if (CURL_FAILURE(rcCurl)) 610 return VERR_INVALID_PARAMETER; 611 612 /* 613 * Setup SSL. Can be a bit of work. 614 */ 615 rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_SSLVERSION, (long)CURL_SSLVERSION_TLSv1); 616 if (CURL_FAILURE(rcCurl)) 617 return VERR_INVALID_PARAMETER; 618 619 const char *pszCaFile = pThis->pszCaFile; 620 if ( !pszCaFile 621 && rtHttpNeedSsl(pszUrl)) 622 { 623 int rc = RTHttpUseTemporaryCaFile(pThis, NULL); 624 if (RT_SUCCESS(rc)) 625 pszCaFile = pThis->pszCaFile; 626 else 627 return rc; /* Non-portable alternative: pszCaFile = "/etc/ssl/certs/ca-certificates.crt"; */ 628 } 629 if (pszCaFile) 630 { 631 rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_CAINFO, pszCaFile); 632 if (CURL_FAILURE(rcCurl)) 633 return VERR_INTERNAL_ERROR; 634 } 635 636 /* 637 * Progress/abort. 638 */ 639 rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_PROGRESSFUNCTION, &rtHttpProgress); 640 if (CURL_FAILURE(rcCurl)) 641 return VERR_INTERNAL_ERROR; 642 rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_PROGRESSDATA, (void *)pThis); 643 if (CURL_FAILURE(rcCurl)) 644 return VERR_INTERNAL_ERROR; 645 rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_NOPROGRESS, (long)0); 646 if (CURL_FAILURE(rcCurl)) 647 return VERR_INTERNAL_ERROR; 648 649 return VINF_SUCCESS; 650 } 651 652 653 /** 654 * cURL callback for writing data. 655 */ 656 static size_t rtHttpWriteData(void *pvBuf, size_t cbUnit, size_t cUnits, void *pvUser) 657 { 658 PRTHTTPINTERNAL pThis = (PRTHTTPINTERNAL)pvUser; 659 660 /* 661 * Do max size and overflow checks. 662 */ 663 size_t const cbToAppend = cbUnit * cUnits; 664 size_t const cbCurSize = pThis->Output.Mem.cb; 665 size_t const cbNewSize = cbCurSize + cbToAppend; 666 if ( cbToAppend < RTHTTP_MAX_MEM_DOWNLOAD_SIZE 667 && cbNewSize < RTHTTP_MAX_MEM_DOWNLOAD_SIZE) 668 { 669 if (cbNewSize + 1 <= pThis->Output.Mem.cbAllocated) 670 { 671 memcpy(&pThis->Output.Mem.pb[cbCurSize], pvBuf, cbToAppend); 672 pThis->Output.Mem.cb = cbNewSize; 673 pThis->Output.Mem.pb[cbNewSize] = '\0'; 674 return VINF_SUCCESS; 675 } 676 677 /* 678 * We need to reallocate the output buffer. 679 */ 680 /** @todo this could do with a better strategy wrt growth. */ 681 size_t cbAlloc = RT_ALIGN_Z(cbNewSize + 1, 64); 682 if ( cbAlloc <= pThis->cbDownloadHint 683 && pThis->cbDownloadHint < RTHTTP_MAX_MEM_DOWNLOAD_SIZE) 684 cbAlloc = RT_ALIGN_Z(pThis->cbDownloadHint + 1, 64); 685 686 uint8_t *pbNew = (uint8_t *)RTMemRealloc(pThis->Output.Mem.pb, cbAlloc); 687 if (pbNew) 688 { 689 memcpy(&pbNew[cbCurSize], pvBuf, cbToAppend); 690 pbNew[cbNewSize] = '\0'; 691 692 pThis->Output.Mem.cbAllocated = cbAlloc; 693 pThis->Output.Mem.pb = pbNew; 694 pThis->Output.Mem.cb = cbNewSize; 695 return VINF_SUCCESS; 696 } 697 698 pThis->rcOutput = VERR_NO_MEMORY; 699 } 700 else 701 pThis->rcOutput = VERR_TOO_MUCH_DATA; 702 703 /* 704 * Failure - abort. 705 */ 706 RTMemFree(pThis->Output.Mem.pb); 707 pThis->Output.Mem.pb = NULL; 708 pThis->Output.Mem.cb = RTHTTP_MAX_MEM_DOWNLOAD_SIZE; 709 pThis->fAbort = true; 710 return 0; 711 } 712 713 714 /** 401 715 * Internal worker that performs a HTTP GET. 402 716 * 403 717 * @returns IPRT status code. 404 * @param hHttp The HTTP instance.405 * @param p cszUrlThe URL.718 * @param hHttp The HTTP/HTTPS client instance. 719 * @param pszUrl The URL. 406 720 * @param ppvResponse Where to return the pointer to the allocated 407 721 * response data (RTMemFree). There will always be … … 409 723 * is not part of the size returned via @a pcb. 410 724 * @param pcb The size of the response data. 411 */ 412 RTR3DECL(int) rtHttpGet(RTHTTP hHttp, const char *pcszUrl, uint8_t **ppvResponse, size_t *pcb) 413 { 414 PRTHTTPINTERNAL pHttpInt = hHttp; 415 RTHTTP_VALID_RETURN(pHttpInt); 416 417 pHttpInt->fAbort = false; 418 419 int rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_URL, pcszUrl); 420 if (CURL_FAILED(rcCurl)) 421 return VERR_INVALID_PARAMETER; 422 423 #if 0 424 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_VERBOSE, 1); 425 if (CURL_FAILED(rcCurl)) 426 return VERR_INVALID_PARAMETER; 427 #endif 428 429 const char *pcszCAFile = "/etc/ssl/certs/ca-certificates.crt"; 430 if (pHttpInt->pcszCAFile) 431 pcszCAFile = pHttpInt->pcszCAFile; 432 if (RTFileExists(pcszCAFile)) 433 { 434 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_CAINFO, pcszCAFile); 435 if (CURL_FAILED(rcCurl)) 436 return VERR_INTERNAL_ERROR; 437 } 438 439 RTHTTPMEMCHUNK Chunk = { NULL, 0 }; 440 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_WRITEFUNCTION, &rtHttpWriteData); 441 if (CURL_FAILED(rcCurl)) 442 return VERR_INTERNAL_ERROR; 443 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_WRITEDATA, (void *)&Chunk); 444 if (CURL_FAILED(rcCurl)) 445 return VERR_INTERNAL_ERROR; 446 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROGRESSFUNCTION, &rtHttpProgress); 447 if (CURL_FAILED(rcCurl)) 448 return VERR_INTERNAL_ERROR; 449 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROGRESSDATA, (void *)pHttpInt); 450 if (CURL_FAILED(rcCurl)) 451 return VERR_INTERNAL_ERROR; 452 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_NOPROGRESS, (long)0); 453 if (CURL_FAILED(rcCurl)) 454 return VERR_INTERNAL_ERROR; 455 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_SSLVERSION, (long)CURL_SSLVERSION_TLSv1); 456 if (CURL_FAILED(rcCurl)) 457 return VERR_INVALID_PARAMETER; 458 459 rcCurl = curl_easy_perform(pHttpInt->pCurl); 460 461 int rc = rtHttpGetCalcStatus(pHttpInt, rcCurl); 725 * 726 * @remarks We ASSUME the API user doesn't do concurrent GETs in different 727 * threads, because that will probably blow up! 728 */ 729 static int rtHttpGetToMem(RTHTTP hHttp, const char *pszUrl, uint8_t **ppvResponse, size_t *pcb) 730 { 731 PRTHTTPINTERNAL pThis = hHttp; 732 RTHTTP_VALID_RETURN(pThis); 733 734 /* 735 * Reset the return values in case of more "GUI programming" on the client 736 * side (i.e. a programming style not bothering checking return codes). 737 */ 738 *ppvResponse = NULL; 739 *pcb = 0; 740 741 /* 742 * Set the busy flag (paranoia). 743 */ 744 bool fBusy = ASMAtomicXchgBool(&pThis->fBusy, true); 745 AssertReturn(fBusy, VERR_WRONG_ORDER); 746 747 /* 748 * Reset the state and apply settings. 749 */ 750 pThis->fAbort = false; 751 pThis->rcOutput = VINF_SUCCESS; 752 pThis->cbDownloadHint = 0; 753 754 int rc = rtHttpApplySettings(hHttp, pszUrl); 462 755 if (RT_SUCCESS(rc)) 463 756 { 464 *ppvResponse = Chunk.pu8Mem; 465 *pcb = Chunk.cb; 466 } 467 else 468 { 469 if (Chunk.pu8Mem) 470 RTMemFree(Chunk.pu8Mem); 471 *ppvResponse = NULL; 472 *pcb = 0; 473 } 474 757 RT_ZERO(pThis->Output.Mem); 758 int rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_WRITEFUNCTION, &rtHttpWriteData); 759 if (!CURL_FAILURE(rcCurl)) 760 rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_WRITEDATA, (void *)pThis); 761 if (!CURL_FAILURE(rcCurl)) 762 { 763 /* 764 * Perform the HTTP operation. 765 */ 766 rcCurl = curl_easy_perform(pThis->pCurl); 767 rc = rtHttpGetCalcStatus(pThis, rcCurl); 768 if (RT_SUCCESS(rc)) 769 rc = pThis->rcOutput; 770 if (RT_SUCCESS(rc)) 771 { 772 *ppvResponse = pThis->Output.Mem.pb; 773 *pcb = pThis->Output.Mem.cb; 774 } 775 else if (pThis->Output.Mem.pb) 776 RTMemFree(pThis->Output.Mem.pb); 777 RT_ZERO(pThis->Output.Mem); 778 } 779 else 780 rc = VERR_INTERNAL_ERROR_3; 781 } 782 783 ASMAtomicWriteBool(&pThis->fBusy, false); 475 784 return rc; 476 785 } 477 786 478 787 479 RTR3DECL(int) RTHttpGetText(RTHTTP hHttp, const char *p cszUrl, char **ppszNotUtf8)788 RTR3DECL(int) RTHttpGetText(RTHTTP hHttp, const char *pszUrl, char **ppszNotUtf8) 480 789 { 481 790 uint8_t *pv; 482 791 size_t cb; 483 int rc = rtHttpGet (hHttp, pcszUrl, &pv, &cb);792 int rc = rtHttpGetToMem(hHttp, pszUrl, &pv, &cb); 484 793 if (RT_SUCCESS(rc)) 485 794 { … … 501 810 502 811 503 RTR3DECL(int) RTHttpGetBinary(RTHTTP hHttp, const char *p cszUrl, void **ppvResponse, size_t *pcb)504 { 505 return rtHttpGet (hHttp, pcszUrl, (uint8_t **)ppvResponse, pcb);812 RTR3DECL(int) RTHttpGetBinary(RTHTTP hHttp, const char *pszUrl, void **ppvResponse, size_t *pcb) 813 { 814 return rtHttpGetToMem(hHttp, pszUrl, (uint8_t **)ppvResponse, pcb); 506 815 } 507 816 … … 513 822 514 823 515 static size_t rtHttpWriteDataToFile(void *pvBuf, size_t cb, size_t n, void *pvUser) 516 { 517 size_t cbAll = cb * n; 518 RTFILE hFile = (RTFILE)(intptr_t)pvUser; 519 824 /** 825 * cURL callback for writing data to a file. 826 */ 827 static size_t rtHttpWriteDataToFile(void *pvBuf, size_t cbUnit, size_t cUnits, void *pvUser) 828 { 829 PRTHTTPINTERNAL pThis = (PRTHTTPINTERNAL)pvUser; 520 830 size_t cbWritten = 0; 521 int rc = RTFileWrite( hFile, pvBuf, cbAll, &cbWritten);831 int rc = RTFileWrite(pThis->Output.hFile, pvBuf, cbUnit * cUnits, &cbWritten); 522 832 if (RT_SUCCESS(rc)) 523 833 return cbWritten; 834 pThis->rcOutput = rc; 524 835 return 0; 525 836 } … … 528 839 RTR3DECL(int) RTHttpGetFile(RTHTTP hHttp, const char *pszUrl, const char *pszDstFile) 529 840 { 530 PRTHTTPINTERNAL pHttpInt = hHttp; 531 RTHTTP_VALID_RETURN(pHttpInt); 532 533 /* 534 * Set up the request. 535 */ 536 pHttpInt->fAbort = false; 537 538 int rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_URL, pszUrl); 539 if (CURL_FAILED(rcCurl)) 540 return VERR_INVALID_PARAMETER; 541 542 #if 0 543 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_VERBOSE, 1); 544 if (CURL_FAILED(rcCurl)) 545 return VERR_INVALID_PARAMETER; 546 #endif 547 548 const char *pcszCAFile = "/etc/ssl/certs/ca-certificates.crt"; 549 if (pHttpInt->pcszCAFile) 550 pcszCAFile = pHttpInt->pcszCAFile; 551 if (RTFileExists(pcszCAFile)) 552 { 553 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_CAINFO, pcszCAFile); 554 if (CURL_FAILED(rcCurl)) 555 return VERR_INTERNAL_ERROR; 556 } 557 558 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_WRITEFUNCTION, &rtHttpWriteDataToFile); 559 if (CURL_FAILED(rcCurl)) 560 return VERR_INTERNAL_ERROR; 561 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROGRESSFUNCTION, &rtHttpProgress); 562 if (CURL_FAILED(rcCurl)) 563 return VERR_INTERNAL_ERROR; 564 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROGRESSDATA, (void *)pHttpInt); 565 if (CURL_FAILED(rcCurl)) 566 return VERR_INTERNAL_ERROR; 567 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_NOPROGRESS, (long)0); 568 if (CURL_FAILED(rcCurl)) 569 return VERR_INTERNAL_ERROR; 570 571 /* 572 * Open the output file. 573 */ 574 RTFILE hFile; 575 int rc = RTFileOpen(&hFile, pszDstFile, RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_READWRITE); 841 PRTHTTPINTERNAL pThis = hHttp; 842 RTHTTP_VALID_RETURN(pThis); 843 844 /* 845 * Set the busy flag (paranoia). 846 */ 847 bool fBusy = ASMAtomicXchgBool(&pThis->fBusy, true); 848 AssertReturn(fBusy, VERR_WRONG_ORDER); 849 850 /* 851 * Reset the state and apply settings. 852 */ 853 pThis->fAbort = false; 854 pThis->rcOutput = VINF_SUCCESS; 855 pThis->cbDownloadHint = 0; 856 857 int rc = rtHttpApplySettings(hHttp, pszUrl); 576 858 if (RT_SUCCESS(rc)) 577 859 { 578 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_WRITEDATA, (void *)(uintptr_t)hFile); 579 if (!CURL_FAILED(rcCurl)) 860 pThis->Output.hFile = NIL_RTFILE; 861 int rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_WRITEFUNCTION, &rtHttpWriteDataToFile); 862 if (!CURL_FAILURE(rcCurl)) 863 rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_WRITEDATA, (void *)pThis); 864 if (!CURL_FAILURE(rcCurl)) 580 865 { 581 866 /* 582 * Perform the request.867 * Open the output file. 583 868 */ 584 rcCurl = curl_easy_perform(pHttpInt->pCurl); 585 rc = rtHttpGetCalcStatus(pHttpInt, rcCurl); 869 rc = RTFileOpen(&pThis->Output.hFile, pszDstFile, RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_READWRITE); 870 if (RT_SUCCESS(rc)) 871 { 872 /* 873 * Perform the HTTP operation. 874 */ 875 rcCurl = curl_easy_perform(pThis->pCurl); 876 rc = rtHttpGetCalcStatus(pThis, rcCurl); 877 if (RT_SUCCESS(rc)) 878 rc = pThis->rcOutput; 879 880 int rc2 = RTFileClose(pThis->Output.hFile); 881 if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) 882 rc = rc2; 883 } 884 pThis->Output.hFile = NIL_RTFILE; 586 885 } 587 886 else 588 rc = VERR_INTERNAL_ERROR; 589 590 int rc2 = RTFileClose(hFile); 591 if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) 592 rc = rc2; 593 } 594 887 rc = VERR_INTERNAL_ERROR_3; 888 } 889 890 ASMAtomicWriteBool(&pThis->fBusy, false); 595 891 return rc; 596 892 } -
trunk/src/VBox/Runtime/common/path/RTPathEnsureTrailingSeparator.cpp
r57572 r57613 44 44 if (RTPATH_IS_SLASH(ch) || RTPATH_IS_VOLSEP(ch)) 45 45 return off; 46 if (off + 2 <= cbPath) 47 { 48 pszPath[off++] = RTPATH_SLASH; 49 pszPath[off] = '\0'; 50 return off; 51 } 46 52 } 47 48 if (off + 2 < cbPath) 53 else if (off + 3 <= cbPath) 49 54 { 50 55 pszPath[off++] = '.'; -
trunk/src/VBox/Runtime/generic/RTCrStoreCreateSnapshotById-generic.cpp
r57572 r57613 146 146 } 147 147 else 148 RTErrInfo Set(pErrInfo, rc, "RTCrStoreCreateInMem failed");148 RTErrInfoAdd(pErrInfo, rc, " RTCrStoreCreateInMem failed"); 149 149 return rc; 150 150 } -
trunk/src/VBox/Runtime/generic/createtemp-generic.cpp
r57358 r57613 235 235 } 236 236 RT_EXPORT_SYMBOL(RTFileCreateTempSecure); 237 238 239 RTDECL(int) RTFileOpenTemp(PRTFILE phFile, char *pszFilename, size_t cbFilename, uint64_t fOpen) 240 { 241 AssertReturn((fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_CREATE, VERR_INVALID_FLAGS); 242 AssertReturn(fOpen & RTFILE_O_WRITE, VERR_INVALID_FLAGS); 243 244 /* 245 * Start by obtaining the path to the temporary directory. 246 */ 247 int rc = RTPathTemp(pszFilename, cbFilename); 248 if (RT_SUCCESS(rc)) 249 { 250 /* 251 * Add a filename pattern. 252 */ 253 static char const s_szTemplate[] = "IPRT-XXXXXXXXXXXX.tmp"; 254 rc = RTPathAppend(pszFilename, cbFilename, s_szTemplate); 255 if (RT_SUCCESS(rc)) 256 { 257 char * const pszX = RTStrEnd(pszFilename, cbFilename) - (sizeof(s_szTemplate) - 1) + 5; 258 unsigned cXes = sizeof(s_szTemplate) - 1 - 4 - 5; 259 Assert(pszX[0] == 'X'); Assert(pszX[-1] == '-'); Assert(pszX[cXes] == '.'); 260 261 /* 262 * Try 10000 times with random names. 263 */ 264 unsigned cTriesLeft = 10000; 265 while (cTriesLeft-- > 0) 266 { 267 rtCreateTempFillTemplate(pszX, cXes); 268 rc = RTFileOpen(phFile, pszFilename, fOpen); 269 if (RT_SUCCESS(rc)) 270 return rc; 271 } 272 } 273 } 274 275 if (cbFilename) 276 *pszFilename = '\0'; 277 *phFile = NIL_RTFILE; 278 return rc; 279 } 280 RT_EXPORT_SYMBOL(RTFileOpenTemp); 281 282 -
trunk/src/VBox/Runtime/generic/fs-stubs-generic.cpp
r57358 r57613 68 68 { 69 69 pProperties->cbMaxComponent = 255; 70 #if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) || defined(RT_OS_DARWIN) 71 pProperties->fCaseSensitive = false; 72 #else 70 73 pProperties->fCaseSensitive = true; 74 #endif 71 75 pProperties->fCompressed = false; 72 76 pProperties->fFileCompression = false; … … 78 82 } 79 83 84 85 RTR3DECL(bool) RTFsIsCaseSensitive(const char *pszFsPath) 86 { 87 #if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) || defined(RT_OS_DARWIN) 88 return false; 89 #else 90 return true; 91 #endif 92 } 93 -
trunk/src/VBox/Runtime/r3/nt/fs-nt.cpp
r57358 r57613 226 226 227 227 228 RTR3DECL(bool) RTFsIsCaseSensitive(const char *pszFsPath) 229 { 230 return false; 231 } 232 228 233 229 234 RTR3DECL(int) RTFsQueryType(const char *pszFsPath, PRTFSTYPE penmType) -
trunk/src/VBox/Runtime/r3/posix/fs-posix.cpp
r57358 r57613 153 153 */ 154 154 pProperties->cbMaxComponent = StatVFS.f_namemax; 155 #if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) 156 pProperties->fCaseSensitive = false; 157 #else 155 158 pProperties->fCaseSensitive = true; 159 #endif 156 160 pProperties->fCompressed = false; 157 161 pProperties->fFileCompression = false; … … 168 172 pszFsPath, pszFsPath, pProperties, pProperties->cbMaxComponent, pProperties->fReadOnly, rc)); 169 173 return rc; 174 } 175 176 177 RTR3DECL(bool) RTFsIsCaseSensitive(const char *pszFsPath) 178 { 179 #if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) 180 return false; 181 #else 182 return true; 183 #endif 170 184 } 171 185 -
trunk/src/VBox/Runtime/r3/win/fs-win.cpp
r57358 r57613 335 335 RTUtf16Free(pwszFsRoot); 336 336 return rc; 337 } 338 339 340 RTR3DECL(bool) RTFsIsCaseSensitive(const char *pszFsPath) 341 { 342 return false; 337 343 } 338 344 -
trunk/src/VBox/Runtime/testcase/Makefile.kmk
r57604 r57613 96 96 tstOnce \ 97 97 tstRTPath \ 98 tstRTPathGlob \ 98 99 tstRTPipe \ 99 100 tstRTPoll \ … … 493 494 tstRTPath_SOURCES = tstRTPath.cpp 494 495 496 tstRTPathGlob_TEMPLATE = VBOXR3TSTEXE 497 tstRTPathGlob_SOURCES = tstRTPathGlob.cpp 498 495 499 tstRTPipe_TEMPLATE = VBOXR3TSTEXE 496 500 tstRTPipe_SOURCES = tstRTPipe.cpp
Note:
See TracChangeset
for help on using the changeset viewer.

