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

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. Note: This module is accessed by several threads/processes. Syncronization is
  91. left to the calling module. At implementation time, VfSys will ensure locking
  92. of the affected dir, and then call <device>.dll to get the permissions, which
  93. in turn call this module. Handles will only be called by one thread, and closed
  94. as soon as a ditrectory is scanned.
  95. */
  96. #include "stdafx.h"
  97. #include <sys/stat.h>
  98. #include "WarSoftware.h"
  99. #include "FsysSecurity.h"
  100. #include "ctype.h"
  101. #ifdef _DEBUG
  102. #define new DEBUG_NEW
  103. #undef THIS_FILE
  104. static char THIS_FILE[] = __FILE__;
  105. #endif
  106. // Get a SECFILE file. If we are in write mode and fail to create
  107. // the file in the Path, we look in .Index.ini for the path. If the
  108. // path dont exist, we try to create a new file in the .Index
  109. // directory, and when done, we add the entry to the .ini file su that
  110. // we can recognize the file later on...
  111. // In read mode we just fail if the file dont exist in the Path
  112. // or in the .ini file.
  113. FILE *CFsysSecurity::OpenSecurityGroupFile(LPCSTR Path, LPCSTR Mode)
  114. {
  115. ASSERT(AfxIsValidString(Path));
  116. ASSERT(AfxIsValidString(Mode));
  117. FILE *fp = NULL;
  118. LPCSTR p;
  119. CString cMyPath = Path;
  120. CString cBuf;
  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 += "\"SECFILE;
  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. CString FsysPath = GetStartupPath();
  160. {
  161. LPSTR p = FsysPath.GetBuffer(1);
  162. p = strrchr(p, '\');
  163. if (*p)
  164. *p = 0;
  165. FsysPath.ReleaseBuffer();
  166. FsysPath += "\Fsys";
  167. }
  168. CString IndexDirPath = FsysPath;
  169. IndexDirPath += "\"SECFILE".DIR";
  170. CString IndexIniPath = IndexDirPath;
  171. IndexIniPath += "\"SECFILE".ini";
  172. GetIniItem(NULL, IndexIniPath, "Maps", cMyKey, cMyPath, "");
  173. if (cMyPath.IsEmpty() && strchr(Mode,'w'))
  174. {
  175. // Make sure that we have the .Index dir available
  176. if (GetFileAttributes(IndexDirPath) == 0xFFFFFFFF)
  177. {
  178. CreateDirectory(IndexDirPath, NULL);
  179. }
  180. int Retries = 0; 
  181. // Create a unique file name for this group
  182. for(Retries = 0; Retries < 1000; Retries ++)
  183. {
  184. struct _stat st;
  185. cMyPath.Format("%s\%s-%lu.txt", IndexDirPath, TagName, Retries);
  186. if (!_stat(cMyPath,&st))
  187. continue; // File exist
  188. if ((fp = fopen(cMyPath, Mode)) != NULL)
  189. PutIniItem(NULL, IndexIniPath, "Maps", cMyKey, cMyPath);
  190. break;
  191. }
  192. }
  193. else if (!cMyPath.IsEmpty())
  194. {
  195. // The path was found in the .ini file
  196. fp = fopen(cMyPath, Mode);
  197. }
  198. }
  199. return fp;
  200. }
  201. // Load the security descriptors for a directory
  202. // Path is always the directory where the permission
  203. // group applies
  204. HANDLE CFsysSecurity::LoadSecurityGroup(LPCSTR Path, BOOL DoScanNodes)
  205. {
  206. #define MYBUFSIZ (1024 * 10)
  207. LPSTR LineBuf = NULL;
  208. FILE *fp = OpenSecurityGroupFile(Path, "r");
  209. HANDLE Rval = INVALID_HANDLE_VALUE;
  210. CFsysSecurityGrp *fsg = NULL;
  211. CFsysSecurityNode *fsn = NULL;
  212. #ifdef _DEBUG
  213. LogMsg(LOGF_DEBUG,"LoadSecurityGroup(%s [%s]) - Called.", Path,
  214. DoScanNodes ? "Scan_nodes" : "skip_nodes");
  215. #endif
  216. char *FileName = NULL;
  217. char *RealPath = NULL;
  218. char *Comment = NULL;
  219. char *UserName = NULL;
  220. char *ClassName = NULL;
  221. DWORD Perms, SpecialNewFilePerms, DlCnt, DefaultPermDir, DefaultPermFiles;
  222. int FileVersion = 0;
  223. if (!fp)
  224. {
  225. LogMsg(LOGF_DEBUG,"LoadSecurityGroup(%s) - No security group file found.", Path);
  226. goto done;
  227. }
  228. LineBuf = new char[MYBUFSIZ];
  229. FileName = new char[MAX_PATH * 2];
  230. RealPath = new char[MAX_PATH * 2];
  231. Comment = new char[1024];
  232. UserName = new char[64];
  233. ClassName = new char[64];
  234. if (!fgets(LineBuf, MYBUFSIZ, fp))
  235. {
  236. LogMsg(LOGF_DEBUG,"LoadSecurityGroup(%s) - Read at 1st line.", Path);
  237. goto done;
  238. }
  239. sscanf(LineBuf,"%s %s %d", FileName,RealPath,&FileVersion);
  240. if ((FileVersion > 4) || (FileVersion < 2))
  241. {
  242. LogMsg(LOGF_WARNINGS,"LoadSecurityGroup(%s): Unknown file format (%d).", Path, FileVersion);
  243. goto done;
  244. }
  245. if (FileVersion == 4) // War version 2.0
  246. {
  247. if (!fgets(LineBuf, MYBUFSIZ, fp))
  248. {
  249. LogMsg(LOGF_WARNINGS,"LoadSecurityGroup(%s) - No second line.", Path);
  250. goto done;
  251. }
  252. MySscanf(LineBuf,"%O %O", &DefaultPermDir, &DefaultPermFiles);
  253. }
  254. else
  255. {
  256. // Fallback to War 1.* versions of the file
  257. DefaultPermDir = 0775; // Owner all, class all, other list + cd
  258. DefaultPermFiles = 0740; // Owner all, class read, other none.
  259. }
  260. // Allocate buffers for the information
  261. fsg = new CFsysSecurityGrp;
  262. fsg->DefaultPermFiles = DefaultPermFiles;
  263. fsg->DefaultPermDirs = DefaultPermDir;
  264. fsg->m_Path = Path;
  265. fsn = NULL;
  266. if (!DoScanNodes)
  267. goto skip_scan; // We only needed the default perms this time..
  268. while(fgets(LineBuf,MYBUFSIZ,fp) != NULL)
  269. {
  270. Perms = 0; SpecialNewFilePerms = 0; *FileName = 0; *RealPath = 0; *Comment = 0; *UserName = 0; *ClassName = 0; DlCnt = 0;
  271. if (*LineBuf == '*')
  272. {
  273. // Link
  274. if (FileVersion == 2)
  275. MySscanf(LineBuf+1,"1%s1 %O %s %s 1%s1",
  276. FileName, &Perms, UserName, ClassName, RealPath);
  277. else
  278. MySscanf(LineBuf+1,"1%s1 %O 1%s1 1%s1 1%s1",
  279. FileName, &Perms, UserName, ClassName, RealPath);
  280. if (*UserName == '(') *UserName = 0;
  281. if (*ClassName == '(') *ClassName = 0;
  282. if ((Perms == 0) || !*RealPath || (*RealPath == '('))
  283. continue; // Bad data...
  284. }
  285. else
  286. {
  287. // Normal file info
  288. if (FileVersion == 2)
  289. MySscanf(LineBuf,"1%s1 %O %s %s %O %ld 1%s1",
  290. FileName, &Perms, UserName, ClassName, &SpecialNewFilePerms, &DlCnt, Comment);
  291. else
  292. MySscanf(LineBuf,"1%s1 %O 1%s1 1%s1 %d %ld 1%s1",
  293. FileName, &Perms, UserName, ClassName, &SpecialNewFilePerms, &DlCnt, Comment);
  294. if (*UserName == '(') *UserName = 0;
  295. if (*ClassName == '(') *ClassName = 0;
  296. if (!stricmp(Comment,"(null)")) *Comment = 0;
  297. if (!*FileName)
  298. continue; // Bad data...
  299. fsn = new CFsysSecurityNode;
  300. int i;
  301. fsn->Perms = Perms;
  302. fsn->DlCnt = DlCnt;
  303. fsn->Owner = *UserName ? (i = atoi(UserName)) ? i : 0 : 0;
  304. fsn->Class = *ClassName ? (i = atoi(ClassName)) ? i : 0 : 0;
  305. //#ifdef _DEBUG
  306. {
  307. LPSTR p = strchr(Comment,'n');
  308. if (p)
  309. *p = 0;
  310. p = strchr(Comment,'r');
  311. if (p)
  312. *p = 0;
  313. }
  314. //#endif
  315. fsn->Comment = Comment;
  316. fsn->FileName = FileName;
  317. fsn->SpecialNewFilePerms = SpecialNewFilePerms;
  318. fsg->m_Nodes.AddLast((LPVOID)fsn);
  319. }
  320. }
  321. skip_scan:
  322. Rval = (HANDLE)fsg;
  323. done:
  324. if (Rval == INVALID_HANDLE_VALUE)
  325. {
  326. if (fsg)
  327. delete fsg;
  328. }
  329. if (LineBuf)
  330. {
  331. delete LineBuf; 
  332. delete FileName;
  333. delete RealPath;
  334. delete Comment;
  335. delete UserName;
  336. delete ClassName;
  337. }
  338. if (fp)
  339. fclose(fp);
  340. return Rval;
  341. #undef MYBUFSIZ
  342. }
  343. HANDLE CFsysSecurity::GetSecurityDescriptor(HANDLE pGrp, LPCSTR FileName)
  344. {
  345. if (pGrp == INVALID_HANDLE_VALUE)
  346. return INVALID_HANDLE_VALUE;
  347. CFsysSecurityGrp *fsg = (CFsysSecurityGrp *)pGrp;
  348. CFsysSecurityNode *fsn;
  349. CLinkedListItem *Item;
  350. for(Item = fsg->m_Nodes.First(); Item; Item = fsg->m_Nodes.Next(Item))
  351. {
  352. fsn = (CFsysSecurityNode *)fsg->m_Nodes.Ptr(Item);
  353. ASSERT(AfxIsValidString(fsn->FileName));
  354. ASSERT(AfxIsValidString(fsn->Comment));
  355. if (!stricmp(fsn->FileName,FileName))
  356. return (HANDLE)fsn;
  357. }
  358. return INVALID_HANDLE_VALUE;
  359. }
  360. void CFsysSecurity::LogMsg(int flag, LPCSTR Format, ...)
  361. {
  362. CString cBuf;
  363. if (!ShouldLog(CLog::GetLog(), flag))
  364. return;
  365. ASSERT(AfxIsValidString(Format, FALSE));
  366. ASSERT(CLog::GetLog() != NULL);
  367. ASSERT(AfxIsValidAddress(CLog::GetLog(),sizeof(CLog)));
  368. cBuf.Format("CFsysSecurity: %s", Format);
  369. va_list argList;
  370. va_start(argList, Format);
  371. CLog::GetLog()->LogMsgV(flag, cBuf, argList);
  372. va_end(argList);
  373. }
  374. BOOL CFsysSecurity::CloseSecurityGroup(HANDLE pGrp)
  375. {
  376. CFsysSecurityGrp *pMyGrp = (CFsysSecurityGrp *)pGrp;
  377. ASSERT(AfxIsValidAddress(pMyGrp, sizeof(CFsysSecurityGrp)));
  378. if (pMyGrp->m_fp)
  379. {
  380. fclose(pMyGrp->m_fp);
  381. pMyGrp->m_fp = NULL;
  382. // Try to hide the file
  383. // If we fail, we can assume that the file is mapped into the ..Index dir and
  384. // then we don't care...
  385. CString cMyPath;
  386. cMyPath.Format("%s\"SECFILE, pMyGrp->m_Path);
  387. CFileStatus fs;
  388. if (CFile::GetStatus(cMyPath,fs))
  389. {
  390. fs.m_attribute |= 0x02; // Hidden
  391. try
  392. {
  393. CFile::SetStatus(cMyPath, fs); 
  394. }
  395. catch(CFileException *e)
  396. {
  397. LogMsg(LOGF_WARNINGS,"CloseSecurityGroup() - Caught FILE ERROR exception (%d) in file '%s' while hiding the file.",
  398. e->m_cause, e->m_strFileName);
  399. e->Delete();
  400. }
  401. }
  402. }
  403. delete pMyGrp;
  404. return TRUE;
  405. }
  406. HANDLE CFsysSecurity::CreateNode(int User, HANDLE pGrp, BOOL IsDir, LPCSTR FileName)
  407. {
  408. CFsysSecurityGrp *pMyGrp = (CFsysSecurityGrp *)pGrp;
  409. ASSERT(AfxIsValidAddress(pMyGrp, sizeof(CFsysSecurityGrp)));
  410. ASSERT(AfxIsValidString(FileName));
  411. HANDLE h = GetSecurityDescriptor(pGrp, FileName);
  412. if (h != INVALID_HANDLE_VALUE)
  413. return h;
  414. CFsysSecurityNode *fsn = new CFsysSecurityNode;
  415. fsn->Perms = IsDir ? pMyGrp->DefaultPermDirs :  pMyGrp->DefaultPermFiles;
  416. fsn->Owner = 0;
  417. fsn->Class = 0;
  418. fsn->DlCnt = 0;
  419. fsn->Comment.Empty();
  420. fsn->FileName = FileName;
  421. pMyGrp->m_Nodes.AddLast((HANDLE) fsn);
  422. return (HANDLE) fsn;
  423. }
  424. // Open a security group for update (flush). Just open the file and
  425. // write the header.
  426. // Path is the file system path to the directory.
  427. // If Default* == 0xffffffff, get the default values ourself.
  428. HANDLE CFsysSecurity::OpenSecurityGroupForUpdate(LPCSTR Path, 
  429.  DWORD DefaultPermFiles,
  430.  DWORD DefaultPermDirs)
  431. {
  432. if ((DefaultPermFiles == 0xffffffff) || (DefaultPermDirs == 0xffffffff))
  433. {
  434. HANDLE h = LoadSecurityGroup(Path, FALSE);
  435. if (h == INVALID_HANDLE_VALUE)
  436. {
  437. // Set hardcoded default values (LIST + browse)
  438. if (DefaultPermFiles == 0xffffffff)
  439. DefaultPermFiles = 0;
  440. if (DefaultPermDirs == 0xffffffff)
  441. DefaultPermDirs = 0555;
  442. }
  443. else
  444. {
  445. // Get default values
  446. CFsysSecurityGrp *pSG = (CFsysSecurityGrp *)h;
  447. if (DefaultPermFiles == 0xffffffff)
  448. DefaultPermFiles = pSG->DefaultPermFiles;
  449. if (DefaultPermDirs == 0xffffffff)
  450. DefaultPermDirs = pSG->DefaultPermDirs;
  451. CloseSecurityGroup(h);
  452. }
  453. }
  454. // Open file
  455. CFsysSecurityGrp *pSG = new CFsysSecurityGrp;
  456. ASSERT(AfxIsValidAddress(pSG, sizeof(CFsysSecurityGrp)));
  457. pSG->m_Path = Path;
  458. pSG->DefaultPermFiles = DefaultPermFiles;
  459. pSG->DefaultPermDirs = DefaultPermDirs;
  460. pSG->m_fp = OpenSecurityGroupFile(Path, "w");
  461. if (!pSG->m_fp)
  462. {
  463. LogMsg(LOGF_WARNINGS,"OpenSecurityGroupForUpdate(%s) - Failed to open security group for update.",
  464. Path);
  465. return FALSE;
  466. }
  467. fprintf(pSG->m_fp,"WarSoftware Series2 4n0%o 0%on", 
  468. pSG->DefaultPermDirs, pSG->DefaultPermFiles);
  469. return (HANDLE)pSG;
  470. }
  471. void CFsysSecurity::FlushNode(
  472. HANDLE hSecGrp,
  473. LPCSTR FileName,
  474. DWORD Perms,
  475. int Owner,
  476. int Class,
  477. int DlCnt,
  478. LPCSTR Comment,
  479. DWORD SpecialNewFilePerms)
  480. {
  481. ASSERT(hSecGrp != INVALID_HANDLE_VALUE);
  482. CFsysSecurityGrp *pSG = (CFsysSecurityGrp *)hSecGrp;
  483. ASSERT(pSG->m_fp != NULL);
  484. #ifdef _DEBUG
  485. ASSERT(AfxIsValidString(FileName));
  486. ASSERT(AfxIsValidString(Comment));
  487. ASSERT(!strchr(Comment,'n'));
  488. ASSERT(!strchr(Comment,'r'));
  489. #endif
  490. fprintf(pSG->m_fp, "1%s1 0%o 1%d1 1%d1 0%o %d 1%s1n",
  491. FileName, 
  492. Perms,
  493. Owner,
  494. Class,
  495. SpecialNewFilePerms, 
  496. DlCnt,
  497. Comment);
  498. }
  499. // Update the SECFILE file from the data in memory. At the same time, delete
  500. // obsolete entries.
  501. BOOL CFsysSecurity::FlushGroup(HANDLE pGrp)
  502. {
  503. /*
  504. CFsysSecurityGrp *pMyGrp = (CFsysSecurityGrp *)pGrp;
  505. ASSERT(AfxIsValidAddress(pMyGrp, sizeof(CFsysSecurityGrp)));
  506. m_Lock.Lock();
  507. FILE *fp = OpenSecurityGroupFile(pMyGrp->m_Path, "w");
  508. if (!fp)
  509. {
  510. LogMsg(LOGF_WARNINGS,"FlushGroup(%s) - Failed to update file permissions.",
  511. pMyGrp->m_Path);
  512. m_Lock.Unlock();
  513. return FALSE;
  514. }
  515. fprintf(fp,"WarSoftware Series2 4n0%o 0%on", 
  516. pMyGrp->DefaultPermDirs, pMyGrp->DefaultPermFiles);
  517. CFsysSecurityNode *fsn;
  518. CLinkedListItem *Item;
  519. for(Item = pMyGrp->m_Nodes.First(); Item; Item = pMyGrp->m_Nodes.Next(Item))
  520. {
  521. fsn = (CFsysSecurityNode *)pMyGrp->m_Nodes.Ptr(Item);
  522. ASSERT(AfxIsValidString(fsn->FileName));
  523. ASSERT(AfxIsValidString(fsn->Comment));
  524. WIN32_FIND_DATA Data;
  525. HANDLE h = CFsys::m_pCFsys->FindFirstFile(0, pMyGrp->m_Path, &Data);
  526. if (h == INVALID_HANDLE_VALUE)
  527. {
  528. // Path dont extist. 
  529. continue;
  530. }
  531. CFsys::m_pCFsys->FindClose(h);
  532. // Update
  533. fprintf(fp,"1%s1 0%o 1%d1 1%d1 %d %ld 1%s1n",
  534. fsn->FileName, 
  535. fsn->Perms,
  536. fsn->Owner,
  537. fsn->Class,
  538. 0, // Obsolete War 1.# inode flags...
  539. fsn->DlCnt,
  540. fsn->Comment);
  541. }
  542. fclose(fp);
  543. // Try to hide the file
  544. // If we fail, we can assume that the file is mapped into the ..Index dir and
  545. // then we don't care...
  546. CString cMyPath;
  547. cMyPath.Format("%s\"SECFILE, pMyGrp->m_Path);
  548. CFsys::DosPath(cMyPath.GetBuffer(1));
  549. cMyPath.ReleaseBuffer();
  550. CFileStatus fs;
  551. if (CFile::GetStatus(cMyPath,fs))
  552. {
  553. fs.m_attribute |= 0x02; // Hidden
  554. try
  555. {
  556. CFile::SetStatus(cMyPath, fs); 
  557. }
  558. catch(CFileException *e)
  559. {
  560. LogMsg(LOGF_WARNINGS,"FlushGroup() - Caught FILE ERROR exception (%d) in file '%s' while hiding the file.",
  561. e->m_cause, e->m_strFileName);
  562. e->Delete();
  563. }
  564. }
  565. m_Lock.Unlock();*/
  566. return TRUE;
  567. }
  568. // Fill in security information
  569. BOOL CFsysSecurity::GetFsysSecurityProperties(HANDLE hGrp, CFileInfo& FileInfo)
  570. {
  571. BOOL Rval = FALSE;
  572. CFsysSecurityGrp *pMyGrp = (CFsysSecurityGrp *)hGrp;
  573. ASSERT(AfxIsValidAddress(pMyGrp, sizeof(CFsysSecurityGrp)));
  574. ASSERT(AfxIsValidString(FileInfo.m_Name));
  575. HANDLE h = GetSecurityDescriptor(hGrp, FileInfo.m_Name);
  576. if (h == INVALID_HANDLE_VALUE)
  577. {
  578. FileInfo.m_Comment = "";
  579. FileInfo.m_DLcount = 0;
  580. FileInfo.m_User = INVALID_USER_VALUE;
  581. FileInfo.m_Group = INVALID_USER_VALUE;
  582. FileInfo.m_Hide = FALSE;
  583. FileInfo.m_Flags = (FileInfo.m_DOSflags & FILE_ATTRIBUTE_DIRECTORY) 
  584. ? pMyGrp->DefaultPermDirs :  pMyGrp->DefaultPermFiles;
  585. FileInfo.m_SpecialNewFilePerms = 0;
  586. }
  587. else
  588. {
  589. CFsysSecurityNode *fsn = (CFsysSecurityNode *)h;
  590. FileInfo.m_Comment = fsn->Comment;
  591. FileInfo.m_DLcount = fsn->DlCnt;
  592. FileInfo.m_User = fsn->Owner;
  593. FileInfo.m_Group = fsn->Class;
  594. FileInfo.m_Hide = FALSE;
  595. FileInfo.m_Flags = fsn->Perms;
  596. FileInfo.m_SpecialNewFilePerms = fsn->SpecialNewFilePerms;
  597. Rval = TRUE;
  598. }
  599. if (FileInfo.m_DOSflags & FILE_ATTRIBUTE_DIRECTORY)
  600. FileInfo.m_Flags |= NODE_DIR;
  601. if (FileInfo.m_DOSflags & FILE_ATTRIBUTE_READONLY)
  602. {
  603. FileInfo.m_Flags |= NODE_READONLY;
  604. FileInfo.m_Flags &= ~(NODE_WRITEMSK);
  605. }
  606. return Rval;
  607. }
  608. int CFsysSecurity::GetPermissions(int User, int Class, 
  609. HANDLE pGrp, LPCSTR FileName, BOOL IsDir, int *Mask, 
  610. CFsysSecurityNode **pFsn, BOOL ShowRealPerms)
  611. {
  612. CFsysSecurityGrp *pMyGrp = (CFsysSecurityGrp *)pGrp;
  613. ASSERT(AfxIsValidAddress(pMyGrp, sizeof(CFsysSecurityGrp)));
  614. ASSERT(AfxIsValidString(FileName));
  615. HANDLE h = GetSecurityDescriptor(pGrp, FileName);
  616. int Perms = 0;
  617. if (!ShowRealPerms && (!User))
  618. {
  619. if (Mask)
  620. *Mask = 0777;
  621. return 0777; // Superuser or server call. Override security...
  622. }
  623. if (h == INVALID_HANDLE_VALUE)
  624. {
  625. if (Mask)
  626. *Mask = S_IRWXO;
  627. Perms = IsDir ? pMyGrp->DefaultPermDirs :  pMyGrp->DefaultPermFiles;
  628. }
  629. else
  630. {
  631. CFsysSecurityNode *fsn = (CFsysSecurityNode *)h;
  632. Perms = fsn->Perms;
  633. if (Mask)
  634. {
  635. *Mask = S_IRWXO;
  636. if (fsn->Owner && (User == fsn->Owner))
  637. *Mask |= S_IRWXU;
  638. if (fsn->Class && (Class == fsn->Class))
  639. *Mask |= S_IRWXG;
  640. }
  641. if (pFsn)
  642. *pFsn = fsn;
  643. // TODO: Check for extra permissions for this user/class
  644. }
  645. return Perms;
  646. }
  647. // Handle fopen(path,"w") to hidden files
  648. FILE *CFsysSecurity::fopen(LPCSTR DosPath, LPCSTR Mode)
  649. {
  650. DWORD dw = GetFileAttributes(DosPath);
  651. if (strchr(Mode,'w') && (dw != 0xFFFFFFFF) && (dw & FILE_ATTRIBUTE_HIDDEN))
  652. {
  653. FILE *fp;
  654. // Turn off the readonly flag
  655. dw &= ~FILE_ATTRIBUTE_HIDDEN;
  656. SetFileAttributes(DosPath,dw);
  657. // open the file
  658. fp = ::fopen(DosPath,Mode);
  659. // Turn on the readonly flag
  660. dw |= FILE_ATTRIBUTE_HIDDEN;
  661. SetFileAttributes(DosPath,dw);
  662. return fp;
  663. }
  664. return ::fopen(DosPath,Mode);
  665. }
  666. void CFsysSecurityGrp::DeleteAllNodes()
  667. {
  668. CFsysSecurityNode *fsn;
  669. while(fsn = (CFsysSecurityNode *)m_Nodes.GetAndDeleteFirst())
  670. delete fsn;
  671. }
  672. CFsysSecurityNode::~CFsysSecurityNode()
  673. {
  674. ASSERT(AfxIsValidAddress(this,sizeof(CFsysSecurityNode)));
  675. }
  676. CFsysSecurityGrp::CFsysSecurityGrp()
  677. {
  678. m_fp = NULL;
  679. }
  680. CFsysSecurityGrp::~CFsysSecurityGrp()
  681. {
  682. ASSERT(AfxIsValidAddress(this,sizeof(CFsysSecurityGrp)));
  683. DeleteAllNodes();
  684. ASSERT(m_fp == NULL);
  685. }