Changeset 65993 in vbox for trunk/src/VBox/HostServices/SharedFolders
- Timestamp:
- Mar 8, 2017 12:21:14 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostServices/SharedFolders/vbsfpath.cpp
r62790 r65993 363 363 364 364 365 /**366 * Check the given UTF-8 path for root escapes.367 *368 * Verify that the path is within the root directory of the mapping. Count '..'369 * and other path components and check that we do not go over the root.370 *371 * @returns VBox status code.372 * @retval VINF_SUCCESS373 * @retval VERR_INVALID_NAME374 *375 * @param pszPath The (UTF-8) path to check. Slashes has been convert376 * to host slashes by this time.377 *378 * @remarks This function assumes that the path will be appended to the root379 * directory of the shared folder mapping. Keep that in mind when380 * checking absolute paths!381 */382 static int vbsfPathCheckRootEscape(const char *pszPath)383 {384 /*385 * Walk the path, component by component and check for escapes.386 */387 388 int cComponents = 0; /* How many normal path components. */389 int cParentDirs = 0; /* How many '..' components. */390 391 for (;;)392 {393 char ch;394 395 /* Skip leading path delimiters. */396 do397 ch = *pszPath++;398 while (RTPATH_IS_SLASH(ch));399 if (ch == '\0')400 return VINF_SUCCESS;401 402 /* Check if that is a dot component. */403 int cDots = 0;404 while (ch == '.')405 {406 cDots++;407 ch = *pszPath++;408 }409 410 if ( cDots >= 1411 && (ch == '\0' || RTPATH_IS_SLASH(ch)) )412 {413 if (cDots >= 2) /* Consider all multidots sequences as a 'parent dir'. */414 {415 cParentDirs++;416 417 /* Escaping? */418 if (cParentDirs > cComponents)419 return VERR_INVALID_NAME;420 }421 /* else: Single dot, nothing changes. */422 }423 else424 {425 /* Not a dot component, skip to the end of it. */426 while (ch != '\0' && !RTPATH_IS_SLASH(ch))427 ch = *pszPath++;428 cComponents++;429 }430 Assert(cComponents >= cParentDirs);431 432 /* The end? */433 Assert(ch == '\0' || RTPATH_IS_SLASH(ch));434 if (ch == '\0')435 return VINF_SUCCESS;436 }437 }438 439 365 #if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2) 440 366 /* See MSDN "Naming Files, Paths, and Namespaces". … … 609 535 * Allocate enough memory to build the host full path from the root and the relative path. 610 536 */ 611 uint32_t cbFullPathAlloc = cbRootLen + 1 + cbGuestPath + 1; /* root + possible_slash + relative + 0 */537 const uint32_t cbFullPathAlloc = cbRootLen + 1 + cbGuestPath + 1; /* root + possible_slash + relative + 0 */ 612 538 pszFullPath = (char *)RTMemAlloc(cbFullPathAlloc); 613 539 if (RT_LIKELY(pszFullPath != NULL)) 614 540 { 615 /* Copy the root. */ 616 memcpy(pszFullPath, pszRoot, cbRootLen); 617 if (!RTPATH_IS_SLASH(pszFullPath[cbRootLen - 1])) 618 { 619 pszFullPath[cbRootLen++] = RTPATH_SLASH; 620 } 621 622 /* Init the pointer for the relative path. */ 623 char *pchDst = &pszFullPath[cbRootLen]; 624 625 uint32_t cbSrc = cbGuestPath; 626 const char *pchSrc = pchGuestPath; 627 628 /* Strip leading delimiters from the path the guest specified. */ 629 while ( cbSrc > 0 630 && *pchSrc == pClient->PathDelimiter) 631 { 632 ++pchSrc; 633 --cbSrc; 634 } 635 636 /* 637 * Iterate the guest path components, verify each of them 638 * and append to the host full path replacing delimiters with host slash. 639 */ 640 bool fLastComponentHasWildcard = false; 641 for (; cbSrc > 0; --cbSrc, ++pchSrc) 642 { 643 if (RT_LIKELY(*pchSrc != pClient->PathDelimiter)) 644 { 645 if (RT_LIKELY(vbsfPathIsValidNameChar(*pchSrc))) 541 /* Buffer for the verified guest path. */ 542 char *pchVerifiedPath = (char *)RTMemAlloc(cbGuestPath + 1); 543 if (RT_LIKELY(pchVerifiedPath != NULL)) 544 { 545 /* Init the pointer for the guest relative path. */ 546 uint32_t cbSrc = cbGuestPath; 547 const char *pchSrc = pchGuestPath; 548 549 /* Strip leading delimiters from the path the guest specified. */ 550 while ( cbSrc > 0 551 && *pchSrc == pClient->PathDelimiter) 552 { 553 ++pchSrc; 554 --cbSrc; 555 } 556 557 /* 558 * Iterate the guest path components, verify each of them replacing delimiters with the host slash. 559 */ 560 char *pchDst = pchVerifiedPath; 561 bool fLastComponentHasWildcard = false; 562 for (; cbSrc > 0; --cbSrc, ++pchSrc) 563 { 564 if (RT_LIKELY(*pchSrc != pClient->PathDelimiter)) 646 565 { 647 if ( pfu32PathFlags && vbsfPathIsWildcardChar(*pchSrc))566 if (RT_LIKELY(vbsfPathIsValidNameChar(*pchSrc))) 648 567 { 649 fLastComponentHasWildcard = true; 568 if (pfu32PathFlags && vbsfPathIsWildcardChar(*pchSrc)) 569 { 570 fLastComponentHasWildcard = true; 571 } 572 573 *pchDst++ = *pchSrc; 650 574 } 651 652 *pchDst++ = *pchSrc; 575 else 576 { 577 rc = VERR_INVALID_NAME; 578 break; 579 } 653 580 } 654 581 else 655 582 { 656 rc = VERR_INVALID_NAME; 657 break; 583 /* Replace with the host slash. */ 584 *pchDst++ = RTPATH_SLASH; 585 586 if (pfu32PathFlags && fLastComponentHasWildcard && cbSrc > 1) 587 { 588 /* Processed component has a wildcard and there are more characters in the path. */ 589 *pfu32PathFlags |= VBSF_F_PATH_HAS_WILDCARD_IN_PREFIX; 590 } 591 fLastComponentHasWildcard = false; 658 592 } 659 593 } 660 else 661 { 662 /* Replace with the host slash. */ 663 *pchDst++ = RTPATH_SLASH; 664 665 if (pfu32PathFlags && fLastComponentHasWildcard && cbSrc > 1) 666 { 667 /* Processed component has a wildcard and there are more characters in the path. */ 668 *pfu32PathFlags |= VBSF_F_PATH_HAS_WILDCARD_IN_PREFIX; 669 } 670 fLastComponentHasWildcard = false; 671 } 672 } 673 674 if (RT_SUCCESS(rc)) 675 { 676 const size_t cbFullPathLength = pchDst - &pszFullPath[0]; /* As strlen(pszFullPath). */ 677 678 *pchDst++ = 0; 679 680 if (pfu32PathFlags && fLastComponentHasWildcard) 681 { 682 *pfu32PathFlags |= VBSF_F_PATH_HAS_WILDCARD_IN_LAST; 683 } 684 685 /* Check the appended path for root escapes. */ 686 if (fu32Options & VBSF_O_PATH_CHECK_ROOT_ESCAPE) 687 { 688 rc = vbsfPathCheckRootEscape(&pszFullPath[cbRootLen]); 689 } 594 690 595 if (RT_SUCCESS(rc)) 691 596 { 692 /* 693 * When the host file system is case sensitive and the guest expects 694 * a case insensitive fs, then problems can occur. 695 */ 696 if ( vbsfIsHostMappingCaseSensitive(hRoot) 697 && !vbsfIsGuestMappingCaseSensitive(hRoot)) 698 { 699 bool fWildCard = RT_BOOL(fu32Options & VBSF_O_PATH_WILDCARD); 700 bool fPreserveLastComponent = RT_BOOL(fu32Options & VBSF_O_PATH_PRESERVE_LAST_COMPONENT); 701 rc = vbsfCorrectPathCasing(pClient, pszFullPath, cbFullPathLength, fWildCard, fPreserveLastComponent); 702 } 703 597 const size_t cbFullPathLength = pchDst - &pszFullPath[0]; /* As strlen(pszFullPath). */ 598 *pchDst++ = 0; 599 600 /* Construct the full host path removing '.' and '..'. */ 601 rc = RTPathAbsEx(pszRoot, pchVerifiedPath, pszFullPath, cbFullPathAlloc); 704 602 if (RT_SUCCESS(rc)) 705 603 { 706 LogFunc(("%s\n", pszFullPath)); 707 708 /* Return the full host path. */ 709 *ppszHostPath = pszFullPath; 710 711 if (pcbHostPathRoot) 712 { 713 *pcbHostPathRoot = cbRootLen - 1; /* Must index the path delimiter. */ 714 } 604 if (pfu32PathFlags && fLastComponentHasWildcard) 605 { 606 *pfu32PathFlags |= VBSF_F_PATH_HAS_WILDCARD_IN_LAST; 607 } 608 609 /* Check if the full path is still within the shared folder. */ 610 if (fu32Options & VBSF_O_PATH_CHECK_ROOT_ESCAPE) 611 { 612 if (!RTPathStartsWith(pszFullPath, pszRoot)) 613 { 614 rc = VERR_INVALID_NAME; 615 } 616 } 617 618 if (RT_SUCCESS(rc)) 619 { 620 /* 621 * If the host file system is case sensitive and the guest expects 622 * a case insensitive fs, then correct the path components casing. 623 */ 624 if ( vbsfIsHostMappingCaseSensitive(hRoot) 625 && !vbsfIsGuestMappingCaseSensitive(hRoot)) 626 { 627 const bool fWildCard = RT_BOOL(fu32Options & VBSF_O_PATH_WILDCARD); 628 const bool fPreserveLastComponent = RT_BOOL(fu32Options & VBSF_O_PATH_PRESERVE_LAST_COMPONENT); 629 rc = vbsfCorrectPathCasing(pClient, pszFullPath, cbFullPathLength, 630 fWildCard, fPreserveLastComponent); 631 } 632 633 if (RT_SUCCESS(rc)) 634 { 635 LogFlowFunc(("%s\n", pszFullPath)); 636 637 /* Return the full host path. */ 638 *ppszHostPath = pszFullPath; 639 640 if (pcbHostPathRoot) 641 { 642 /* Return the length of the root path without the trailing slash. */ 643 *pcbHostPathRoot = RTPATH_IS_SLASH(pszFullPath[cbRootLen - 1]) ? 644 cbRootLen - 1 : /* pszRoot already had the trailing slash. */ 645 cbRootLen; /* pszRoot did not have the trailing slash. */ 646 } 647 } 648 } 715 649 } 716 } 650 else 651 { 652 LogFunc(("RTPathAbsEx %Rrc\n", rc)); 653 } 654 } 655 656 RTMemFree(pchVerifiedPath); 657 } 658 else 659 { 660 rc = VERR_NO_MEMORY; 717 661 } 718 662 } … … 738 682 RTMemFree(pszFullPath); 739 683 684 LogFunc(("%Rrc\n", rc)); 740 685 return rc; 741 686 }
Note:
See TracChangeset
for help on using the changeset viewer.