Exemplo n.º 1
0
static char *
FindSuitableExistingDirectory(
   const char *realRoot,       // IN: e.g. $HOME/.cache/vmware/drag_and_drop/
   const char *apparentRoot)   // IN: e.g. /tmp/VMwareDnD/
{
   char *result = NULL;

   char **stagingDirList;
   int numStagingDirs = File_ListDirectory(realRoot, &stagingDirList);
   int i;

   for (i = 0; i < numStagingDirs && result == NULL; i++) {
      char *stagingDir = Unicode_Append(realRoot, stagingDirList[i]);
      char *apparentStagingDir = Unicode_Append(apparentRoot, stagingDirList[i]);
      char *temp = NULL;
      struct stat sb;

      if (   File_IsEmptyDirectory(stagingDir)
          && (   Posix_Symlink(stagingDir, apparentStagingDir) == 0
              || (   Posix_Lstat(apparentStagingDir, &sb) == 0
                  && sb.st_uid == getuid()
                  && (temp = Posix_ReadLink(apparentStagingDir)) != NULL
                  && strcmp(stagingDir, temp) == 0))) {
         result = apparentStagingDir;
         apparentStagingDir = NULL;
      }

      free(stagingDir);
      free(apparentStagingDir);
      free(temp);
   }

   Util_FreeStringList(stagingDirList, numStagingDirs);
   return result;
}
Exemplo n.º 2
0
static Bool
FileAcceptableSafeTmpDir(const char *dirname,  // IN:
                         int userId)           // IN:
{
   Bool result;
   static const mode_t mode = 0700;

   result = (Posix_Mkdir(dirname, mode) == 0);
   if (!result) {
      int error = errno;

      if (EEXIST == error) {
         struct stat st;

         /*
          * The name already exists. Check that it is what we want: a
          * directory owned by the current effective user with permissions
          * 'mode'. It is crucial to use lstat() instead of stat() here,
          * because we do not want the name to be a symlink (created by
          * another user) pointing to a directory owned by the current
          * effective user with permissions 'mode'.
          */

         if (0 == Posix_Lstat(dirname, &st)) {
            /*
             * Our directory inherited S_ISGID if its parent had it. So it
             * is important to ignore that bit, and it is safe to do so
             * because that bit does not affect the owner's permissions.
             */

            if (S_ISDIR(st.st_mode) &&
                (st.st_uid == userId) &&
                ((st.st_mode & 05777) == mode)) {
               result = TRUE;
            }
         }
      }
   }

   return result;
}