static Unicode
UnicodeTrimInternal(ConstUnicode str,      // IN
                    UnicodeTrimSide side)  // IN
{
   Unicode trimmed;
   utf16_t *utf16;
   utf16_t *utf16Start;
   utf16_t *utf16End;

   ASSERT(str);

   utf16 = Unicode_GetAllocBytes(str, STRING_ENCODING_UTF16);
   utf16Start = utf16;
   utf16End = utf16 + Unicode_UTF16Strlen(utf16);

   if (side & UNICODE_TRIMLEFT) {
      while (utf16Start != utf16End && UnicodeSimpleIsWhiteSpace(*utf16Start)) {
         utf16Start++;
      }
   }

   if (side & UNICODE_TRIMRIGHT) {
      while (utf16End != utf16Start && UnicodeSimpleIsWhiteSpace(*(utf16End - 1))) {
         utf16End--;
      }
   }

   *utf16End = 0;

   trimmed = Unicode_AllocWithUTF16(utf16Start);
   free(utf16);

   return trimmed;
}
Unicode
Unicode_FoldCase(ConstUnicode str) // IN
{
   Unicode folded;
   utf16_t *utf16;
   utf16_t *utf16Current;

   ASSERT(str);

   utf16 = Unicode_GetAllocBytes(str, STRING_ENCODING_UTF16);

   utf16Current = utf16;
   while (*utf16Current) {
      *utf16Current = UnicodeSimpleCaseFold(*utf16Current);
      utf16Current++;
   }

   folded = Unicode_AllocWithUTF16(utf16);
   free(utf16);

   return folded;
}
Exemplo n.º 3
0
Unicode
File_StripSlashes(ConstUnicode path)  // IN:
{
   Unicode result, volume, dir, base;

   /*
    * SplitName handles all drive letter/UNC/whatever cases, all we
    * have to do is make sure the dir part is stripped of slashes if
    * there isn't a base part.
    */

   File_SplitName(path, &volume, &dir, &base);

   if (!Unicode_IsEmpty(dir) && Unicode_IsEmpty(base)) {
      char *dir2 = Unicode_GetAllocBytes(dir, STRING_ENCODING_UTF8);
      size_t i = strlen(dir2);

      /*
       * Don't strip first slash on Windows, since we want at least
       * one slash to trail a drive letter/colon or UNC specifier.
       */

#if defined(_WIN32)
      while ((i > 1) && (('/' == dir2[i - 1]) ||
                         ('\\' == dir2[i - 1]))) {
#else
      while ((i > 0) && ('/' == dir2[i - 1])) {
#endif
         i--;
      }

      Unicode_Free(dir);
      dir = Unicode_AllocWithLength(dir2, i, STRING_ENCODING_UTF8);
      free(dir2);
   }

   result = Unicode_Join(volume, dir, base, NULL);

   Unicode_Free(volume);
   Unicode_Free(dir);
   Unicode_Free(base);

   return result;
}


/*
 *-----------------------------------------------------------------------------
 *
 * File_MapPathPrefix --
 *
 *      Given a path and a newPrefix -> oldPrefix mapping, transform
 *      oldPath according to the mapping.
 *
 * Results:
 *      The new path, or NULL if there is no mapping.
 *
 * Side effects:
 *      The returned string is allocated, free it.
 *
 *-----------------------------------------------------------------------------
 */

char *
File_MapPathPrefix(const char *oldPath,       // IN:
                   const char **oldPrefixes,  // IN:
                   const char **newPrefixes,  // IN:
                   size_t numPrefixes)        // IN:
{
   int i;
   size_t oldPathLen = strlen(oldPath);

   for (i = 0; i < numPrefixes; i++) {
      char *newPath;
      char *oldPrefix;
      char *newPrefix;
      size_t oldPrefixLen;

      oldPrefix = File_StripSlashes(oldPrefixes[i]);
      newPrefix = File_StripSlashes(newPrefixes[i]);
      oldPrefixLen = strlen(oldPrefix);

      /*
       * If the prefix matches on a DIRSEPS boundary, or the prefix is the
       * whole string, replace it.
       *
       * If we don't insist on matching a whole directory name, we could
       * mess things of if one directory is a substring of another.
       *
       * Perform a case-insensitive compare on Windows. (There are
       * case-insensitive filesystems on MacOS also, but the problem
       * is more acute with Windows because of frequent drive-letter
       * case mismatches. So in lieu of actually asking the
       * filesystem, let's just go with a simple ifdef for now.)
       */

      if ((oldPathLen >= oldPrefixLen) &&
#ifdef _WIN32
          (Str_Strncasecmp(oldPath, oldPrefix, oldPrefixLen) == 0) &&
#else
          (Str_Strncmp(oldPath, oldPrefix, oldPrefixLen) == 0) &&
#endif
          (strchr(VALID_DIRSEPS, oldPath[oldPrefixLen]) ||
              (oldPath[oldPrefixLen] == '\0'))) {
         size_t newPrefixLen = strlen(newPrefix);
         size_t newPathLen = (oldPathLen - oldPrefixLen) + newPrefixLen;

         ASSERT(newPathLen > 0);
         ASSERT(oldPathLen >= oldPrefixLen);

         newPath = Util_SafeMalloc((newPathLen + 1) * sizeof(char));
         memcpy(newPath, newPrefix, newPrefixLen);
         memcpy(newPath + newPrefixLen, oldPath + oldPrefixLen,
                oldPathLen - oldPrefixLen + 1);
         /*
          * It should only match once.  Weird self-referencing mappings
          * aren't allowed.
          */

         free(oldPrefix);
         free(newPrefix);

         return newPath;
      }
      free(oldPrefix);
      free(newPrefix);
   }

   return NULL;
}
Exemplo n.º 4
0
Bool
ProcMgr_ImpersonateUserStart(const char *user,  // IN: UTF-8 encoded user name
                             AuthToken token)   // IN
{
   char buffer[BUFSIZ];
   struct passwd pw;
   struct passwd *ppw;
   gid_t root_gid;
   int ret;
   char *userLocal;

   ppw = &pw;
   if ((ppw = getpwuid_r(0, &pw, buffer, sizeof buffer)) == NULL) {
      return FALSE;
   }

   root_gid = ppw->pw_gid;

   /* convert user name to local character set */
   userLocal = (char *)Unicode_GetAllocBytes(user, Unicode_GetCurrentEncoding());
   if (!userLocal) {
       Warning("Failed to convert user name %s to local character set.\n", user);
       return FALSE;
   }

   ppw = getpwnam_r(userLocal, &pw, buffer, sizeof buffer);

   free(userLocal);

   if (ppw == NULL) {
      return FALSE;
   }

   /* first change group. */
   ret = Id_SetGid(root_gid);
   if (ret < 0) {
      Warning("Failed to setregid() for root\n");
      return FALSE;
   }

   /*  Snippet from Solaris setregid man page --
    *
    *  A -1 argument does not change the corresponding gid. If the real user ID
    *  is being changed, or the effective user ID is being changed to a value
    *  not equal to the real user ID, the saved set-user ID is set equal to
    *  the new effective user ID.
    */
   ret = Id_SetREGid(ppw->pw_gid, -1);
   if (ret < 0) {
      Warning("Failed to setregid() for user %s\n", user);
      return FALSE;
   }
   ret = Id_SetREGid(-1, ppw->pw_gid);
   if (ret < 0) {
      Warning("Failed to setregid() for user %s\n", user);
      return FALSE;
   }
   ret = initgroups(ppw->pw_name, ppw->pw_gid);
   if (ret < 0) {
      Warning("Failed to initgroups() for user %s\n", user);
      goto failure;
   }

   /* now user. */
   ret = Id_SetUid(0);
   if (ret < 0) {
      Warning("Failed to setregid() for root\n");
      return FALSE;
   }

   /* Same as above. */
   ret = Id_SetREUid(ppw->pw_uid, -1);
   if (ret < 0) {
      Warning("Failed to setreuid() for user %s\n", user);
      goto failure;
   }
   ret = Id_SetREUid(-1, ppw->pw_uid);
   if (ret < 0) {
      Warning("Failed to setreuid() for user %s\n", user);
      goto failure;
   }

   /* set env. */
   setenv("USER", ppw->pw_name, 1);
   setenv("HOME", ppw->pw_dir, 1);
   setenv("SHELL", ppw->pw_shell, 1);

   return TRUE;

failure:
   /* try to restore on error. */
   ProcMgr_ImpersonateUserStop();
   return FALSE;
}