00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <spl/Environment.h>
00024 #include <spl/io/Permissions.h>
00025 #include <spl/text/StringBuffer.h>
00026 #include <spl/io/WinPerm.h>
00027
00028 #ifdef _WINDOWS
00029
00030 #include <Tchar.h>
00031 #include <Lmcons.h>
00032 #include <aclapi.h>
00033 #include <accctrl.h>
00034
00035 #define S_IRUSR 0400
00036 #define S_IWUSR 0200
00037 #define S_IXUSR 0100
00038 #define S_IRGRP 0040
00039 #define S_IWGRP 0020
00040 #define S_IXGRP 0010
00041 #define S_IROTH 0004
00042 #define S_IWOTH 0002
00043 #define S_IXOTH 0001
00044
00045 #ifndef SECURITY_MAX_SID_SIZE
00046 #define SECURITY_MAX_SID_SIZE 68
00047 #endif
00048
00049 #else
00050
00051 #include <sys/stat.h>
00052
00053 #endif
00054
00055 const int Permissions::USER_READ = S_IRUSR,
00056 Permissions::USER_WRITE = S_IWUSR,
00057 Permissions::USER_READ_WRITE = (S_IRUSR | S_IWUSR),
00058 Permissions::USER_EXECUTE = S_IXUSR,
00059 Permissions::USER_ALL = (S_IRUSR | S_IWUSR | S_IXUSR),
00060 Permissions::GROUP_READ = S_IRGRP,
00061 Permissions::GROUP_WRITE = S_IWGRP,
00062 Permissions::GROUP_READ_WRITE = (S_IRGRP | S_IWGRP),
00063 Permissions::GROUP_EXECUTE = S_IXGRP,
00064 Permissions::GROUP_ALL = (S_IRGRP | S_IWGRP | S_IXGRP),
00065 Permissions::OTHERS_READ = S_IROTH,
00066 Permissions::OTHERS_WRITE = S_IWOTH,
00067 Permissions::OTHERS_READ_WRITE = (S_IROTH | S_IWOTH),
00068 Permissions::OTHERS_EXECUTE = S_IXOTH,
00069 Permissions::OTHERS_ALL = (S_IROTH | S_IWOTH | S_IXOTH),
00070 Permissions::ALL_READ_WRITE = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP
00071 | S_IROTH | S_IWOTH),
00072 Permissions::ALLBITS = (USER_ALL | GROUP_ALL | OTHERS_ALL);
00073
00074
00075
00076
00077 const Permissions Permissions::DefaultFilePerms(Permissions::USER_ALL
00078 | Permissions::GROUP_READ);
00079
00080 const Permissions Permissions::DefaultDirPerms(Permissions::USER_ALL
00081 | Permissions::GROUP_READ
00082 | Permissions::GROUP_EXECUTE);
00083
00084
00085
00086
00087 Permissions::Permissions(uint32 mask ) throw()
00088 : _mask(mask & ALLBITS)
00089 {
00090 }
00091
00092
00093
00094
00095 Permissions::Permissions(const Permissions& other) throw()
00096 : _mask(other._mask)
00097 {
00098 }
00099
00100
00101
00102
00103 Permissions::~Permissions() throw()
00104 {
00105 }
00106
00107
00108
00109
00110 Permissions& Permissions::operator=(const Permissions& other) throw()
00111 {
00112 _mask = other._mask;
00113 return(*this);
00114 }
00115
00116
00117
00118
00119 StringPtr Permissions::ToString() const
00120 {
00121 StringBuffer s;
00122 s.Append("---------");
00123
00124 for(int i = 2, x = 0; i >=0; --i)
00125 {
00126 unsigned int b = ((_mask >> (i * 3)) & 0x07);
00127
00128 if(b & 4)
00129 s.SetCharAt(x, 'r');
00130 ++x;
00131
00132 if(b & 2)
00133 s.SetCharAt(x, 'w');
00134 ++x;
00135
00136 if(b & 1)
00137 s.SetCharAt(x, 'x');
00138 ++x;
00139 }
00140
00141 return s.ToString();
00142 }
00143
00144 #ifdef _WINDOWS
00145
00146 #define LUSIZE 1024
00147 #define ACCT_NAME_SIZE LUSIZE
00148 #define ACL_SIZE 1024
00149 #define SID_SIZE LUSIZE
00150 #define DOM_SIZE LUSIZE
00151
00152
00153 bool FindPrimaryGroup(LPTSTR name)
00154 {
00155
00156
00157
00158
00159
00160
00161
00162 TCHAR RefDomain[DOM_SIZE];
00163 DWORD RefDomCnt = DOM_SIZE;
00164 SID_NAME_USE nameuse = SidTypeGroup;
00165 HANDLE tHandle;
00166 TOKEN_GROUPS TokenG[512];
00167 DWORD TISize, AcctSize = UNLEN + 1;
00168
00169 if(! ::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS, &tHandle))
00170 return false;
00171
00172 if(! ::GetTokenInformation(tHandle, TokenGroups, &TokenG, sizeof(TokenG), &TISize))
00173 {
00174 ::CloseHandle(tHandle);
00175 return false;
00176 }
00177
00178 if(! ::LookupAccountSid(NULL, TokenG[0].Groups[2].Sid, name, &AcctSize, RefDomain, &RefDomCnt, &nameuse))
00179 {
00180 ::CloseHandle(tHandle);
00181 return false;
00182 }
00183
00184 ::CloseHandle(tHandle);
00185 return true;
00186 }
00187
00188
00189 bool EncodePermissions(const Permissions& perm, _WinPerms &wperm)
00190 {
00191 if (NULL != wperm.pdesc)
00192 {
00193 ::LocalFree(wperm.pdesc);
00194 wperm.pdesc = NULL;
00195 }
00196
00197 static uint32 masks[9] = { Permissions::USER_READ,
00198 Permissions::USER_WRITE,
00199 Permissions::USER_EXECUTE,
00200 Permissions::GROUP_READ,
00201 Permissions::GROUP_WRITE,
00202 Permissions::GROUP_EXECUTE,
00203 Permissions::OTHERS_READ,
00204 Permissions::OTHERS_WRITE,
00205 Permissions::OTHERS_EXECUTE };
00206
00207 static int types[3] = { (FILE_READ_DATA | READ_CONTROL
00208 | FILE_READ_ATTRIBUTES | FILE_READ_EA),
00209
00210 (FILE_WRITE_DATA | FILE_APPEND_DATA
00211 | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA
00212 | DELETE | FILE_DELETE_CHILD
00213 | WRITE_DAC | WRITE_OWNER),
00214
00215 FILE_EXECUTE };
00216
00218
00219 bool status = false;
00220 int i;
00221
00222 wperm.pdesc = (PSECURITY_DESCRIPTOR)::LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR));
00223
00224 if(! ::InitializeSecurityDescriptor(wperm.pdesc, SECURITY_DESCRIPTOR_REVISION))
00225 return false;
00226
00227 PACL pAcl = NULL;
00228 LPTSTR GrpNms[3] = { "", "", "Everyone" };
00229 PSID sids[3] = { NULL, NULL, NULL };
00230 SID_NAME_USE nameuse [] = { SidTypeUser, SidTypeGroup, SidTypeWellKnownGroup };
00231 TCHAR RefDomain[3][DOM_SIZE];
00232 TCHAR user[UNLEN + 1];
00233 DWORD RefDomSize[3] = { DOM_SIZE, DOM_SIZE, DOM_SIZE };
00234 DWORD sidSize[3] = { SECURITY_MAX_SID_SIZE, SECURITY_MAX_SID_SIZE,
00235 SECURITY_MAX_SID_SIZE };
00236 DWORD sz = UNLEN + 1;
00237
00238 if(! ::GetUserName(user, &sz))
00239 return false;
00240
00241 GrpNms[0] = user;
00242
00243
00244
00245 GrpNms[1] = (LPTSTR)::HeapAlloc(wperm.heap, 0, UNLEN + 1);
00246 if(GrpNms[1] == NULL)
00247 return false;
00248
00249 GrpNms[1][0] = 0;
00250 if (!FindPrimaryGroup(GrpNms[1]))
00251 {
00252 return false;
00253 }
00254
00255 for(i = 0; i < 3; i++)
00256 {
00257 sids[i] = ::HeapAlloc(wperm.heap, 0, SECURITY_MAX_SID_SIZE);
00258 if(sids[i] == NULL)
00259 return false;
00260
00261 if(! ::LookupAccountName(NULL, GrpNms[i], sids[i], &sidSize[i],
00262 RefDomain[i], &RefDomSize[i], &nameuse[i]))
00263 return false;
00264 }
00265
00266 pAcl = (PACL)::HeapAlloc(wperm.heap, 0, ACL_SIZE);
00267 if(pAcl == NULL)
00268 return false;
00269
00270 if(! ::InitializeAcl(pAcl, ACL_SIZE, ACL_REVISION))
00271 return false;
00272
00273
00274
00275 for(i = 0; i < 9; i++)
00276 {
00277 bool f = 0 != (perm & masks[i]);
00278 bool ok;
00279
00280 if(f)
00281 ok = 0 != ::AddAccessAllowedAce(pAcl, ACL_REVISION, types[i % 3], sids[i / 3]);
00282 else
00283 ok = 0 != ::AddAccessDeniedAce(pAcl, ACL_REVISION, types[i % 3], sids[i / 3]);
00284
00285 if(! ok)
00286 return false;
00287 }
00288
00289
00290
00291 if(! ::AddAccessDeniedAce(pAcl, ACL_REVISION,
00292 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
00293 sids[2]))
00294 return false;
00295
00296
00297
00298 if(! ::SetSecurityDescriptorDacl(wperm.pdesc, TRUE, pAcl, FALSE))
00299 return false;
00300
00301 if(! ::IsValidSecurityDescriptor(wperm.pdesc))
00302 return false;
00303
00304 return true;
00305 }
00306
00307
00308 bool DecodePermissions(_WinPerms &wperm, Permissions &perm)
00309 {
00310 PSID _worldSID = NULL;
00311 TRUSTEE ident = { NULL, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID };
00312 ACCESS_MASK mask;
00313
00314
00315
00316 ident.TrusteeType = TRUSTEE_IS_USER;
00317 ident.ptstrName = (LPTSTR)wperm.user;
00318
00319 if(::GetEffectiveRightsFromAcl(wperm.dacl, &ident, &mask) != ERROR_SUCCESS)
00320 {
00321 return false;
00322 }
00323
00324 (mask & FILE_READ_DATA) ? perm.SetUserRead() : perm.ClearUserRead();
00325 (mask & FILE_WRITE_DATA) ? perm.SetUserWrite() : perm.ClearUserWrite();
00326 (mask & FILE_EXECUTE) ? perm.SetUserExecute() : perm.ClearUserExecute();
00327
00328
00329
00330 ident.TrusteeType = TRUSTEE_IS_GROUP;
00331 ident.ptstrName = (LPTSTR)wperm.group;
00332
00333 if(::GetEffectiveRightsFromAcl(wperm.dacl, &ident, &mask) != ERROR_SUCCESS)
00334 {
00335 return false;
00336 }
00337
00338 (mask & FILE_READ_DATA) ? perm.SetGroupRead() : perm.ClearGroupRead();
00339 (mask & FILE_WRITE_DATA) ? perm.SetGroupWrite() : perm.ClearGroupWrite();
00340 (mask & FILE_EXECUTE) ? perm.SetGroupExecute() : perm.ClearGroupExecute();
00341
00342
00343 SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_WORLD_SID_AUTHORITY;
00344 ::AllocateAndInitializeSid(&sidAuth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &_worldSID);
00345
00346 ident.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
00347 ident.ptstrName = (LPTSTR)_worldSID;
00348
00349 if(::GetEffectiveRightsFromAcl(wperm.dacl, &ident, &mask) != ERROR_SUCCESS)
00350 {
00351 ::FreeSid(_worldSID);
00352 return false;
00353 }
00354 ::FreeSid(_worldSID);
00355
00356 (mask & FILE_READ_DATA) ? perm.SetOthersRead() : perm.ClearOthersRead();
00357 (mask & FILE_WRITE_DATA) ? perm.SetOthersWrite() : perm.ClearOthersWrite();
00358 (mask & FILE_EXECUTE) ? perm.SetOthersExecute() : perm.ClearOthersExecute();
00359
00360 return true;
00361 }
00362
00363 #else
00364
00365 void EncodePermissions(const Permissions& perm, mode_t& mode)
00366 {
00367 mode = (mode_t)perm.GetMask();
00368 }
00369
00370
00371 void DecodePermissions(const mode_t mode, Permissions& perm)
00372 {
00373 perm = (uint32)(mode & 0777);
00374 }
00375
00376 #endif
00377
00378