FsysSecurity.cpp
上传用户:surprise9
上传日期:2007-01-04
资源大小:426k
文件大小:21k
源码类别:

Ftp客户端

开发平台:

Visual C++

  1. // This is part of the WAR SOFTWARE SERIES initiated by Jarle Aase
  2. // Copyright 1996 by Jarle Aase. All rights reserved.
  3. // See the "War Software Series Licende Agreement" for details concerning 
  4. // use and distribution.
  5. // ---
  6. // This source code, executables and programs containing source code or
  7. // binaries or proprietetary technology from the War Software Series are
  8. // NOT alloed used, viewed or tested by any governmental agencies in
  9. // any countries. This includes the government, departments, police, 
  10. // military etc.
  11. // ---
  12. // This file is intended for use with Tab space = 2
  13. // Created and maintained in MSVC Developer Studio
  14. // ---
  15. // NAME : FsysSecurity.cpp
  16. // PURPOSE : File System security
  17. // PROGRAM : 
  18. // DATE : Oct. 9 1996
  19. // AUTHOR : Jarle Aase
  20. // ---
  21. // REVISION HISTORY
  22. // 
  23. /* 
  24. The design of the security system is a combination of the UNIX security
  25. system and the "classic" DOS/FTP based security. The flexibility makes
  26. the security a little slower than other FTP servers, but it ease the
  27. maintainance of the sites with a uniform way of handeling the file
  28. system.
  29. Basically all files have the UNIX Perms; Read, Write and Execute.
  30. On directories the user must have execute permission to access the
  31. directory entry (if the execute permission miss, the user can not
  32. see the directory, or any of it's subdirs).
  33. Direcotories:
  34. Read - The user can see files in the directory
  35. Write - The user can create files and directories in the directory
  36. Execute - The user can access the directory.
  37. Files:
  38. Read - The user can read the file
  39. Write - The user can overwrite/delete the file
  40. Execute - The user can execute the file (if it is an executable)
  41. When the server search for permissions, it begins from the system root
  42. and walks down the path till the desired item is reached. If the user miss
  43. the execute permission on a directory along the path, the access is denied.
  44. The files have 3 set of permissions.
  45. Owner - The permissions that applies for the owner of the file
  46. Class - The permissions that applies for the member of the owners class
  47. Other - The permissions that applies for all other users.
  48. In order to add a little flexibility on this design, there can be defined
  49. several different permissions for "other". 
  50. The rules are:
  51. If the current user are the owner, the "other" applies for the FTP "default" level
  52. (system wide or virtual server).
  53. If the current user not is the owner, the server checks if the current user has his
  54. own special permissions for this object. If he dont, the same check is performed for
  55. the group he belongs to (the file system itself dont distinguish between users and
  56. groups - they all have unique numbers. An object can therefore belong to a user or
  57. a group without breaking the integrety of the filesystem).
  58. If the current user (or his group) have special permissions, these are used as the
  59. "other" permissions. (If the object is owned by the users group, the user is *not*
  60. considered owner).
  61. Also: The UNIX "owner" and "class" flags are static for an object. The "other" flags
  62. are dynamic and can be set specially for any user or user-group. If both the user and
  63. his group have special rights, the uses group permissions are ignored, and the users
  64. personal rights used.
  65. The only flags that can be set on these three levels are read, write and execute.
  66. Other file permissions like "free file" and "dupe exception" are shared among all
  67. users of the object.
  68. In order to speed things up and avoid wasting permission files everywhere, each directory
  69. has a set of "default" permissions for it's directories and files. If a file or directory
  70. is undefined in the list, these default permissions applies. The default attributes
  71. are inherited by it's children, uless it has it's own attributes defined.
  72. This is non-standard, and allows attributes to be chained down the paths if the paths
  73. dont have their own permissions set. If they have their own permission set, these will
  74. apply and the chaining will stop.
  75. If no descriptos are found anywhere, the user will get "read + execute" permission on
  76. directories, but no permissions on the files. The users will also be able to browse, but
  77. not access any files.
  78. The security system does not check the paths against the users root-path. But the user will
  79. never be able to access any files below his root path, unless they apper as links to the user,
  80. and the link is part of the path given from the user.
  81. When the Find*File() functions looks for files, they first get a handle to the security
  82. descriptors for the Find*File() start-path. If they need to traverse directories, they
  83. can use this handle so that the security system dont have to perform a new scan from root.
  84. When the handle is closed the information is freed, and the next time the user want to
  85. access something, a new scan is performed.
  86. If the virtual file system is used this is fast, as all the information is cached. Without
  87. the virtual file system, the security functions have to read the information from disk.
  88. Each user has a UMASK for files and directories, so that files created by this user
  89. gets the right permissions.
  90. */
  91. #include "stdafx.h"
  92. #include <sys/stat.h>
  93. #include "WarDaemon.h"
  94. #include "FsysSecurity.h"
  95. #include "ctype.h"
  96. #ifdef _DEBUG
  97. #define new DEBUG_NEW
  98. #undef THIS_FILE
  99. static char THIS_FILE[] = __FILE__;
  100. #endif
  101. CLog *CFsysSecurity::m_Log = NULL;
  102. CCriticalSection CFsysSecurity::m_Lock;
  103. // Get a .Index.txt file. If we are in write mode and fail to create
  104. // the file in the Path, we look in .Index.ini for the path. If the
  105. // path dont exist, we try to create a new file in the .Index
  106. // directory, and when done, we add the entry to the .ini file su that
  107. // we can recognize the file later on...
  108. // In read mode we just fail if the file dont exist in the Path
  109. // or in the .ini file.
  110. FILE *CFsysSecurity::OpenSecurityGroupFile(LPCSTR Path, LPCSTR Mode)
  111. {
  112. ASSERT(AfxIsValidString(Path));
  113. ASSERT(AfxIsValidString(Mode));
  114. FILE *fp = NULL;
  115. LPCSTR p;
  116. m_Lock.Lock();
  117. CString cMyPath = Path;
  118. CString cBuf;
  119. CFsys::DosPath(cMyPath.GetBuffer(1));
  120. cMyPath.ReleaseBuffer();
  121. CString cMyKey;
  122. LPCSTR TagName = strrchr(Path, '\');
  123. if (!TagName || !*++TagName)
  124. TagName = ".suspect";
  125. // Check for root path
  126. if (!*Path)
  127. {
  128. TagName = ".Root";
  129. cMyKey = "@root@";
  130. goto ini_fallback;
  131. }
  132. // Check for disk drive X: ...
  133. if (cMyPath.GetLength() <= 3)
  134. {
  135. ASSERT(strlen(cMyPath) <= 3);
  136. ASSERT((toupper(cMyPath[0]) >= 'A') && (toupper(cMyPath[0]) <= 'Z'));
  137. cMyKey.Format("@drive@%c@", cMyPath[0]);
  138. goto ini_fallback;
  139. }
  140. cMyPath += "\.Index.txt";
  141. if ((fp = fopen(cMyPath,Mode)) == NULL)
  142. {
  143. LogMsg(LOGF_DEBUG,"OpenSecurityGroupFile(%s,%s) failed. %s", Path, Mode, GetLastErrorText());
  144. p = Path;
  145. cMyKey.Empty();
  146. while(*p)
  147. {
  148. if (!isalpha(*p) && !isdigit(*p))
  149. {
  150. char buf[8];
  151. sprintf(buf,"@%x@", (unsigned)*p);
  152. cMyKey += buf;
  153. }
  154. else
  155. cMyKey += *p;
  156. ++p;
  157. }
  158. ini_fallback:
  159. GetIniItem(NULL, ".\.Index\.Index.ini", "Maps", cMyKey, cMyPath, "");
  160. if (cMyPath.IsEmpty() && strchr(Mode,'w'))
  161. {
  162. // Make sure that we have the .Index dir available
  163. if (GetFileAttributes(".Index") == 0xFFFFFFFF)
  164. {
  165. CreateDirectory(".Index", NULL);
  166. }
  167. int Retries = 0; 
  168. // Create a unique file name for this group
  169. for(Retries = 0; Retries < 1000; Retries ++)
  170. {
  171. struct _stat st;
  172. cMyPath.Format(".\.Index\%s-%lu.txt", TagName, Retries);
  173. if (!_stat(cMyPath,&st))
  174. continue; // File exist
  175. if ((fp = fopen(cMyPath, Mode)) != NULL)
  176. PutIniItem(NULL, ".\.Index\.Index.ini", "Maps", cMyKey, cMyPath);
  177. break;
  178. }
  179. }
  180. else if (!cMyPath.IsEmpty())
  181. {
  182. // The path was found in the .ini file
  183. fp = fopen(cMyPath, Mode);
  184. }
  185. }
  186. m_Lock.Unlock();
  187. return fp;
  188. }
  189. // Load the security descriptors for a directory
  190. // Path is always the directory where the permission
  191. // group applies
  192. HANDLE CFsysSecurity::LoadSecurityGroup(LPCSTR Path)
  193. {
  194. #define MYBUFSIZ (1024 * 10)
  195. LPSTR LineBuf = NULL;
  196. FILE *fp = OpenSecurityGroupFile(Path, "r");
  197. HANDLE Rval = INVALID_HANDLE_VALUE;
  198. CFsysSecurityGrp *fsg = NULL;
  199. CFsysSecurityNode *fsn = NULL;
  200. char *FileName = NULL;
  201. char *RealPath = NULL;
  202. char *Comment = NULL;
  203. char *UserName = NULL;
  204. char *ClassName = NULL;
  205. int Perms, Flags, DlCnt, DefaultPermDir, DefaultPermFiles;
  206. int FileVersion = 0;
  207. m_Lock.Lock();
  208. if (!fp)
  209. {
  210. LogMsg(LOGF_DEBUG,"LoadSecurityGroup(%s) - No security group file found.", Path);
  211. goto done;
  212. }
  213. LineBuf = new char[MYBUFSIZ];
  214. FileName = new char[MAX_PATH * 2];
  215. RealPath = new char[MAX_PATH * 2];
  216. Comment = new char[1024];
  217. UserName = new char[64];
  218. ClassName = new char[64];
  219. if (!fgets(LineBuf, MYBUFSIZ, fp))
  220. {
  221. LogMsg(LOGF_DEBUG,"LoadSecurityGroup(%s) - Read at 1st line.", Path);
  222. goto done;
  223. }
  224. sscanf(LineBuf,"%s %s %d", FileName,RealPath,&FileVersion);
  225. if ((FileVersion > 4) || (FileVersion < 2))
  226. {
  227. LogMsg(LOGF_WARNINGS,"LoadSecurityGroup(%s): Unknown file format (%d).", Path, FileVersion);
  228. goto done;
  229. }
  230. if (FileVersion == 4) // War version 2.0
  231. {
  232. if (!fgets(LineBuf, MYBUFSIZ, fp))
  233. {
  234. LogMsg(LOGF_WARNINGS,"LoadSecurityGroup(%s) - No second line.", Path);
  235. goto done;
  236. }
  237. MySscanf(LineBuf,"%O %O", &DefaultPermDir, &DefaultPermFiles);
  238. }
  239. else
  240. {
  241. // Fallback to War 1.* versions of the file
  242. DefaultPermDir = 0775; // Owner all, class all, other list + cd
  243. DefaultPermFiles = 0740; // Owner all, class read, other none.
  244. }
  245. // Allocate buffers for the information
  246. fsg = new CFsysSecurityGrp;
  247. fsg->DefaultPermFiles = DefaultPermFiles;
  248. fsg->DefaultPermDirs = DefaultPermDir;
  249. fsg->m_Path = Path;
  250. fsn = NULL;
  251. while(fgets(LineBuf,MYBUFSIZ,fp) != NULL)
  252. {
  253. Perms = 0; Flags = 0; *FileName = 0; *RealPath = 0; *Comment = 0; *UserName = 0; *ClassName = 0; DlCnt = 0;
  254. if (*LineBuf == '*')
  255. {
  256. // Link
  257. if (FileVersion == 2)
  258. MySscanf(LineBuf+1,"1%s1 %O %s %s 1%s1",
  259. FileName, &Perms, UserName, ClassName, RealPath);
  260. else
  261. MySscanf(LineBuf+1,"1%s1 %O 1%s1 1%s1 1%s1",
  262. FileName, &Perms, UserName, ClassName, RealPath);
  263. if (*UserName == '(') *UserName = 0;
  264. if (*ClassName == '(') *ClassName = 0;
  265. if ((Perms == 0) || !*RealPath || (*RealPath == '('))
  266. continue; // Bad data...
  267. }
  268. else
  269. {
  270. // Normal file info
  271. if (FileVersion == 2)
  272. MySscanf(LineBuf,"1%s1 %O %s %s %d %ld 1%s1",
  273. FileName, &Perms, UserName, ClassName, &Flags, &DlCnt, Comment);
  274. else
  275. MySscanf(LineBuf,"1%s1 %O 1%s1 1%s1 %d %ld 1%s1",
  276. FileName, &Perms, UserName, ClassName, &Flags, &DlCnt, Comment);
  277. if (*UserName == '(') *UserName = 0;
  278. if (*ClassName == '(') *ClassName = 0;
  279. if (!stricmp(Comment,"(null)")) *Comment = 0;
  280. if (!*FileName)
  281. continue; // Bad data...
  282. fsn = new CFsysSecurityNode;
  283. int i;
  284. fsn->Perms = Perms;
  285. fsn->DlCnt = DlCnt;
  286. fsn->Owner = *UserName ? (i = atoi(UserName)) ? i : CUsr::FindUser(UT_USER, UserName) : 0;
  287. fsn->Class = *ClassName ? (i = atoi(ClassName)) ? i : CUsr::FindUser(UT_CLASS, ClassName) : 0;
  288. fsn->Comment = Comment;
  289. fsn->FileName = FileName;
  290. fsg->m_Nodes.AddLast((LPVOID)fsn);
  291. }
  292. }
  293. Rval = (HANDLE)fsg;
  294. done:
  295. if (Rval == INVALID_HANDLE_VALUE)
  296. {
  297. if (fsg)
  298. delete fsg;
  299. }
  300. if (LineBuf)
  301. {
  302. delete LineBuf; 
  303. delete FileName;
  304. delete RealPath;
  305. delete Comment;
  306. delete UserName;
  307. delete ClassName;
  308. }
  309. if (fp)
  310. fclose(fp);
  311. m_Lock.Unlock();
  312. return Rval;
  313. #undef MYBUFSIZ
  314. }
  315. HANDLE CFsysSecurity::GetSecurityDescriptor(HANDLE pGrp, LPCSTR FileName)
  316. {
  317. if (pGrp == INVALID_HANDLE_VALUE)
  318. return INVALID_HANDLE_VALUE;
  319. CFsysSecurityGrp *fsg = (CFsysSecurityGrp *)pGrp;
  320. CFsysSecurityNode *fsn;
  321. CLinkedListItem *Item;
  322. for(Item = fsg->m_Nodes.First(); Item; Item = fsg->m_Nodes.Next(Item))
  323. {
  324. fsn = (CFsysSecurityNode *)fsg->m_Nodes.Ptr(Item);
  325. ASSERT(AfxIsValidString(fsn->FileName));
  326. ASSERT(AfxIsValidString(fsn->Comment));
  327. if (!stricmp(fsn->FileName,FileName))
  328. return (HANDLE)fsn;
  329. }
  330. return INVALID_HANDLE_VALUE;
  331. }
  332. void CFsysSecurity::LogMsg(int flag, LPCSTR Format, ...)
  333. {
  334. CString cBuf;
  335. if (!ShouldLog(m_Log, flag))
  336. return;
  337. ASSERT(AfxIsValidString(Format, FALSE));
  338. ASSERT(m_Log != NULL);
  339. ASSERT(AfxIsValidAddress(m_Log,sizeof(CLog)));
  340. cBuf.Format("CFsysSecurity: %s", Format);
  341. va_list argList;
  342. va_start(argList, Format);
  343. m_Log->LogMsgV(flag, cBuf, argList);
  344. va_end(argList);
  345. }
  346. // Entry point when checking security. This function will
  347. // walk trough the path and make sure that inherited
  348. // permissons are taken care of.
  349. // If the user miss x permission to a directory down the road,
  350. // we return "INVALID_HANDLE_VALUE" and set the error state to
  351. // permission denied.
  352. // This function is not resolving .. or links. This must be expanded
  353. // prior to calling us.
  354. // We want the Path in internal format (cwhatever)
  355. HANDLE CFsysSecurity::GetSecurityGroupFromPath(int User, int Class, LPCSTR Path)
  356. {
  357. ASSERT(AfxIsValidString(Path));
  358. SetLastError(NO_ERROR);
  359. int PathLen = 0;
  360. LPCSTR p = Path;
  361. CString cMyPath = "";
  362. HANDLE hCurrentGrp, hPrevGrp = INVALID_HANDLE_VALUE;
  363. CFsysSecurityGrp *pPrevGrp = NULL;
  364. int Indirections;
  365. for(;;)
  366. {
  367. if (!*p || (*p == '\'))
  368. {
  369. if ((hCurrentGrp = LoadSecurityGroup(cMyPath)) == INVALID_HANDLE_VALUE)
  370. {
  371. ++Indirections;
  372. if (hPrevGrp == INVALID_HANDLE_VALUE)
  373. {
  374. // Root. Create a "dummy" group with read + execute perms on directories
  375. pPrevGrp = new CFsysSecurityGrp;
  376. pPrevGrp->DefaultPermFiles = 0;
  377. pPrevGrp->DefaultPermDirs = NODE_OREAD | NODE_GREAD | NODE_AREAD | NODE_OEXEC | NODE_GEXEC | NODE_AEXEC;
  378. hPrevGrp = (HANDLE) pPrevGrp;
  379. Indirections = 0;
  380. }
  381. if (Indirections == 1)
  382. {
  383. // We dont need the nodes anymore. The hPrevGrp is only neened for it's
  384. // default attributes.
  385. // In fact, if we kept the nodes we would risk to inherit file permissions
  386. // for files in another directory.
  387. pPrevGrp = (CFsysSecurityGrp *)hPrevGrp;
  388. pPrevGrp->DeleteAllNodes();
  389. }
  390. hCurrentGrp = hPrevGrp;
  391. }
  392. // Check execute permission
  393. if (!*p && (cMyPath.GetLength() > 3))
  394. {
  395. // Check if the current path is a directory.
  396. char *MyPath = strdup(cMyPath);
  397. struct _stat st;
  398. CFsys::DosPath(MyPath);
  399. if (!::_stat(MyPath,&st))
  400. {
  401. if (st.st_mode & _S_IFDIR)
  402. {
  403. free(MyPath);
  404. goto validiate_dir;
  405. }
  406. }
  407. free(MyPath);
  408. }
  409. else
  410. {
  411. // User must have execute permission
  412. validiate_dir:
  413. LPCSTR CurrentFile = strrchr(cMyPath,'\');
  414. if (CurrentFile)
  415. ++CurrentFile;
  416. if (CurrentFile && *CurrentFile)
  417. {
  418. if (!CheckPermission(User, Class, hPrevGrp, CurrentFile, NODE_EXEC, TRUE))
  419. {
  420. CloseSecurityGroup(hPrevGrp);
  421. SetLastError(ERROR_ACCESS_DENIED);
  422. return INVALID_HANDLE_VALUE;
  423. }
  424. }
  425. }
  426. if (hPrevGrp != hCurrentGrp)
  427. {
  428. // Close the prev group - we have a new valid one.
  429. if (hPrevGrp != INVALID_HANDLE_VALUE)
  430. CloseSecurityGroup(hPrevGrp);
  431. hPrevGrp = hCurrentGrp;
  432. Indirections = 0;
  433. }
  434. }
  435. if (!*p)
  436. break;
  437. cMyPath += *p++;
  438. }
  439. pPrevGrp = (CFsysSecurityGrp *)hCurrentGrp;
  440. pPrevGrp->m_Path = Path; // We've got to remember the correct path!
  441. return hCurrentGrp;
  442. }
  443. BOOL CFsysSecurity::CloseSecurityGroup(HANDLE pGrp)
  444. {
  445. CFsysSecurityGrp *pMyGrp = (CFsysSecurityGrp *)pGrp;
  446. ASSERT(AfxIsValidAddress(pMyGrp, sizeof(CFsysSecurityGrp)));
  447. delete pMyGrp;
  448. return TRUE;
  449. }
  450. HANDLE CFsysSecurity::CreateNode(int User, HANDLE pGrp, BOOL IsDir, LPCSTR FileName)
  451. {
  452. CFsysSecurityGrp *pMyGrp = (CFsysSecurityGrp *)pGrp;
  453. ASSERT(AfxIsValidAddress(pMyGrp, sizeof(CFsysSecurityGrp)));
  454. ASSERT(AfxIsValidString(FileName));
  455. HANDLE h = GetSecurityDescriptor(pGrp, FileName);
  456. if (h != INVALID_HANDLE_VALUE)
  457. return h;
  458. CFsysSecurityNode *fsn = new CFsysSecurityNode;
  459. fsn->Perms = IsDir ? pMyGrp->DefaultPermDirs :  pMyGrp->DefaultPermFiles;
  460. fsn->Owner = 0;
  461. fsn->Class = 0;
  462. fsn->DlCnt = 0;
  463. fsn->Comment.Empty();
  464. fsn->FileName = FileName;
  465. pMyGrp->m_Nodes.AddLast((HANDLE) fsn);
  466. return (HANDLE) fsn;
  467. }
  468. // Update the .index.txt file from the data in memory. At the same time, delete
  469. // obsolete entries.
  470. BOOL CFsysSecurity::FlushGroup(HANDLE pGrp)
  471. {
  472. CFsysSecurityGrp *pMyGrp = (CFsysSecurityGrp *)pGrp;
  473. ASSERT(AfxIsValidAddress(pMyGrp, sizeof(CFsysSecurityGrp)));
  474. m_Lock.Lock();
  475. FILE *fp = OpenSecurityGroupFile(pMyGrp->m_Path, "w");
  476. if (!fp)
  477. {
  478. LogMsg(LOGF_WARNINGS,"FlushGroup(%s) - Failed to update file permissions.",
  479. pMyGrp->m_Path);
  480. m_Lock.Unlock();
  481. return FALSE;
  482. }
  483. fprintf(fp,"WarSoftware Series2 4n0%o 0%on", 
  484. pMyGrp->DefaultPermDirs, pMyGrp->DefaultPermFiles);
  485. CFsysSecurityNode *fsn;
  486. CLinkedListItem *Item;
  487. for(Item = pMyGrp->m_Nodes.First(); Item; Item = pMyGrp->m_Nodes.Next(Item))
  488. {
  489. fsn = (CFsysSecurityNode *)pMyGrp->m_Nodes.Ptr(Item);
  490. ASSERT(AfxIsValidString(fsn->FileName));
  491. ASSERT(AfxIsValidString(fsn->Comment));
  492. WIN32_FIND_DATA Data;
  493. HANDLE h = CFsys::m_pCFsys->FindFirstFile(0, pMyGrp->m_Path, &Data);
  494. if (h == INVALID_HANDLE_VALUE)
  495. {
  496. // Path dont extist. 
  497. continue;
  498. }
  499. CFsys::m_pCFsys->FindClose(h);
  500. // Update
  501. fprintf(fp,"1%s1 0%o 1%d1 1%d1 %d %ld 1%s1n",
  502. fsn->FileName, 
  503. fsn->Perms,
  504. fsn->Owner,
  505. fsn->Class,
  506. 0, // Obsolete War 1.# inode flags...
  507. fsn->DlCnt,
  508. fsn->Comment);
  509. }
  510. fclose(fp);
  511. // Try to hide the file
  512. // If we fail, we can assume that the file is mapped into the ..Index dir and
  513. // then we don't care...
  514. CString cMyPath;
  515. cMyPath.Format("%s\.Index.txt", pMyGrp->m_Path);
  516. CFsys::DosPath(cMyPath.GetBuffer(1));
  517. cMyPath.ReleaseBuffer();
  518. CFileStatus fs;
  519. if (CFile::GetStatus(cMyPath,fs))
  520. {
  521. fs.m_attribute |= 0x02; // Hidden
  522. try
  523. {
  524. CFile::SetStatus(cMyPath, fs); 
  525. }
  526. catch(CFileException *e)
  527. {
  528. LogMsg(LOGF_WARNINGS,"FlushGroup() - Caught FILE ERROR exception (%d) in file '%s' while hiding the file.",
  529. e->m_cause, e->m_strFileName);
  530. e->Delete();
  531. }
  532. }
  533. m_Lock.Unlock();
  534. return TRUE;
  535. }
  536. int CFsysSecurity::GetPermissions(int User, int Class, 
  537. HANDLE pGrp, LPCSTR FileName, BOOL IsDir, int *Mask, 
  538. CFsysSecurityNode **pFsn, BOOL ShowRealPerms)
  539. {
  540. CFsysSecurityGrp *pMyGrp = (CFsysSecurityGrp *)pGrp;
  541. ASSERT(AfxIsValidAddress(pMyGrp, sizeof(CFsysSecurityGrp)));
  542. ASSERT(AfxIsValidString(FileName));
  543. HANDLE h = GetSecurityDescriptor(pGrp, FileName);
  544. int Perms = 0;
  545. if (!ShowRealPerms && (!User || CUsr::IsAdmin(User)))
  546. {
  547. if (Mask)
  548. *Mask = 0777;
  549. return 0777; // Superuser or server call. Override security...
  550. }
  551. if (h == INVALID_HANDLE_VALUE)
  552. {
  553. if (Mask)
  554. *Mask = S_IRWXO;
  555. Perms = IsDir ? pMyGrp->DefaultPermDirs :  pMyGrp->DefaultPermFiles;
  556. }
  557. else
  558. {
  559. CFsysSecurityNode *fsn = (CFsysSecurityNode *)h;
  560. Perms = fsn->Perms;
  561. if (Mask)
  562. {
  563. *Mask = S_IRWXO;
  564. if (fsn->Owner && (User == fsn->Owner))
  565. *Mask |= S_IRWXU;
  566. if (fsn->Class && (Class == fsn->Class))
  567. *Mask |= S_IRWXG;
  568. }
  569. if (pFsn)
  570. *pFsn = fsn;
  571. // TODO: Check for extra permissions for this user/class
  572. }
  573. return Perms;
  574. }
  575. BOOL CFsysSecurity::CheckPermission(int User, int Class, 
  576. HANDLE pGrp, LPCSTR FileName, int PermsWanted, BOOL IsDir)
  577. {
  578. CFsysSecurityGrp *pMyGrp = (CFsysSecurityGrp *)pGrp;
  579. ASSERT(AfxIsValidAddress(pMyGrp, sizeof(CFsysSecurityGrp)));
  580. ASSERT(AfxIsValidString(FileName));
  581. int Mask;
  582. int Perms = GetPermissions(User, Class, pGrp, FileName, IsDir, &Mask, NULL, FALSE);
  583. if (PermsWanted & NODE_EXEC)
  584. {
  585. if (!((Perms & Mask) & (NODE_OEXEC | NODE_GEXEC | NODE_AEXEC)))
  586. return FALSE; // No permissions
  587. }
  588. if (PermsWanted & NODE_READ)
  589. {
  590. if (!((Perms & Mask) & (NODE_OREAD | NODE_GREAD | NODE_AREAD)))
  591. return FALSE; // No permissions
  592. }
  593. if (PermsWanted & NODE_WRITE)
  594. {
  595. if (!((Perms & Mask) & (NODE_0WRITE | NODE_GWRITE | NODE_AWRITE)))
  596. return FALSE; // No permissions
  597. }
  598. return TRUE;
  599. }
  600. // Handle fopen(path,"w") to hidden files
  601. FILE *CFsysSecurity::fopen(LPCSTR DosPath, LPCSTR Mode)
  602. {
  603. DWORD dw = GetFileAttributes(DosPath);
  604. if (strchr(Mode,'w') && (dw != 0xFFFFFFFF) && (dw & FILE_ATTRIBUTE_HIDDEN))
  605. {
  606. FILE *fp;
  607. // Turn off the readonly flag
  608. dw &= ~FILE_ATTRIBUTE_HIDDEN;
  609. SetFileAttributes(DosPath,dw);
  610. // open the file
  611. fp = ::fopen(DosPath,Mode);
  612. // Turn on the readonly flag
  613. dw |= FILE_ATTRIBUTE_HIDDEN;
  614. SetFileAttributes(DosPath,dw);
  615. return fp;
  616. }
  617. return ::fopen(DosPath,Mode);
  618. }
  619. CFsysSecurityGrp::~CFsysSecurityGrp()
  620. {
  621. ASSERT(AfxIsValidAddress(this,sizeof(CFsysSecurityGrp)));
  622. DeleteAllNodes();
  623. }
  624. void CFsysSecurityGrp::DeleteAllNodes()
  625. {
  626. CFsysSecurityNode *fsn;
  627. while(fsn = (CFsysSecurityNode *)m_Nodes.GetAndDeleteFirst())
  628. delete fsn;
  629. }
  630. CFsysSecurityNode::~CFsysSecurityNode()
  631. {
  632. ASSERT(AfxIsValidAddress(this,sizeof(CFsysSecurityNode)));
  633. }