Home | History | Annotate | Download | only in Common
      1 // PropIDUtils.cpp
      2 
      3 #include "StdAfx.h"
      4 
      5 #include "../../../../C/CpuArch.h"
      6 
      7 #include "../../../Common/IntToString.h"
      8 #include "../../../Common/StringConvert.h"
      9 
     10 #include "../../../Windows/FileFind.h"
     11 #include "../../../Windows/FileIO.h"
     12 #include "../../../Windows/PropVariantConv.h"
     13 
     14 #include "../../PropID.h"
     15 
     16 #include "PropIDUtils.h"
     17 
     18 #define Get16(x) GetUi16(x)
     19 #define Get32(x) GetUi32(x)
     20 
     21 using namespace NWindows;
     22 
     23 static const char g_WinAttribChars[16 + 1] = "RHS8DAdNTsLCOnE_";
     24 /*
     25 0 READONLY
     26 1 HIDDEN
     27 2 SYSTEM
     28 
     29 4 DIRECTORY
     30 5 ARCHIVE
     31 6 DEVICE
     32 7 NORMAL
     33 8 TEMPORARY
     34 9 SPARSE_FILE
     35 10 REPARSE_POINT
     36 11 COMPRESSED
     37 12 OFFLINE
     38 13 NOT_CONTENT_INDEXED
     39 14 ENCRYPTED
     40 
     41 16 VIRTUAL
     42 */
     43 
     44 void ConvertWinAttribToString(char *s, UInt32 wa)
     45 {
     46   for (int i = 0; i < 16; i++)
     47     if ((wa & (1 << i)) && i != 7)
     48       *s++ = g_WinAttribChars[i];
     49   *s = 0;
     50 }
     51 
     52 static const char kPosixTypes[16] = { '0', 'p', 'c', '3', 'd', '5', 'b', '7', '-', '9', 'l', 'B', 's', 'D', 'E', 'F' };
     53 #define MY_ATTR_CHAR(a, n, c) ((a) & (1 << (n))) ? c : '-';
     54 
     55 void ConvertPropertyToShortString(char *dest, const PROPVARIANT &prop, PROPID propID, bool full) throw()
     56 {
     57   *dest = 0;
     58   if (prop.vt == VT_FILETIME)
     59   {
     60     FILETIME localFileTime;
     61     if ((prop.filetime.dwHighDateTime == 0 &&
     62         prop.filetime.dwLowDateTime == 0) ||
     63         !::FileTimeToLocalFileTime(&prop.filetime, &localFileTime))
     64       return;
     65     ConvertFileTimeToString(localFileTime, dest, true, full);
     66     return;
     67   }
     68   switch (propID)
     69   {
     70     case kpidCRC:
     71     {
     72       if (prop.vt != VT_UI4)
     73         break;
     74       ConvertUInt32ToHex8Digits(prop.ulVal, dest);
     75       return;
     76     }
     77     case kpidAttrib:
     78     {
     79       if (prop.vt != VT_UI4)
     80         break;
     81       ConvertWinAttribToString(dest, prop.ulVal);
     82       return;
     83     }
     84     case kpidPosixAttrib:
     85     {
     86       if (prop.vt != VT_UI4)
     87         break;
     88       UString res;
     89       UInt32 a = prop.ulVal;
     90 
     91       dest[0] = kPosixTypes[(a >> 12) & 0xF];
     92       for (int i = 6; i >= 0; i -= 3)
     93       {
     94         dest[7 - i] = MY_ATTR_CHAR(a, i + 2, 'r');
     95         dest[8 - i] = MY_ATTR_CHAR(a, i + 1, 'w');
     96         dest[9 - i] = MY_ATTR_CHAR(a, i + 0, 'x');
     97       }
     98       if ((a & 0x800) != 0) dest[3] = ((a & (1 << 6)) ? 's' : 'S');
     99       if ((a & 0x400) != 0) dest[6] = ((a & (1 << 3)) ? 's' : 'S');
    100       if ((a & 0x200) != 0) dest[9] = ((a & (1 << 0)) ? 't' : 'T');
    101       dest[10] = 0;
    102 
    103       a &= ~(UInt32)0xFFFF;
    104       if (a != 0)
    105       {
    106         dest[10] = ' ';
    107         ConvertUInt32ToHex8Digits(a, dest + 11);
    108       }
    109       return;
    110     }
    111     case kpidINode:
    112     {
    113       if (prop.vt != VT_UI8)
    114         break;
    115       ConvertUInt32ToString((UInt32)(prop.uhVal.QuadPart >> 48), dest);
    116       dest += strlen(dest);
    117       *dest++ = '-';
    118       UInt64 low = prop.uhVal.QuadPart & (((UInt64)1 << 48) - 1);
    119       ConvertUInt64ToString(low, dest);
    120       return;
    121     }
    122     case kpidVa:
    123     {
    124       UInt64 v = 0;
    125       if (ConvertPropVariantToUInt64(prop, v))
    126       {
    127         dest[0] = '0';
    128         dest[1] = 'x';
    129         ConvertUInt64ToHex(prop.ulVal, dest + 2);
    130         return;
    131       }
    132       break;
    133     }
    134   }
    135   ConvertPropVariantToShortString(prop, dest);
    136 }
    137 
    138 void ConvertPropertyToString(UString &dest, const PROPVARIANT &prop, PROPID propID, bool full)
    139 {
    140   if (prop.vt == VT_BSTR)
    141   {
    142     dest = prop.bstrVal;
    143     return;
    144   }
    145   char temp[64];
    146   ConvertPropertyToShortString(temp, prop, propID, full);
    147   int len = MyStringLen(temp);
    148   wchar_t *str = dest.GetBuffer(len);
    149   for (int i = 0; i < len; i++)
    150     str[i] = temp[i];
    151   dest.ReleaseBuffer(len);
    152 }
    153 
    154 static inline char GetHex(Byte value)
    155 {
    156   return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
    157 }
    158 
    159 #ifndef _SFX
    160 
    161 static inline void AddHexToString(AString &res, Byte value)
    162 {
    163   res += GetHex((Byte)(value >> 4));
    164   res += GetHex((Byte)(value & 0xF));
    165   res += ' ';
    166 }
    167 
    168 /*
    169 static AString Data_To_Hex(const Byte *data, size_t size)
    170 {
    171   AString s;
    172   for (size_t i = 0; i < size; i++)
    173     AddHexToString(s, data[i]);
    174   return s;
    175 }
    176 */
    177 
    178 static const char *sidNames[] =
    179 {
    180   "0",
    181   "Dialup",
    182   "Network",
    183   "Batch",
    184   "Interactive",
    185   "Logon",  // S-1-5-5-X-Y
    186   "Service",
    187   "Anonymous",
    188   "Proxy",
    189   "EnterpriseDC",
    190   "Self",
    191   "AuthenticatedUsers",
    192   "RestrictedCode",
    193   "TerminalServer",
    194   "RemoteInteractiveLogon",
    195   "ThisOrganization",
    196   "16",
    197   "IUserIIS",
    198   "LocalSystem",
    199   "LocalService",
    200   "NetworkService",
    201   "Domains"
    202 };
    203 
    204 struct CSecID2Name
    205 {
    206   UInt32 n;
    207   const char *sz;
    208 };
    209 
    210 const CSecID2Name sid_32_Names[] =
    211 {
    212   { 544, "Administrators" },
    213   { 545, "Users" },
    214   { 546, "Guests" },
    215   { 547, "PowerUsers" },
    216   { 548, "AccountOperators" },
    217   { 549, "ServerOperators" },
    218   { 550, "PrintOperators" },
    219   { 551, "BackupOperators" },
    220   { 552, "Replicators" },
    221   { 553, "Backup Operators" },
    222   { 554, "PreWindows2000CompatibleAccess" },
    223   { 555, "RemoteDesktopUsers" },
    224   { 556, "NetworkConfigurationOperators" },
    225   { 557, "IncomingForestTrustBuilders" },
    226   { 558, "PerformanceMonitorUsers" },
    227   { 559, "PerformanceLogUsers" },
    228   { 560, "WindowsAuthorizationAccessGroup" },
    229   { 561, "TerminalServerLicenseServers" },
    230   { 562, "DistributedCOMUsers" },
    231   { 569, "CryptographicOperators" },
    232   { 573, "EventLogReaders" },
    233   { 574, "CertificateServiceDCOMAccess" }
    234 };
    235 
    236 static const CSecID2Name sid_21_Names[] =
    237 {
    238   { 500, "Administrator" },
    239   { 501, "Guest" },
    240   { 502, "KRBTGT" },
    241   { 512, "DomainAdmins" },
    242   { 513, "DomainUsers" },
    243   { 515, "DomainComputers" },
    244   { 516, "DomainControllers" },
    245   { 517, "CertPublishers" },
    246   { 518, "SchemaAdmins" },
    247   { 519, "EnterpriseAdmins" },
    248   { 520, "GroupPolicyCreatorOwners" },
    249   { 553, "RASandIASServers" },
    250   { 553, "RASandIASServers" },
    251   { 571, "AllowedRODCPasswordReplicationGroup" },
    252   { 572, "DeniedRODCPasswordReplicationGroup" }
    253 };
    254 
    255 struct CServicesToName
    256 {
    257   UInt32 n[5];
    258   const char *sz;
    259 };
    260 
    261 static const CServicesToName services_to_name[] =
    262 {
    263   { { 0x38FB89B5, 0xCBC28419, 0x6D236C5C, 0x6E770057, 0x876402C0 } , "TrustedInstaller" }
    264 };
    265 
    266 static void ParseSid(AString &s, const Byte *p, UInt32 lim, UInt32 &sidSize)
    267 {
    268   sidSize = 0;
    269   if (lim < 8)
    270   {
    271     s += "ERROR";
    272     return;
    273   }
    274   UInt32 rev = p[0];
    275   if (rev != 1)
    276   {
    277     s += "UNSUPPORTED";
    278     return;
    279   }
    280   UInt32 num = p[1];
    281   if (8 + num * 4 > lim)
    282   {
    283     s += "ERROR";
    284     return;
    285   }
    286   sidSize = 8 + num * 4;
    287   UInt32 authority = GetBe32(p + 4);
    288 
    289   if (p[2] == 0 && p[3] == 0 && authority == 5 && num >= 1)
    290   {
    291     UInt32 v0 = Get32(p + 8);
    292     if (v0 < ARRAY_SIZE(sidNames))
    293     {
    294       s += sidNames[v0];
    295       return;
    296     }
    297     if (v0 == 32 && num == 2)
    298     {
    299       UInt32 v1 = Get32(p + 12);
    300       for (int i = 0; i < ARRAY_SIZE(sid_32_Names); i++)
    301         if (sid_32_Names[i].n == v1)
    302         {
    303           s += sid_32_Names[i].sz;
    304           return;
    305         }
    306     }
    307     if (v0 == 21 && num == 5)
    308     {
    309       UInt32 v4 = Get32(p + 8 + 4 * 4);
    310       for (int i = 0; i < ARRAY_SIZE(sid_21_Names); i++)
    311         if (sid_21_Names[i].n == v4)
    312         {
    313           s += sid_21_Names[i].sz;
    314           return;
    315         }
    316     }
    317     if (v0 == 80 && num == 6)
    318     {
    319       for (int i = 0; i < ARRAY_SIZE(services_to_name); i++)
    320       {
    321         const CServicesToName &sn = services_to_name[i];
    322         int j;
    323         for (j = 0; j < 5 && sn.n[j] == Get32(p + 8 + 4 + j * 4); j++);
    324         if (j == 5)
    325         {
    326           s += sn.sz;
    327           return;
    328         }
    329       }
    330     }
    331   }
    332 
    333   char sz[16];
    334   s += "S-1-";
    335   if (p[2] == 0 && p[3] == 0)
    336   {
    337     ConvertUInt32ToString(authority, sz);
    338     s += sz;
    339   }
    340   else
    341   {
    342     s += "0x";
    343     for (int i = 2; i < 8; i++)
    344       AddHexToString(s, p[i]);
    345   }
    346   for (UInt32 i = 0; i < num; i++)
    347   {
    348     s += '-';
    349     ConvertUInt32ToString(Get32(p + 8 + i * 4), sz);
    350     s += sz;
    351   }
    352 }
    353 
    354 static void ParseOwner(AString &s, const Byte *p, UInt32 size, UInt32 pos)
    355 {
    356   if (pos > size)
    357   {
    358     s += "ERROR";
    359     return;
    360   }
    361   UInt32 sidSize = 0;
    362   ParseSid(s, p + pos, size - pos, sidSize);
    363 }
    364 
    365 static void AddUInt32ToString(AString &s, UInt32 val)
    366 {
    367   char sz[16];
    368   ConvertUInt32ToString(val, sz);
    369   s += sz;
    370 }
    371 
    372 static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName, UInt32 flags, UInt32 offset)
    373 {
    374   UInt32 control = Get16(p + 2);
    375   if ((flags & control) == 0)
    376     return;
    377   UInt32 pos = Get32(p + offset);
    378   s += ' ';
    379   s += strName;
    380   if (pos >= size)
    381     return;
    382   p += pos;
    383   size -= pos;
    384   if (size < 8)
    385     return;
    386   if (Get16(p) != 2) // revision
    387     return;
    388   // UInt32 aclSize = Get16(p + 2);
    389   UInt32 num = Get32(p + 4);
    390   AddUInt32ToString(s, num);
    391   /*
    392   if (num >= (1 << 16))
    393     return;
    394   if (aclSize > size)
    395     return;
    396   size = aclSize;
    397   size -= 8;
    398   p += 8;
    399   for (UInt32 i = 0 ; i < num; i++)
    400   {
    401     if (size <= 8)
    402       return;
    403     // Byte type = p[0];
    404     // Byte flags = p[1];
    405     // UInt32 aceSize = Get16(p + 2);
    406     // UInt32 mask = Get32(p + 4);
    407     p += 8;
    408     size -= 8;
    409 
    410     UInt32 sidSize = 0;
    411     s += ' ';
    412     s += ParseSid(p, size, sidSize);
    413     if (sidSize == 0)
    414       return;
    415     p += sidSize;
    416     size -= sidSize;
    417   }
    418   if (size != 0)
    419     s += " ERROR";
    420   */
    421 }
    422 
    423 #define MY_SE_OWNER_DEFAULTED       (0x0001)
    424 #define MY_SE_GROUP_DEFAULTED       (0x0002)
    425 #define MY_SE_DACL_PRESENT          (0x0004)
    426 #define MY_SE_DACL_DEFAULTED        (0x0008)
    427 #define MY_SE_SACL_PRESENT          (0x0010)
    428 #define MY_SE_SACL_DEFAULTED        (0x0020)
    429 #define MY_SE_DACL_AUTO_INHERIT_REQ (0x0100)
    430 #define MY_SE_SACL_AUTO_INHERIT_REQ (0x0200)
    431 #define MY_SE_DACL_AUTO_INHERITED   (0x0400)
    432 #define MY_SE_SACL_AUTO_INHERITED   (0x0800)
    433 #define MY_SE_DACL_PROTECTED        (0x1000)
    434 #define MY_SE_SACL_PROTECTED        (0x2000)
    435 #define MY_SE_RM_CONTROL_VALID      (0x4000)
    436 #define MY_SE_SELF_RELATIVE         (0x8000)
    437 
    438 void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s)
    439 {
    440   s.Empty();
    441   if (size < 20 || size > (1 << 18))
    442   {
    443     s += "ERROR";
    444     return;
    445   }
    446   if (Get16(data) != 1) // revision
    447   {
    448     s += "UNSUPPORTED";
    449     return;
    450   }
    451   ParseOwner(s, data, size, Get32(data + 4));
    452   s += ' ';
    453   ParseOwner(s, data, size, Get32(data + 8));
    454   ParseAcl(s, data, size, "s:", MY_SE_SACL_PRESENT, 12);
    455   ParseAcl(s, data, size, "d:", MY_SE_DACL_PRESENT, 16);
    456   s += ' ';
    457   AddUInt32ToString(s, size);
    458   // s += '\n';
    459   // s += Data_To_Hex(data, size);
    460 }
    461 
    462 #ifdef _WIN32
    463 
    464 static bool CheckSid(const Byte *data, UInt32 size, UInt32 pos)
    465 {
    466   if (pos >= size)
    467     return false;
    468   size -= pos;
    469   if (size < 8)
    470     return false;
    471   UInt32 rev = data[pos];
    472   if (rev != 1)
    473     return false;
    474   UInt32 num = data[pos + 1];
    475   return (8 + num * 4 <= size);
    476 }
    477 
    478 static bool CheckAcl(const Byte *p, UInt32 size, UInt32 flags, UInt32 offset)
    479 {
    480   UInt32 control = Get16(p + 2);
    481   if ((flags & control) == 0)
    482     return true;
    483   UInt32 pos = Get32(p + offset);
    484   if (pos >= size)
    485     return false;
    486   p += pos;
    487   size -= pos;
    488   if (size < 8)
    489     return false;
    490   UInt32 aclSize = Get16(p + 2);
    491   return (aclSize <= size);
    492 }
    493 
    494 bool CheckNtSecure(const Byte *data, UInt32 size)
    495 {
    496   if (size < 20)
    497     return false;
    498   if (Get16(data) != 1) // revision
    499     return true; // windows function can handle such error, so we allow it
    500   if (size > (1 << 18))
    501     return false;
    502   if (!CheckSid(data, size, Get32(data + 4))) return false;
    503   if (!CheckSid(data, size, Get32(data + 8))) return false;
    504   if (!CheckAcl(data, size, MY_SE_SACL_PRESENT, 12)) return false;
    505   if (!CheckAcl(data, size, MY_SE_DACL_PRESENT, 16)) return false;
    506   return true;
    507 }
    508 
    509 #endif
    510 
    511 bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s)
    512 {
    513   s.Empty();
    514   NFile::CReparseAttr attr;
    515   if (attr.Parse(data, size))
    516   {
    517     if (!attr.IsSymLink())
    518       s += L"Junction: ";
    519     s += attr.GetPath();
    520     if (!attr.IsOkNamePair())
    521     {
    522       s += L" : ";
    523       s += attr.PrintName;
    524     }
    525     return true;
    526   }
    527 
    528   if (size < 8)
    529     return false;
    530   UInt32 tag = Get32(data);
    531   UInt32 len = Get16(data + 4);
    532   if (len + 8 > size)
    533     return false;
    534   if (Get16(data + 6) != 0) // padding
    535     return false;
    536 
    537   char hex[16];
    538   ConvertUInt32ToHex8Digits(tag, hex);
    539   s.AddAsciiStr(hex);
    540   s += L' ';
    541 
    542   data += 8;
    543 
    544   for (UInt32 i = 0; i < len; i++)
    545   {
    546     Byte b = ((const Byte *)data)[i];
    547     s += (wchar_t)GetHex((Byte)((b >> 4) & 0xF));
    548     s += (wchar_t)GetHex((Byte)(b & 0xF));
    549   }
    550   return true;
    551 }
    552 
    553 #endif
    554