Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2829 lines
72 KiB

  1. //
  2. // Modification:
  3. // oct.29, 1997 changed by a-zexu to debug bug#113977(incorrect output info).
  4. // May 10, 1998 changed by a-zexu to debug bug#158667.
  5. //
  6. //
  7. #include "PERMS.H"
  8. PSID SidEveryone = NULL;
  9. PSID SidOwnerGroup = NULL;
  10. PSID SidFromLookupName = NULL;
  11. PSID ASidFromLookupName[10];
  12. PSID *AccountSids = NULL;
  13. DWORD cbSidFromLookupName=0;
  14. SAM_HANDLE SamServerHandle = NULL;
  15. SAM_HANDLE SamDomainHandle = NULL;
  16. ACCESS_MASK grant_mask = 0;
  17. BOOL g_noAccess = FALSE;
  18. BOOL owner_flag = FALSE;
  19. BOOL owner_group = FALSE;
  20. BOOL Local_Machine = TRUE;
  21. ULONG Total_Sids=0;
  22. BOOL inter_logon=FALSE; /* interactive login flag */
  23. PSECURITY_DESCRIPTOR SidFromGetFileSecurity; /* address of security descriptor */
  24. _cdecl main(int argc, char *argv[])
  25. {
  26. char
  27. UserNameBuff[LSA_WIN_STANDARD_BUFFER_SIZE], /* user name buff */
  28. SystemNameBuff[LSA_WIN_STANDARD_BUFFER_SIZE], /* system name buff */
  29. FileNameBuff[LSA_WIN_STANDARD_BUFFER_SIZE], /* system name buff */
  30. FileSystemNameBuff[LSA_WIN_STANDARD_BUFFER_SIZE], /* system name buff */
  31. RefDFromLookupName[LSA_WIN_STANDARD_BUFFER_SIZE],
  32. GeneralUseBuffer[LSA_WIN_STANDARD_BUFFER_SIZE],
  33. LocalSystemName[MAX_COMPUTERNAME_LENGTH + 1],
  34. FileName[LSA_WIN_STANDARD_BUFFER_SIZE],
  35. FilePath[LSA_WIN_STANDARD_BUFFER_SIZE];
  36. DWORD cchRefDFromLookupName=0,
  37. SidsizeFromGetFileSecurity=0,
  38. lpcbsdRequired=0,
  39. SNameLen = MAX_COMPUTERNAME_LENGTH + 1;
  40. SID_NAME_USE UseFromLookupName;
  41. DWORD cchNameFromLookupSid;
  42. char NameFromLookupSid[LSA_WIN_STANDARD_BUFFER_SIZE];
  43. char RefDFromLookupSid[LSA_WIN_STANDARD_BUFFER_SIZE];
  44. DWORD cchRefDFromLookupSid,
  45. WStatus,
  46. WNetSize = LSA_WIN_STANDARD_BUFFER_SIZE;
  47. SID_NAME_USE UseFromLookupSid;
  48. PSID usid; /* user SID pointer */
  49. LPDWORD sidsize;
  50. LPSTR User = NULL,
  51. System,
  52. Path,
  53. File = NULL,
  54. FileMachine = NULL;
  55. LPDWORD domain_size;
  56. PSID_NAME_USE psnu;
  57. LPTSTR pbslash; /* address of string for back slash */
  58. SECURITY_INFORMATION /* requested information */
  59. si =(OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION
  60. |DACL_SECURITY_INFORMATION);
  61. DWORD cbsd, LastError; /* size of security descriptor buffer */
  62. BOOL BoolStatus=TRUE;
  63. int i, k, j;
  64. ULONG ui;
  65. BOOL sys=FALSE,
  66. fl=FALSE,
  67. LocalFlag=FALSE,
  68. BackUpPriv=TRUE,
  69. DriveFlag=FALSE,
  70. RecurseFlag=FALSE,
  71. RestorePriv=TRUE,
  72. DirFlag=FALSE;
  73. ULONG AccountSidsLength;
  74. HANDLE TokenHandle,
  75. FindFileHandle;
  76. WIN32_FIND_DATA FindFileData;
  77. // Set Back up privs for process
  78. // Get our process token
  79. if(!GetTokenHandle(&TokenHandle))
  80. {
  81. syserror(GetLastError());
  82. return(TRUE);
  83. }
  84. // Have valid process token handle
  85. // Now set the backup operator priv
  86. if(!SetBackOperatorPriv(TokenHandle))
  87. BackUpPriv = FALSE;
  88. CloseHandle(TokenHandle);
  89. // Initialize some memory say for 100 sids
  90. AccountSidsLength = 100 * sizeof ( PSID );
  91. AccountSids = (PSID *) LocalAlloc( LPTR, AccountSidsLength );
  92. // Initialize some memory for a large file security discriptor
  93. SidFromGetFileSecurity = (PSECURITY_DESCRIPTOR) GlobalAlloc( GPTR, (DWORD) LARGEPSID);
  94. // Check to see if memory was allocated
  95. if(AccountSids == NULL || SidFromGetFileSecurity == NULL )
  96. {
  97. syserror(GetLastError());
  98. return(TRUE);
  99. }
  100. UserNameBuff[0] = (char) NULL;
  101. SystemNameBuff[0] = (char) NULL;
  102. FilePath[0] = (char) NULL;
  103. FileNameBuff[0] = (char) NULL;
  104. FileSystemNameBuff[0] = (char) NULL;
  105. GeneralUseBuffer[0] = (char) NULL;
  106. /* Check for valid command line argument syntax before processing */
  107. /* check for some count greater than zero and less than max argc count */
  108. if(argc > 1 && argc <= MAXARGS)
  109. {
  110. /* Need to make the following assumptions: That the first command line arg
  111. can be a help request or other switch "/? -? /i -i" or an account name.
  112. and not a switch option, could be additional switches or a path name.
  113. Also, switches can be intermixed the account name and path. Path is
  114. not required local directory is assumed. First parse switches,
  115. account and path.
  116. */
  117. /* Loop through command line args */
  118. for(i=1; i<argc; i++)
  119. {
  120. /* check length of args, 2 may indicate a switch */
  121. switch(strlen(argv[i]))
  122. {
  123. case 1:
  124. if(sys == FALSE) // if file flagg true have an invalid case
  125. {
  126. strcpy(UserNameBuff, argv[i]);
  127. // System is local
  128. System = NULL;
  129. sys = TRUE;
  130. }
  131. else
  132. {
  133. // copy the argument into the file name buffer
  134. strcpy(FileNameBuff,argv[i]);
  135. // Make the Machine name NULL for local machine
  136. FileMachine = NULL;
  137. LocalFlag = TRUE;
  138. fl = TRUE;
  139. }
  140. break;
  141. case 2: /* Valid size for switch */
  142. /* check for switch flag */
  143. if( argv[i][0] == '/' || argv[i][0] == '-')
  144. {
  145. switch((int)argv[i][1])
  146. { // Help Switch
  147. case (int) '?':
  148. usage(HELP, NULL);
  149. return(TRUE);
  150. // Interactive Logon Switchs
  151. case (int) 'i':
  152. inter_logon = TRUE;
  153. continue;
  154. case (int) 'I':
  155. inter_logon = TRUE;
  156. continue;
  157. // Recurse Subdirectories
  158. case (int) 's':
  159. RecurseFlag = TRUE;
  160. continue;
  161. case (int) 'S':
  162. RecurseFlag = TRUE;
  163. continue;
  164. default:
  165. usage(INVALID_SWT, argv[i]);
  166. usage(USAGE_ARG, NULL);
  167. return(TRUE);
  168. }
  169. }
  170. else /* if not swiches then must be a or 2 char path name */
  171. {
  172. if(sys == FALSE) // if file flag true have an invalid case
  173. {
  174. strcpy(UserNameBuff, argv[i]);
  175. // System is local
  176. System = NULL;
  177. sys = TRUE;
  178. }
  179. else
  180. {
  181. // copy the argument into the file name buffer
  182. strcpy(FileNameBuff,argv[i]);
  183. // Check for "_:" drive type
  184. pbslash = strchr(argv[i], 0x3a);
  185. if(pbslash != NULL)
  186. {
  187. strcat(FileNameBuff, "\\");
  188. // Set File pointer
  189. File = (LPTSTR) &FileNameBuff[0];
  190. }
  191. fl = TRUE;
  192. }
  193. }
  194. break;
  195. default: /* look for account or path */
  196. // Also we know that a sys/user machine\user is the first string
  197. if(sys == FALSE)
  198. {
  199. // need to to find the "\" in the
  200. pbslash = strchr(argv[i], 0x5c);
  201. // check pointer location if a NULL no "\" or at first postion in string
  202. // if no slash have a account name only
  203. if(pbslash == NULL)
  204. {
  205. strcpy(UserNameBuff, argv[i]);
  206. // Set System to NULL
  207. System = NULL;
  208. sys = TRUE;
  209. break;
  210. }
  211. if( pbslash == argv[i])
  212. {
  213. usage(INVALID_ARG, argv[i]);
  214. usage(USAGE_ARG, NULL);
  215. return(TRUE);
  216. }
  217. // copy the string from the "\" tho the user buffer
  218. strcpy(UserNameBuff, ++pbslash);
  219. // copy the string up to the "\" in to the system buffer
  220. // now terminate the string at "\" to a NULL
  221. --pbslash;
  222. *pbslash = '\0';
  223. // Check to see if we have a domain name
  224. if(!IsDomainName(argv[i], (LPSTR) SystemNameBuff))
  225. {
  226. // add the "\\" to the begining of string
  227. strcpy(SystemNameBuff, "\\\\");
  228. strcat(SystemNameBuff, argv[i]);
  229. System = (LPTSTR) &SystemNameBuff[0];
  230. }
  231. else
  232. {
  233. System = (LPTSTR) &SystemNameBuff[0];
  234. // printf("\n :%s is :%s \n", argv[i], System);
  235. }
  236. sys = TRUE;
  237. }
  238. else // File argument
  239. {
  240. // Get the local machine name
  241. // machine is in UNC form.
  242. // add the "\\" to the begining of string
  243. strcpy(LocalSystemName, "\\\\");
  244. if(!GetComputerName(&LocalSystemName[2],
  245. &SNameLen))
  246. {
  247. syserror(GetLastError());
  248. return(TRUE);
  249. }
  250. // Check for "\\" in first 2 chars in file path for UNC path
  251. if( strncmp(argv[i], "\\\\", 2) == 0)
  252. {
  253. // copy "\\ to the next \" to the file machine name
  254. for(j=0; j < (int) strlen(argv[i]); j++)
  255. {
  256. if(j<2)
  257. FileSystemNameBuff[j] = argv[i][j];
  258. else
  259. {
  260. // check for 3rd "\"
  261. if(argv[i][j] == 0x5c)
  262. break;
  263. FileSystemNameBuff[j] = argv[i][j];
  264. }
  265. }
  266. // add null to string
  267. FileSystemNameBuff[j] = '\0';
  268. // now need to check for the local machine name
  269. // The get file security call will fail if local
  270. // Compare the local machine name to the file machine
  271. if(_stricmp(LocalSystemName, FileSystemNameBuff) == 0)
  272. {
  273. // Have a local Machine UNC path
  274. // Check account machine name
  275. if(_stricmp(LocalSystemName, System) == 0)
  276. {
  277. // Have a local Machine equal to account machine
  278. // no need to look up sids for file machine.
  279. LocalFlag = TRUE;
  280. }
  281. // Make the Machine name NULL for local machine
  282. FileMachine = NULL;
  283. // Need to strip off UNC name of local machine
  284. // The j counter is at "\" character
  285. strcpy(FileNameBuff, &argv[i][j]);
  286. }
  287. else // Have a nonlocal path
  288. {
  289. // Need to check system name against account machine
  290. if(System != NULL)
  291. if(_stricmp(FileSystemNameBuff, System) == 0)
  292. {
  293. // Have a file Machine equal to account machine
  294. // no need to look up sids for file machine.
  295. LocalFlag = TRUE;
  296. }
  297. strcpy(FileNameBuff,argv[i]);
  298. FileMachine = (LPTSTR) &FileSystemNameBuff[0];
  299. }
  300. // printf("\n file machine: %s", FileMachine);
  301. }
  302. else // have a local file (assume local) or logical
  303. {
  304. // Need to get the logical or drive ie "_:"
  305. pbslash = strchr(argv[i], 0x3a);
  306. // check pointer location if a NULL assume a "\xx\xx" type path
  307. if(pbslash == NULL)
  308. {
  309. strcpy(FileNameBuff,argv[i]);
  310. // set the filemachine name to a null to force local
  311. FileMachine = NULL;
  312. }
  313. else
  314. {
  315. // Have a logical drive or a machine drive
  316. // Need the drive part
  317. k = (int) strlen(argv[i]);
  318. for(j=0; j < k; j++)
  319. {
  320. GeneralUseBuffer[j] = argv[i][j];
  321. // check for ":"
  322. if(argv[i][j] == 0x3a)
  323. break;
  324. }
  325. // add null to string
  326. GeneralUseBuffer[++j] = '\0';
  327. // WNetGetConnection
  328. WStatus = WNetGetConnection((LPTSTR) GeneralUseBuffer, // Drive name
  329. (LPTSTR) FileSystemNameBuff, // Returned Name
  330. &WNetSize);
  331. // Check return status
  332. if(WStatus == NO_ERROR)
  333. {
  334. // Have a valid redirected drive
  335. // Build the full path name
  336. strcat(FileNameBuff, argv[i]);
  337. // Next get the machine name of the share
  338. // copy "\\ to the next \" to the file machine name
  339. for(j=0; j < (int) strlen(FileSystemNameBuff); j++)
  340. {
  341. if(j>2)
  342. {
  343. // check for 3rd "\"
  344. if(FileSystemNameBuff[j] == 0x5c)
  345. break;
  346. }
  347. }
  348. // Add NULL
  349. FileSystemNameBuff[j] = '\0';
  350. FileMachine = (LPTSTR) &FileSystemNameBuff[0];
  351. }
  352. else
  353. {
  354. // Have a local machine drive
  355. strcpy(FileNameBuff,argv[i]);
  356. // Check for drive only path "_:\" or "_:"
  357. // FindFirstFile has with it.
  358. // Need to convert "_:" to "_:\"
  359. if(k <= 3)
  360. DriveFlag = TRUE;
  361. // Check for a System = NULL
  362. if(System != NULL)
  363. {
  364. // Check User Account system against local name
  365. if(_stricmp(LocalSystemName, System) == 0)
  366. {
  367. // Have a local user account machine
  368. LocalFlag = TRUE;
  369. }
  370. }
  371. else // System is Local machine
  372. LocalFlag = TRUE;
  373. // set the filemachine name to a null to force local
  374. FileMachine = NULL;
  375. }
  376. }
  377. }
  378. fl = TRUE;
  379. // Set File pointer
  380. File = (LPTSTR) &FileNameBuff[0];
  381. }
  382. break;
  383. } /* end switch */
  384. } /* end for argv loop */
  385. User = (LPTSTR) &UserNameBuff[0];
  386. // Make sure GeneralUseBuffer is null
  387. GeneralUseBuffer[0] = (CHAR) NULL;
  388. // Check to see if file was entered
  389. if(fl == FALSE)
  390. {
  391. usage(INVALID_FIL, (CHAR) NULL);
  392. return(FALSE);
  393. }
  394. // Clean up the file name ie "." ".." ".\" etc
  395. if(!CleanUpSource((LPTSTR) FileNameBuff, (LPTSTR) FileName, &DirFlag))
  396. {
  397. usage(INVALID_FIL, (LPTSTR) FileNameBuff);
  398. return(FALSE);
  399. }
  400. File = &FileName[0];
  401. Path = &FilePath[0];
  402. strcpy(Path, File);
  403. //Find last Slash
  404. pbslash = strrchr(Path, 0x5c);
  405. if(pbslash != NULL)
  406. {
  407. pbslash++;
  408. *pbslash = (CHAR) NULL;
  409. }
  410. /*** Get everyone SID by use LookupAccountName ***/
  411. /* Have no buffer sizes first call to LookupAccountName will return
  412. need buffer sizes */
  413. if( LookupAccountName( NULL,
  414. TEXT("everyone"),
  415. SidEveryone,
  416. &cbSidFromLookupName,
  417. RefDFromLookupName,
  418. &cchRefDFromLookupName,
  419. &UseFromLookupName))
  420. {
  421. usage(INVALID_ACC, User);
  422. usage(USAGE_ARG, NULL);
  423. return(TRUE);
  424. }
  425. /* Now have valid buffer sizes to call LookupAccountName for a valid SID */
  426. /* allocate memory for the sid */
  427. SidEveryone = LocalAlloc( (UINT) LMEM_FIXED, (UINT) cbSidFromLookupName);
  428. if(SidEveryone == NULL)
  429. {
  430. syserror(GetLastError());
  431. return(TRUE);
  432. }
  433. if( !LookupAccountName( NULL,
  434. TEXT("everyone"),
  435. SidEveryone,
  436. &cbSidFromLookupName,
  437. RefDFromLookupName,
  438. &cchRefDFromLookupName,
  439. &UseFromLookupName))
  440. {
  441. usage(INVALID_ACC, User);
  442. usage(USAGE_ARG, NULL);
  443. return(TRUE);
  444. }
  445. /* Have no buffer sizes first call to LookupAccountName will return
  446. need buffer sizes */
  447. if( LookupAccountName( System,
  448. User,
  449. SidFromLookupName,
  450. &cbSidFromLookupName,
  451. RefDFromLookupName,
  452. &cchRefDFromLookupName,
  453. &UseFromLookupName))
  454. {
  455. usage(INVALID_ACC, User);
  456. usage(USAGE_ARG, NULL);
  457. return(TRUE);
  458. }
  459. /* Now have valid buffer sizes to call LookupAccountName for a valid SID */
  460. /* allocate memory for the sid */
  461. SidFromLookupName = LocalAlloc( (UINT) LMEM_FIXED, (UINT) cbSidFromLookupName);
  462. if(SidFromLookupName == NULL)
  463. {
  464. syserror(GetLastError());
  465. return(TRUE);
  466. }
  467. if( !LookupAccountName( System,
  468. User,
  469. SidFromLookupName,
  470. &cbSidFromLookupName,
  471. RefDFromLookupName,
  472. &cchRefDFromLookupName,
  473. &UseFromLookupName))
  474. {
  475. usage(INVALID_ACC, User);
  476. usage(USAGE_ARG, NULL);
  477. return(TRUE);
  478. }
  479. ASidFromLookupName[0] = SidFromLookupName;
  480. if(!VariableInitialization())
  481. {
  482. syserror(GetLastError());
  483. return(TRUE);
  484. }
  485. // look up the user's group sids for the machine the accounts on
  486. BoolStatus = LookupAllUserSidsWS(System);
  487. // look up the user's group sid for the workstation that the file resides on
  488. // Need to check if the account machine and file machine are the same.
  489. // If not done duplicate sids will be build.
  490. if( LocalFlag == FALSE)
  491. {
  492. if( !LookupAllUserSidsWS(FileMachine))
  493. {
  494. // system error message
  495. syserror(GetLastError());
  496. return(TRUE);
  497. }
  498. }
  499. // Not a directory
  500. if(!DirFlag)
  501. {
  502. // Need to get the findfirstfile
  503. FindFileHandle = FindFirstFile(File, &FindFileData);
  504. if(FindFileHandle == INVALID_HANDLE_VALUE)
  505. {
  506. usage(INVALID_FIL, (LPTSTR) FileNameBuff);
  507. return(FALSE);
  508. }
  509. // FindClose(FindFileHandle);
  510. if(Path != NULL)
  511. {
  512. strcpy(File, Path);
  513. // This sould give a valid path
  514. strcat(File,FindFileData.cFileName);
  515. }
  516. else
  517. strcpy(File,FindFileData.cFileName);
  518. }
  519. else // need to fake out the Finfirstfile data structure
  520. FindFileData.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
  521. // Now have all of the user sid and the first file.
  522. // Loop through the files
  523. while(1)
  524. {
  525. if(strcmp(FindFileData.cFileName, ".") != 0)
  526. if(strcmp(FindFileData.cFileName, "..") != 0)
  527. {
  528. /* The call to GetFileSecurity works similar to LookupAccountName
  529. in that the first call get need buffer sizes */
  530. // Use a fairly larger buffer size of returned size value.
  531. // This will keep the number of malloc type calls down.
  532. SidsizeFromGetFileSecurity = LARGEPSID;
  533. BoolStatus = GetFileSecurityBackup(File,
  534. si,
  535. SidFromGetFileSecurity,
  536. SidsizeFromGetFileSecurity, /* buffer size */
  537. &lpcbsdRequired, /* required buffer size */
  538. BackUpPriv);
  539. if(!BoolStatus)
  540. {
  541. // GetFileSecurity failed need to check if buffer was to small
  542. if(lpcbsdRequired != 0)
  543. {
  544. SidsizeFromGetFileSecurity = lpcbsdRequired;
  545. // Reallocate the memory to the new size
  546. SidFromGetFileSecurity = GlobalReAlloc( SidFromGetFileSecurity, lpcbsdRequired, GMEM_ZEROINIT);
  547. BoolStatus = GetFileSecurityBackup(File,
  548. si,
  549. SidFromGetFileSecurity,
  550. SidsizeFromGetFileSecurity,
  551. &lpcbsdRequired,
  552. BackUpPriv);
  553. if(!BoolStatus)
  554. {
  555. syserror(GetLastError());
  556. return(TRUE);
  557. }
  558. }
  559. else // Have a problem with file
  560. {
  561. usage(INVALID_FIL, (LPTSTR) File);
  562. return(FALSE);
  563. }
  564. }
  565. // Clear access masks
  566. grant_mask = 0;
  567. if(!GetFilePermissions(SidFromGetFileSecurity, (PSID) SidFromLookupName))
  568. {
  569. syserror(GetLastError());
  570. return(TRUE);
  571. }
  572. // Need to chech for directory structure
  573. if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  574. {
  575. // Display the directory perms
  576. if(!IsLastCharSlash(File))
  577. strcat(File, "\\");
  578. DisplayPerms(File, TRUE);
  579. // Check Recurse subdirectories flagg
  580. // This is ugly but time is short
  581. if(!DirFlag)
  582. if(RecurseFlag == TRUE)
  583. {
  584. // Need the Filename, Path, user account sid, and Backup priv flag
  585. RecurseSubs(FindFileData.cFileName, Path, SidFromLookupName, BackUpPriv,
  586. RecurseFlag);
  587. }
  588. }
  589. else // For initial files that are directories
  590. if(!DirFlag)
  591. DisplayPerms(File, TRUE);
  592. } // End if "." .""
  593. // Go for the next file
  594. // for recursing subdirectories.
  595. if(DirFlag)
  596. {
  597. // Check recurse flag
  598. if(RecurseFlag)
  599. {
  600. // Need to update the path
  601. strcpy(Path, File);
  602. // Add the wild card
  603. strcat(File, "*");
  604. FindClose(FindFileHandle);
  605. // Need to get the findfirstfile
  606. FindFileHandle = FindFirstFile(File, &FindFileData);
  607. if(FindFileHandle == INVALID_HANDLE_VALUE)
  608. {
  609. syserror(GetLastError());
  610. return(TRUE);
  611. }
  612. // Add path to file
  613. strcpy(File, Path);
  614. // This sould give a valid path
  615. strcat(File,FindFileData.cFileName);
  616. DirFlag = FALSE;
  617. continue;
  618. }
  619. // Have only a single directory
  620. // if(!IsLastCharSlash(File))
  621. // strcat(File, "\\");
  622. // DisplayPerms(File, TRUE);
  623. break;
  624. }
  625. if(FindNextFile(FindFileHandle, &FindFileData))
  626. {
  627. if(Path != NULL)
  628. {
  629. strcpy(File, Path);
  630. // This sould give a valid path
  631. strcat(File,FindFileData.cFileName);
  632. }
  633. else
  634. strcpy(File,FindFileData.cFileName);
  635. }
  636. else // Have end of files
  637. break;
  638. } // End While loop
  639. FindClose(FindFileHandle);
  640. // free memory
  641. if(AccountSids)
  642. LocalFree(AccountSids);
  643. if(SidFromLookupName)
  644. LocalFree(SidFromLookupName);
  645. if(SidEveryone)
  646. LocalFree(SidEveryone);
  647. return(TRUE);
  648. } /* end of main if */
  649. else
  650. usage(HELP, NULL);
  651. return(TRUE);
  652. } /* End of Main */
  653. /* *********************************************************************
  654. Recure Subdirectories
  655. ************************************************************************ */
  656. BOOL
  657. RecurseSubs(IN LPTSTR FileName,
  658. IN LPTSTR FilePath,
  659. IN PSID UserSid,
  660. IN BOOL BackPriv,
  661. IN BOOL Recurse)
  662. {
  663. char
  664. PathBuff[LSA_WIN_STANDARD_BUFFER_SIZE],
  665. FileNameBuffer[LSA_WIN_STANDARD_BUFFER_SIZE],
  666. GeneralUseBuffer[LSA_WIN_STANDARD_BUFFER_SIZE];
  667. DWORD cchRefDFromLookupName=0,
  668. SidsizeFromGetFileSecurity=0,
  669. lpcbsdRequired=0;
  670. SID_NAME_USE UseFromLookupSid;
  671. LPSTR RPath,
  672. RFile;
  673. SECURITY_INFORMATION si; /* requested information */
  674. BOOL BoolStatus=TRUE;
  675. ULONG AccountSidsLength;
  676. HANDLE FileHandle;
  677. WIN32_FIND_DATA FindFileData;
  678. // Need to create a wildcard file name for FindFirstFile
  679. sprintf(FileNameBuffer, "%s%s%s", FilePath, FileName, "\\*");
  680. RFile = (LPTSTR) &FileNameBuffer[0];
  681. // Update path to include the new directory
  682. sprintf(PathBuff, "%s%s%s", FilePath, FileName, "\\");
  683. RPath = (LPTSTR) &PathBuff[0];
  684. FileHandle = FindFirstFile(RFile, &FindFileData);
  685. if(FileHandle == INVALID_HANDLE_VALUE)
  686. return(FALSE);
  687. si =(OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION
  688. |DACL_SECURITY_INFORMATION);
  689. // Now have all of the user sid and the first file.
  690. // Loop through the files
  691. while(1)
  692. {
  693. // Need to check for "." and ".."
  694. if(strcmp(FindFileData.cFileName, ".") != 0)
  695. if(strcmp(FindFileData.cFileName, "..") != 0)
  696. {
  697. sprintf(RFile, "%s%s", RPath, FindFileData.cFileName);
  698. /* The call to GetFileSecurity works similar to LookupAccountName
  699. in that the first call get need buffer sizes */
  700. // Use a fairly larger buffer size of returned size value.
  701. // This will keep the number of malloc type calls down.
  702. SidsizeFromGetFileSecurity = LARGEPSID;
  703. BoolStatus = GetFileSecurityBackup(RFile,
  704. si,
  705. SidFromGetFileSecurity,
  706. SidsizeFromGetFileSecurity, /* buffer size */
  707. &lpcbsdRequired, /* required buffer size */
  708. BackPriv);
  709. if(!BoolStatus)
  710. {
  711. // GetFileSecurity failed need to check if buffer was to small
  712. if(lpcbsdRequired != 0)
  713. {
  714. SidsizeFromGetFileSecurity = lpcbsdRequired;
  715. // Reallocate the memory to the new size
  716. SidFromGetFileSecurity = GlobalReAlloc( SidFromGetFileSecurity, lpcbsdRequired, GMEM_ZEROINIT);
  717. BoolStatus = GetFileSecurityBackup(RFile,
  718. si,
  719. SidFromGetFileSecurity,
  720. SidsizeFromGetFileSecurity,
  721. &lpcbsdRequired,
  722. BackPriv);
  723. if(!BoolStatus)
  724. {
  725. return(FALSE);
  726. }
  727. }
  728. // Have general failure this is a access priv problem.
  729. DisplayPerms(RFile, FALSE);
  730. }
  731. if(BoolStatus) // Valid file security discriptor
  732. {
  733. grant_mask = 0;
  734. if(!GetFilePermissions(SidFromGetFileSecurity, (PSID) UserSid))
  735. return(FALSE);
  736. // Need to chech for directory structure
  737. if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  738. {
  739. // Display the directory perms
  740. strcat(RFile, "\\");
  741. DisplayPerms(RFile, TRUE);
  742. // Recurse subdirectories
  743. // Need the Filename, Path, user account sid, and Backup priv flag
  744. RecurseSubs(FindFileData.cFileName, RPath, SidFromLookupName, BackPriv,
  745. Recurse);
  746. }
  747. else
  748. DisplayPerms(RFile, TRUE);
  749. } // End of valid security descriptor else
  750. } // end of ". or .." if
  751. // Go for the next file
  752. if(!FindNextFile(FileHandle, &FindFileData))
  753. break;
  754. } // End While loop
  755. return(TRUE);
  756. }
  757. /* ***************************************************************
  758. Usage Error subroutine
  759. ******************************************************************* */
  760. void usage(IN INT message_num,
  761. IN PCHAR string_val)
  762. {
  763. if(string_val == NULL)
  764. fprintf(stderr, "\n%s\n", MESSAGES[message_num]);
  765. else
  766. fprintf(stderr,"\n%s %s\n", MESSAGES[message_num], string_val);
  767. }
  768. /*
  769. System Error subroutine
  770. */
  771. void syserror(DWORD error_val)
  772. {
  773. CHAR MessageBuf[512];
  774. DWORD eval,
  775. Lang_Val;
  776. Lang_Val = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
  777. FormatMessage(
  778. FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
  779. NULL,
  780. error_val,
  781. Lang_Val,
  782. (LPTSTR) MessageBuf,
  783. 512,
  784. NULL);
  785. printf("\n%s", MessageBuf);
  786. }
  787. /* ********************************************************************* */
  788. BOOL IsDomainName(
  789. IN LPSTR TestDomainName,
  790. IN LPSTR DomainNameBuff)
  791. {
  792. NTSTATUS dNtStatus;
  793. ANSI_STRING AnsiString;
  794. UNICODE_STRING UDomainName;
  795. NET_API_STATUS NetCallStatus;
  796. LPBYTE xbuff = NULL;
  797. LPWSTR NDomainName;
  798. UINT BuffSize;
  799. INT AnsiSize, slen;
  800. UDomainName.Buffer = NULL;
  801. // get a unicode string
  802. RtlInitAnsiString( &AnsiString, TestDomainName );
  803. dNtStatus = RtlAnsiStringToUnicodeString( &UDomainName, &AnsiString, TRUE );
  804. // Free up the ansi string to use it later
  805. // RtlFreeAnsiString(&AnsiString);
  806. // Compute the needed amount of memory for a zero terminated string
  807. // Allocate the memory and zero it
  808. BuffSize = (UINT) (UDomainName.Length * 2) + 4;
  809. NDomainName = LocalAlloc( (UINT) LPTR,
  810. BuffSize);
  811. if (NDomainName == NULL)
  812. {
  813. syserror(GetLastError());
  814. exit(FALSE);
  815. }
  816. // Copy the wide string to the allocated memory
  817. RtlMoveMemory( NDomainName, UDomainName.Buffer, BuffSize-4);
  818. // Should now have a zero terminated string
  819. // now check for the domain name
  820. NetCallStatus = NetGetDCName(NULL, NDomainName,
  821. &xbuff );
  822. if(NetCallStatus == ERROR_SUCCESS)
  823. {
  824. // Convert the wchar null string to ansi sting is passed back machine
  825. // name of domain controler
  826. // Use the current unicode buffer
  827. slen = wcslen((USHORT *) xbuff) * 2;
  828. UDomainName.Length = (USHORT) slen;
  829. UDomainName.MaximumLength = (USHORT) slen + 2;
  830. UDomainName.Buffer = (PWSTR) xbuff;
  831. dNtStatus = RtlUnicodeStringToAnsiString( &AnsiString, &UDomainName, TRUE );
  832. // return the string pointer
  833. RtlMoveMemory( DomainNameBuff, AnsiString.Buffer,
  834. (UINT) strlen(AnsiString.Buffer) +1);
  835. LocalFree(NDomainName);
  836. return(TRUE);
  837. }
  838. LocalFree(NDomainName);
  839. return(FALSE);
  840. }
  841. /* ********************************************************************* */
  842. BOOL
  843. LookupAllUserSidsWS( IN LPSTR lpSystemName
  844. )
  845. /*++
  846. Routine Description:
  847. Arguments:
  848. Return Value:
  849. BOOL - TRUE is returned if successful, else FALSE.
  850. --*/
  851. {
  852. NTSTATUS xNtStatus;
  853. ANSI_STRING AnsiString;
  854. UNICODE_STRING USystemName;
  855. ULONG Count;
  856. OBJECT_ATTRIBUTES ObjectAttributes;
  857. SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
  858. LSA_HANDLE PolicyHandle = NULL;
  859. UNICODE_STRING AccountDomainName;
  860. PPOLICY_ACCOUNT_DOMAIN_INFO PolicyAccountDomainInfo;
  861. USystemName.Buffer = NULL;
  862. RtlInitAnsiString( &AnsiString, lpSystemName );
  863. xNtStatus = RtlAnsiStringToUnicodeString( &USystemName, &AnsiString, TRUE );
  864. if (!NT_SUCCESS(xNtStatus))
  865. {
  866. SetLastError(xNtStatus);
  867. return(FALSE);
  868. }
  869. //
  870. // Open a handle to the target Workstation's Policy Object so that we can
  871. // information from it and also so that we can use it for looking up.
  872. // Sids
  873. //
  874. InitObjectAttributes(
  875. &ObjectAttributes,
  876. &SecurityQualityOfService
  877. );
  878. xNtStatus = LsaOpenPolicy(
  879. &USystemName, // WorkstationName,
  880. &ObjectAttributes,
  881. POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION,
  882. &PolicyHandle
  883. );
  884. if (!NT_SUCCESS(xNtStatus))
  885. {
  886. // try local machine
  887. PolicyHandle = NULL;
  888. xNtStatus = LsaOpenPolicy(
  889. NULL, // WorkstationName,
  890. &ObjectAttributes,
  891. POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION,
  892. &PolicyHandle
  893. );
  894. if (!NT_SUCCESS(xNtStatus))
  895. {
  896. SetLastError(xNtStatus);
  897. return(FALSE);
  898. }
  899. }
  900. // Lookup the Group Sids contained in the Workstation's
  901. // SAM Account Domain
  902. //
  903. // First, obtain the Name and Sid of the SAM Account Domain from the
  904. // Workstation's LSA Policy Object.
  905. //
  906. xNtStatus = LsaQueryInformationPolicy(
  907. PolicyHandle,
  908. PolicyAccountDomainInformation,
  909. (PVOID *) &PolicyAccountDomainInfo
  910. );
  911. if (!NT_SUCCESS(xNtStatus))
  912. {
  913. SetLastError(xNtStatus);
  914. return(FALSE);
  915. }
  916. AccountDomainName = PolicyAccountDomainInfo->DomainName;
  917. xNtStatus = LsaClose(PolicyHandle);
  918. if(!NT_SUCCESS(xNtStatus))
  919. {
  920. SetLastError(xNtStatus);
  921. return(FALSE);
  922. }
  923. if(!LookupSidsInSamDomain(
  924. &USystemName, // WorkstationName,
  925. &USystemName, // WorkstationName,
  926. &AccountDomainName
  927. ))
  928. return(FALSE);
  929. if( USystemName.Buffer != NULL )
  930. {
  931. RtlFreeUnicodeString( &USystemName );
  932. }
  933. return(TRUE);
  934. }
  935. BOOL
  936. GeneralBuildSid(
  937. OUT PSID *Sid,
  938. IN PSID DomainSid,
  939. IN ULONG RelativeId
  940. )
  941. /*++
  942. Routine Description:
  943. This function builds a Sid from a Domain Sid and a RelativeId.
  944. Arguments:
  945. Sid - Receives a pointer to the constructed Sid.
  946. DomainSid - Points to a Domain Sid
  947. RelativeId - Contains a Relative Id
  948. BOOL - TRUE if successful, else FALSE.
  949. --*/
  950. {
  951. PSID OutputSid = NULL;
  952. ULONG OutputSidLength;
  953. UCHAR SubAuthorityCount;
  954. SubAuthorityCount = *RtlSubAuthorityCountSid( DomainSid ) + (UCHAR) 1;
  955. OutputSidLength = RtlLengthRequiredSid( SubAuthorityCount );
  956. OutputSid = LocalAlloc( (UINT) LMEM_FIXED, (UINT) OutputSidLength );
  957. if (OutputSid == NULL) {
  958. return(FALSE);
  959. }
  960. RtlMoveMemory( OutputSid, DomainSid, OutputSidLength - sizeof (ULONG));
  961. (*RtlSubAuthorityCountSid( OutputSid ))++;
  962. (*RtlSubAuthoritySid(OutputSid, SubAuthorityCount - (UCHAR) 1)) = RelativeId;
  963. *Sid = OutputSid;
  964. return(TRUE);
  965. }
  966. VOID
  967. InitObjectAttributes(
  968. IN POBJECT_ATTRIBUTES ObjectAttributes,
  969. IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService
  970. )
  971. /* ++
  972. Routine Description:
  973. This function initializes the given Object Attributes structure, including
  974. Security Quality Of Service. Memory must be allcated for both
  975. ObjectAttributes and Security QOS by the caller.
  976. Arguments:
  977. ObjectAttributes - Pointer to Object Attributes to be initialized.
  978. SecurityQualityOfService - Pointer to Security QOS to be initialized.
  979. Return Value:
  980. None.
  981. -- */
  982. {
  983. SecurityQualityOfService->Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
  984. SecurityQualityOfService->ImpersonationLevel = SecurityImpersonation;
  985. SecurityQualityOfService->ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  986. SecurityQualityOfService->EffectiveOnly = FALSE;
  987. //
  988. // Set up the object attributes prior to opening the LSA.
  989. //
  990. InitializeObjectAttributes(
  991. ObjectAttributes,
  992. NULL,
  993. 0L,
  994. NULL,
  995. NULL
  996. );
  997. //
  998. // The InitializeObjectAttributes macro presently stores NULL for
  999. // the SecurityQualityOfService field, so we must manually copy that
  1000. // structure for now.
  1001. //
  1002. ObjectAttributes->SecurityQualityOfService = SecurityQualityOfService;
  1003. }
  1004. BOOL
  1005. LookupSidsInSamDomain(
  1006. IN OPTIONAL PUNICODE_STRING WorkstationName,
  1007. IN PUNICODE_STRING DomainControllerName,
  1008. IN PUNICODE_STRING SamDomainName
  1009. )
  1010. /*++
  1011. Routine Description:
  1012. This function enumerates all the SAM accounts of a specified type
  1013. in a specified SAM domain on a specified target system. The system
  1014. must be one of the following:
  1015. o The Workstation itself.
  1016. o A Domain Controller for the Primary Domain of the Workstation.
  1017. o A Domain Controller for one of the Trusted Domains of the
  1018. Workstation.
  1019. Having enumerated the accounts, the function then performs
  1020. an LsaLookupSids call via the specified Workstation to lookup all of
  1021. these account Sids, and then compares the returned information
  1022. with that expected.
  1023. Arguments:
  1024. WorkstationName - Specifies a Workstation Name. The name may be
  1025. the NULL string, which means the current system.
  1026. DomainControllerName - Specifies the name of a target Domain Controller
  1027. for (the Workstation's Primary Domain or one of its Trusted
  1028. Domains.
  1029. SamDomainName - Specifies the name of the SAM Domain. This is either
  1030. the BUILTIN Domain or the name of the Accounts Domain.
  1031. SamAccountType - Specifies the type of SAM account to be enumerated
  1032. and looked up.
  1033. Return Values:
  1034. BOOL - TRUE if successful, else FALSE.
  1035. --*/
  1036. {
  1037. NTSTATUS CtStatus;
  1038. BOOL BooleanStatus = TRUE;
  1039. OBJECT_ATTRIBUTES SamObjectAttributes;
  1040. OBJECT_ATTRIBUTES LsaObjectAttributes;
  1041. PSID SamDomainSid = NULL;
  1042. SID WorldTypeSid = SECURITY_WORLD_SID_AUTHORITY;
  1043. PSAM_RID_ENUMERATION EnumerationBuffer = NULL;
  1044. ULONG DomainIndex;
  1045. ULONG UserAccountControl;
  1046. ULONG GroupCount;
  1047. ULONG SidCount=0;
  1048. ULONG Relid=0;
  1049. ULONG RidIndex=0;
  1050. ULONG GenRid;
  1051. ULONG CountReturned;
  1052. PULONG AliasBuffer;
  1053. UNICODE_STRING TmpDomainControllerName;
  1054. PVOID EnumerationInformation;
  1055. ULONG EnumerationContext;
  1056. ULONG PreferedMaximumLength;
  1057. //
  1058. // Connect to the SAM server.
  1059. //
  1060. CtStatus = SamConnect(
  1061. DomainControllerName,
  1062. &SamServerHandle,
  1063. SAM_SERVER_ENUMERATE_DOMAINS | SAM_SERVER_LOOKUP_DOMAIN,
  1064. &SamObjectAttributes
  1065. );
  1066. if (!NT_SUCCESS(CtStatus))
  1067. {
  1068. // try local machine
  1069. CtStatus = SamConnect(
  1070. NULL, // DomainControllerName,
  1071. &SamServerHandle,
  1072. SAM_SERVER_ENUMERATE_DOMAINS | SAM_SERVER_LOOKUP_DOMAIN,
  1073. &SamObjectAttributes
  1074. );
  1075. if (!NT_SUCCESS(CtStatus))
  1076. {
  1077. SetLastError(CtStatus);
  1078. return(FALSE);
  1079. }
  1080. }
  1081. //
  1082. // Lookup the Named Domain in the Sam Server to get its Sid.
  1083. //
  1084. CountReturned = 0;
  1085. EnumerationContext = 0;
  1086. EnumerationBuffer = NULL;
  1087. PreferedMaximumLength = 512;
  1088. CtStatus = SamEnumerateDomainsInSamServer(
  1089. SamServerHandle,
  1090. &EnumerationContext,
  1091. (PVOID *) &EnumerationBuffer,
  1092. PreferedMaximumLength,
  1093. &CountReturned
  1094. );
  1095. if(!NT_SUCCESS(CtStatus))
  1096. {
  1097. SetLastError(CtStatus);
  1098. return(FALSE);
  1099. }
  1100. if((INT) CountReturned == 0)
  1101. {
  1102. SetLastError(CtStatus);
  1103. return(FALSE);
  1104. }
  1105. //
  1106. // Now look up the sid for the domains in the samserver
  1107. //
  1108. for(DomainIndex = 0; DomainIndex < CountReturned; DomainIndex++)
  1109. {
  1110. // if(SamDomainHandle != NULL)
  1111. // CtStatus = SamCloseHandle(SamDomainHandle);
  1112. SamDomainHandle = NULL;
  1113. SamDomainSid = NULL;
  1114. GroupCount = 0;
  1115. SidCount = 0;
  1116. CtStatus = SamLookupDomainInSamServer(
  1117. SamServerHandle,
  1118. (PUNICODE_STRING) &EnumerationBuffer[ DomainIndex ].Name, // SamDomainName,
  1119. &SamDomainSid
  1120. );
  1121. if(!NT_SUCCESS(CtStatus))
  1122. {
  1123. SetLastError(CtStatus);
  1124. return(FALSE);
  1125. }
  1126. //
  1127. // Open the Domain
  1128. //
  1129. CtStatus = SamOpenDomain(
  1130. SamServerHandle,
  1131. (GENERIC_READ | GENERIC_EXECUTE), //(DOMAIN_LIST_ACCOUNTS|DOMAIN_GET_ALIAS_MEMBERSHIP)
  1132. SamDomainSid,
  1133. &SamDomainHandle
  1134. );
  1135. if (!NT_SUCCESS(CtStatus))
  1136. {
  1137. SetLastError(CtStatus);
  1138. return(FALSE);
  1139. }
  1140. CtStatus = SamGetAliasMembership(
  1141. SamDomainHandle,
  1142. 1,
  1143. ASidFromLookupName,
  1144. &GroupCount,
  1145. &AliasBuffer
  1146. );
  1147. if(!NT_SUCCESS(CtStatus))
  1148. {
  1149. SetLastError(CtStatus);
  1150. return(FALSE);
  1151. }
  1152. if (GroupCount == 0)
  1153. {
  1154. // SamCloseHandle(SamDomainHandle);
  1155. SamFreeMemory(AliasBuffer);
  1156. SamDomainSid = NULL;
  1157. GroupCount = 0;
  1158. SidCount = 0;
  1159. continue;
  1160. }
  1161. //
  1162. // Now construct the Account Sids from the Rids just enumerated.
  1163. // We prepend the Sam Domain Sid to the Rids.
  1164. //
  1165. SidCount = RidIndex + GroupCount;
  1166. for (RidIndex; RidIndex < SidCount; RidIndex++)
  1167. {
  1168. Relid = AliasBuffer[ RidIndex ];
  1169. if (!GeneralBuildSid(
  1170. &(AccountSids[Total_Sids++]),
  1171. SamDomainSid,
  1172. AliasBuffer[ RidIndex ]
  1173. ))
  1174. {
  1175. SetLastError(CtStatus);
  1176. return(FALSE);
  1177. }
  1178. } // end for loop
  1179. // free up Sam memory to use again
  1180. SamFreeMemory(AliasBuffer);
  1181. } // domain for loop
  1182. // add world sid
  1183. AccountSids[Total_Sids++] = SeWorldSid;
  1184. // if interactive logon
  1185. if(inter_logon)
  1186. {
  1187. // printf("\n adding Interactive sid ");
  1188. AccountSids[Total_Sids++] = SeInteractiveSid;
  1189. }
  1190. else
  1191. AccountSids[Total_Sids++] = SeNetworkSid;
  1192. // Add in Account Sid
  1193. AccountSids[Total_Sids++] = SidFromLookupName;
  1194. //
  1195. // If necessary, close the SAM Domain Handle for the Workstation.
  1196. //
  1197. if(SamDomainHandle != NULL)
  1198. CtStatus = SamCloseHandle( SamDomainHandle);
  1199. //
  1200. // If necessary, disconnect from the SAM Server.
  1201. //
  1202. if(SamServerHandle != NULL)
  1203. CtStatus = SamCloseHandle( SamServerHandle );
  1204. return(TRUE);
  1205. }
  1206. //
  1207. //
  1208. //
  1209. void DisplayPerms(IN LPTSTR filename, IN BOOL valid_access)
  1210. {
  1211. if(g_noAccess)
  1212. {
  1213. printf("-");
  1214. goto exit;
  1215. }
  1216. if(valid_access)
  1217. {
  1218. if(owner_flag == TRUE)
  1219. printf("*");
  1220. else if(owner_group == TRUE)
  1221. printf("#");
  1222. if( grant_mask == 0)
  1223. {
  1224. printf("?");
  1225. goto exit;
  1226. }
  1227. if(grant_mask == FILE_GEN_ALL)
  1228. {
  1229. printf("A");
  1230. goto exit;
  1231. }
  1232. if((FILE_GENERIC_READ & grant_mask) == FILE_GENERIC_READ)
  1233. printf("R");
  1234. if((FILE_GENERIC_WRITE & grant_mask) == FILE_GENERIC_WRITE)
  1235. printf("W");
  1236. if((FILE_GENERIC_EXECUTE & grant_mask) == FILE_GENERIC_EXECUTE)
  1237. printf("X");
  1238. if((DELETE & grant_mask) == DELETE)
  1239. printf("D");
  1240. if((WRITE_DAC & grant_mask) == WRITE_DAC)
  1241. printf("P");
  1242. if((WRITE_OWNER & grant_mask) == WRITE_OWNER)
  1243. printf("O");
  1244. } // End if !valid_access
  1245. else
  1246. printf("?");
  1247. exit:
  1248. printf("\t%s\n", filename);
  1249. return;
  1250. }
  1251. BOOL GetFilePermissions(
  1252. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  1253. OUT PSID UserAccountSids)
  1254. {
  1255. PISECURITY_DESCRIPTOR ISecurityDescriptor;
  1256. UCHAR Revision;
  1257. SECURITY_DESCRIPTOR_CONTROL Control;
  1258. PSID Owner;
  1259. PSID Group;
  1260. PACL Sacl;
  1261. PACL Dacl;
  1262. ULONG ui;
  1263. ISecurityDescriptor = ( PISECURITY_DESCRIPTOR )SecurityDescriptor;
  1264. Revision = ISecurityDescriptor->Revision;
  1265. Control = ISecurityDescriptor->Control;
  1266. Owner = SepOwnerAddrSecurityDescriptor( ISecurityDescriptor );
  1267. Group = SepGroupAddrSecurityDescriptor( ISecurityDescriptor );
  1268. Sacl = SepSaclAddrSecurityDescriptor( ISecurityDescriptor );
  1269. Dacl = SepDaclAddrSecurityDescriptor( ISecurityDescriptor );
  1270. if(EqualSid(UserAccountSids, Owner))
  1271. owner_flag = TRUE;
  1272. // check all the group sids for owner
  1273. for(ui=0; ui < Total_Sids; ui++)
  1274. {
  1275. if(EqualSid(AccountSids[ui], Owner))
  1276. {
  1277. SidOwnerGroup = AccountSids[ui];
  1278. owner_group = TRUE;
  1279. }
  1280. }
  1281. if(Dacl == NULL)
  1282. {
  1283. return(TRUE);
  1284. }
  1285. else
  1286. {
  1287. // Check the user sid ACLS
  1288. if(!ProcessAcl( Dacl))
  1289. {
  1290. return(FALSE);
  1291. }
  1292. }
  1293. return(TRUE);
  1294. }
  1295. /* ********************************************************************** */
  1296. // changed by a-zexu @ 5/10/98
  1297. BOOL ProcessAcl(PACL Acl)
  1298. {
  1299. ULONG i;
  1300. PACCESS_ALLOWED_ACE Ace;
  1301. BOOL KnownType = FALSE;
  1302. ULONG isid;
  1303. ACCESS_MASK mask = 0;
  1304. PCHAR AceTypes[] = { "Access Allowed",
  1305. "Access Denied ",
  1306. "System Audit ",
  1307. "System Alarm " };
  1308. // Check if the Acl is null.
  1309. if (Acl == NULL)
  1310. return(FALSE);
  1311. // Now for each Ace check the Sids of Owner
  1312. if(owner_group)
  1313. {
  1314. mask = 0;
  1315. for (i = 0, Ace = FirstAce(Acl);
  1316. i < Acl->AceCount;
  1317. i++, Ace = NextAce(Ace) )
  1318. {
  1319. if(EqualSid(SidOwnerGroup, &Ace->SidStart))
  1320. {
  1321. // Special case on the standard ace types
  1322. if(Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
  1323. {
  1324. mask = Ace->Mask;
  1325. }
  1326. else if(Ace->Header.AceType == ACCESS_DENIED_ACE_TYPE)
  1327. g_noAccess = TRUE;
  1328. }
  1329. } //end ace loop
  1330. grant_mask |= mask;
  1331. }
  1332. // Now for each Ace check the Sids of Everyone
  1333. if(!g_noAccess && SidEveryone)
  1334. {
  1335. mask = 0;
  1336. for (i = 0, Ace = FirstAce(Acl);
  1337. i < Acl->AceCount;
  1338. i++, Ace = NextAce(Ace) )
  1339. {
  1340. if(EqualSid(SidEveryone, &Ace->SidStart))
  1341. {
  1342. // Special case on the standard ace types
  1343. if(Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
  1344. {
  1345. mask = Ace->Mask;
  1346. }
  1347. else if(Ace->Header.AceType == ACCESS_DENIED_ACE_TYPE)
  1348. g_noAccess = TRUE;
  1349. }
  1350. } //end ace loop
  1351. grant_mask |= mask;
  1352. }
  1353. // Now for each Ace check the Sids of the user
  1354. if(!g_noAccess)
  1355. {
  1356. mask = 0;
  1357. for (i = 0, Ace = FirstAce(Acl);
  1358. i < Acl->AceCount;
  1359. i++, Ace = NextAce(Ace) )
  1360. {
  1361. if(EqualSid(SidFromLookupName, &Ace->SidStart))
  1362. {
  1363. // Special case on the standard ace types
  1364. if(Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
  1365. {
  1366. mask = Ace->Mask;
  1367. }
  1368. else if(Ace->Header.AceType == ACCESS_DENIED_ACE_TYPE)
  1369. g_noAccess = TRUE;
  1370. }
  1371. } //end ace loop
  1372. grant_mask |= mask;
  1373. }
  1374. return(TRUE);
  1375. }
  1376. /********************************************************************/
  1377. BOOL
  1378. VariableInitialization()
  1379. /*++
  1380. Routine Description:
  1381. This function initializes the global variables used by and exposed
  1382. by security.
  1383. Arguments:
  1384. None.
  1385. Return Value:
  1386. TRUE if variables successfully initialized.
  1387. FALSE if not successfully initialized.
  1388. --*/
  1389. {
  1390. PVOID HeapHandel;
  1391. ULONG SidWithZeroSubAuthorities;
  1392. ULONG SidWithOneSubAuthority;
  1393. ULONG SidWithTwoSubAuthorities;
  1394. ULONG SidWithThreeSubAuthorities;
  1395. SID_IDENTIFIER_AUTHORITY NullSidAuthority;
  1396. SID_IDENTIFIER_AUTHORITY WorldSidAuthority;
  1397. SID_IDENTIFIER_AUTHORITY LocalSidAuthority;
  1398. SID_IDENTIFIER_AUTHORITY CreatorSidAuthority;
  1399. SID_IDENTIFIER_AUTHORITY SeNtAuthority;
  1400. //
  1401. // Get the handle to the current process heap
  1402. //
  1403. HeapHandel = RtlProcessHeap();
  1404. NullSidAuthority = SepNullSidAuthority;
  1405. WorldSidAuthority = SepWorldSidAuthority;
  1406. LocalSidAuthority = SepLocalSidAuthority;
  1407. CreatorSidAuthority = SepCreatorSidAuthority;
  1408. SeNtAuthority = SepNtAuthority;
  1409. //
  1410. // The following SID sizes need to be allocated
  1411. //
  1412. SidWithZeroSubAuthorities = RtlLengthRequiredSid( 0 );
  1413. SidWithOneSubAuthority = RtlLengthRequiredSid( 1 );
  1414. SidWithTwoSubAuthorities = RtlLengthRequiredSid( 2 );
  1415. SidWithThreeSubAuthorities = RtlLengthRequiredSid( 3 );
  1416. //
  1417. // Allocate and initialize the universal SIDs
  1418. //
  1419. SeNullSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithOneSubAuthority);
  1420. SeWorldSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithOneSubAuthority);
  1421. SeLocalSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithOneSubAuthority);
  1422. SeCreatorOwnerSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithOneSubAuthority);
  1423. SeCreatorGroupSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithOneSubAuthority);
  1424. //
  1425. // Fail initialization if we didn't get enough memory for the universal
  1426. // SIDs.
  1427. //
  1428. if ( (SeNullSid == NULL) ||
  1429. (SeWorldSid == NULL) ||
  1430. (SeLocalSid == NULL) ||
  1431. (SeCreatorOwnerSid == NULL) ||
  1432. (SeCreatorGroupSid == NULL)
  1433. )
  1434. {
  1435. return( FALSE );
  1436. }
  1437. RtlInitializeSid( SeNullSid, &NullSidAuthority, 1 );
  1438. RtlInitializeSid( SeWorldSid, &WorldSidAuthority, 1 );
  1439. RtlInitializeSid( SeLocalSid, &LocalSidAuthority, 1 );
  1440. RtlInitializeSid( SeCreatorOwnerSid, &CreatorSidAuthority, 1 );
  1441. RtlInitializeSid( SeCreatorGroupSid, &CreatorSidAuthority, 1 );
  1442. *(RtlSubAuthoritySid( SeNullSid, 0 )) = SECURITY_NULL_RID;
  1443. *(RtlSubAuthoritySid( SeWorldSid, 0 )) = SECURITY_WORLD_RID;
  1444. *(RtlSubAuthoritySid( SeLocalSid, 0 )) = SECURITY_LOCAL_RID;
  1445. *(RtlSubAuthoritySid( SeCreatorOwnerSid, 0 )) = SECURITY_CREATOR_OWNER_RID;
  1446. *(RtlSubAuthoritySid( SeCreatorGroupSid, 0 )) = SECURITY_CREATOR_GROUP_RID;
  1447. //
  1448. // Allocate and initialize the NT defined SIDs
  1449. //
  1450. SeNetworkSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithOneSubAuthority);
  1451. SeInteractiveSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithOneSubAuthority);
  1452. SeLocalSystemSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithOneSubAuthority);
  1453. SeAliasAdminsSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithTwoSubAuthorities);
  1454. SeAliasUsersSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithTwoSubAuthorities);
  1455. SeAliasGuestsSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithTwoSubAuthorities);
  1456. SeAliasPowerUsersSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithTwoSubAuthorities);
  1457. SeAliasAccountOpsSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithTwoSubAuthorities);
  1458. SeAliasSystemOpsSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithTwoSubAuthorities);
  1459. SeAliasPrintOpsSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithTwoSubAuthorities);
  1460. SeAliasBackupOpsSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithTwoSubAuthorities);
  1461. //
  1462. // Fail initialization if we didn't get enough memory for the NT SIDs.
  1463. //
  1464. if((SeNetworkSid == NULL) ||
  1465. (SeInteractiveSid == NULL) ||
  1466. (SeLocalSystemSid == NULL) ||
  1467. (SeAliasAdminsSid == NULL) ||
  1468. (SeAliasUsersSid == NULL) ||
  1469. (SeAliasGuestsSid == NULL) ||
  1470. (SeAliasPowerUsersSid == NULL) ||
  1471. (SeAliasAccountOpsSid == NULL) ||
  1472. (SeAliasSystemOpsSid == NULL) ||
  1473. (SeAliasPrintOpsSid == NULL) ||
  1474. (SeAliasBackupOpsSid == NULL)
  1475. ) {
  1476. return(FALSE);
  1477. }
  1478. RtlInitializeSid( SeNetworkSid, &SeNtAuthority, 1 );
  1479. RtlInitializeSid( SeInteractiveSid, &SeNtAuthority, 1 );
  1480. RtlInitializeSid( SeLocalSystemSid, &SeNtAuthority, 1 );
  1481. *(RtlSubAuthoritySid( SeNetworkSid, 0 )) = SECURITY_NETWORK_RID;
  1482. *(RtlSubAuthoritySid( SeInteractiveSid, 0 )) = SECURITY_INTERACTIVE_RID;
  1483. *(RtlSubAuthoritySid( SeLocalSystemSid, 0 )) = SECURITY_LOCAL_SYSTEM_RID;
  1484. return(TRUE);
  1485. }
  1486. /* ************************************************************************* */
  1487. BOOL
  1488. GetTokenHandle(
  1489. IN OUT PHANDLE TokenHandle
  1490. )
  1491. //
  1492. // This routine will open the current process and return
  1493. // a handle to its token.
  1494. //
  1495. // These handles will be closed for us when the process
  1496. // exits.
  1497. //
  1498. {
  1499. HANDLE ProcessHandle;
  1500. BOOL Result;
  1501. ProcessHandle = OpenProcess(
  1502. PROCESS_QUERY_INFORMATION,
  1503. FALSE,
  1504. GetCurrentProcessId()
  1505. );
  1506. if (ProcessHandle == NULL)
  1507. return(FALSE);
  1508. Result = OpenProcessToken (
  1509. ProcessHandle,
  1510. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  1511. TokenHandle
  1512. );
  1513. if (!Result)
  1514. return(FALSE);
  1515. return(TRUE);
  1516. }
  1517. /* *********************************************************************** */
  1518. BOOL
  1519. SetBackOperatorPriv(
  1520. IN HANDLE TokenHandle
  1521. )
  1522. //
  1523. // This routine turns on SeSetBackupPrivilege in the current
  1524. // token. Once that has been accomplished, we can open the file
  1525. // for READ_OWNER even if we are denied that access by the ACL
  1526. // on the file.
  1527. {
  1528. LUID SetBackupPrivilegeValue;
  1529. TOKEN_PRIVILEGES TokenPrivileges;
  1530. //
  1531. // First, find out the value of Backup Privilege
  1532. //
  1533. if(!LookupPrivilegeValue(
  1534. NULL,
  1535. "SeBackupPrivilege",
  1536. &SetBackupPrivilegeValue
  1537. ))
  1538. return(FALSE);
  1539. //
  1540. // Set up the privilege set we will need
  1541. //
  1542. TokenPrivileges.PrivilegeCount = 1;
  1543. TokenPrivileges.Privileges[0].Luid = SetBackupPrivilegeValue;
  1544. TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  1545. (VOID) AdjustTokenPrivileges (
  1546. TokenHandle,
  1547. FALSE,
  1548. &TokenPrivileges,
  1549. sizeof( TOKEN_PRIVILEGES ),
  1550. NULL,
  1551. NULL
  1552. );
  1553. if(GetLastError() != NO_ERROR )
  1554. return(FALSE);
  1555. return(TRUE);
  1556. }
  1557. BOOL
  1558. GetFileSecurityBackupW(
  1559. LPWSTR lpFileName,
  1560. SECURITY_INFORMATION RequestedInformation,
  1561. PSECURITY_DESCRIPTOR pSecurityDescriptor,
  1562. DWORD nLength,
  1563. LPDWORD lpnLengthNeeded,
  1564. BOOL UseBackUp
  1565. )
  1566. /*++
  1567. Routine Description:
  1568. This API returns top the caller a copy of the security descriptor
  1569. protecting a file or directory. Based on the caller's access
  1570. rights and privileges, this procedure will return a security
  1571. descriptor containing the requested security descriptor fields.
  1572. To read the handle's security descriptor the caller must be
  1573. granted READ_CONTROL access or be the owner of the object. In
  1574. addition, the caller must have SeSecurityPrivilege privilege to
  1575. read the system ACL.
  1576. Arguments:
  1577. lpFileName - Represents the name of the file or directory whose
  1578. security is being retrieved.
  1579. RequestedInformation - A pointer to the security information being
  1580. requested.
  1581. pSecurityDescriptor - A pointer to the buffer to receive a copy of
  1582. the secrity descriptor protecting the object that the caller
  1583. has the rigth to view. The security descriptor is returned in
  1584. self-relative format.
  1585. nLength - The size, in bytes, of the security descriptor buffer.
  1586. lpnLengthNeeded - A pointer to the variable to receive the number
  1587. of bytes needed to store the complete secruity descriptor. If
  1588. returned number of bytes is less than or equal to nLength then
  1589. the entire security descriptor is returned in the output
  1590. buffer, otherwise none of the descriptor is returned.
  1591. Return Value:
  1592. TRUE is returned for success, FALSE if access is denied or if the
  1593. buffer is too small to hold the security descriptor.
  1594. --*/
  1595. {
  1596. NTSTATUS WStatus;
  1597. HANDLE FileHandle;
  1598. ACCESS_MASK DesiredAccess;
  1599. OBJECT_ATTRIBUTES Obja;
  1600. UNICODE_STRING FileName;
  1601. RTL_RELATIVE_NAME_U RelativeName;
  1602. IO_STATUS_BLOCK IoStatusBlock;
  1603. PVOID FreeBuffer;
  1604. QuerySecAccessMask(
  1605. RequestedInformation,
  1606. &DesiredAccess
  1607. );
  1608. if(!RtlDosPathNameToRelativeNtPathName_U(
  1609. lpFileName,
  1610. &FileName,
  1611. NULL,
  1612. &RelativeName
  1613. ))
  1614. {
  1615. return(FALSE);
  1616. }
  1617. FreeBuffer = FileName.Buffer;
  1618. if(RelativeName.RelativeName.Length)
  1619. {
  1620. FileName = RelativeName.RelativeName;
  1621. }
  1622. else
  1623. {
  1624. RelativeName.ContainingDirectory = NULL;
  1625. }
  1626. InitializeObjectAttributes(
  1627. &Obja,
  1628. &FileName,
  1629. OBJ_CASE_INSENSITIVE,
  1630. RelativeName.ContainingDirectory,
  1631. NULL
  1632. );
  1633. // Check for backup operator priv.
  1634. if(UseBackUp)
  1635. {
  1636. WStatus = NtOpenFile(
  1637. &FileHandle,
  1638. DesiredAccess,
  1639. &Obja,
  1640. &IoStatusBlock,
  1641. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  1642. FILE_OPEN_FOR_BACKUP_INTENT
  1643. );
  1644. }
  1645. else
  1646. {
  1647. WStatus = NtOpenFile(
  1648. &FileHandle,
  1649. DesiredAccess,
  1650. &Obja,
  1651. &IoStatusBlock,
  1652. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  1653. 0
  1654. );
  1655. }
  1656. RtlReleaseRelativeName(&RelativeName);
  1657. RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);
  1658. if(NT_SUCCESS(WStatus))
  1659. {
  1660. WStatus = NtQuerySecurityObject(
  1661. FileHandle,
  1662. RequestedInformation,
  1663. pSecurityDescriptor,
  1664. nLength,
  1665. lpnLengthNeeded
  1666. );
  1667. NtClose(FileHandle);
  1668. }
  1669. if(!NT_SUCCESS(WStatus))
  1670. {
  1671. // LastNTError(WStatus);
  1672. return(FALSE);
  1673. }
  1674. return(TRUE);
  1675. }
  1676. BOOL
  1677. GetFileSecurityBackup(
  1678. LPSTR lpFileName,
  1679. SECURITY_INFORMATION RequestedInformation,
  1680. PSECURITY_DESCRIPTOR pSecurityDescriptor,
  1681. DWORD nLength,
  1682. LPDWORD lpnLengthNeeded,
  1683. BOOL BackUpPrivFlag
  1684. )
  1685. /*++
  1686. Routine Description:
  1687. ANSI thunk to GetFileSecurityBackupW
  1688. --*/
  1689. {
  1690. PUNICODE_STRING Unicode;
  1691. ANSI_STRING AnsiString;
  1692. NTSTATUS FStatus;
  1693. Unicode = &NtCurrentTeb()->StaticUnicodeString;
  1694. RtlInitAnsiString(&AnsiString,lpFileName);
  1695. FStatus = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE);
  1696. if(!NT_SUCCESS(FStatus))
  1697. {
  1698. // LastNTError(FStatus);
  1699. return FALSE;
  1700. }
  1701. return ( GetFileSecurityBackupW( Unicode->Buffer,
  1702. RequestedInformation,
  1703. pSecurityDescriptor,
  1704. nLength,
  1705. lpnLengthNeeded,
  1706. BackUpPrivFlag
  1707. )
  1708. );
  1709. }
  1710. VOID
  1711. QuerySecAccessMask(
  1712. IN SECURITY_INFORMATION SecurityInformation,
  1713. OUT LPDWORD DesiredAccess
  1714. )
  1715. /*++
  1716. Routine Description:
  1717. This routine builds an access mask representing the accesses necessary
  1718. to query the object security information specified in the
  1719. SecurityInformation parameter. While it is not difficult to determine
  1720. this information, the use of a single routine to generate it will ensure
  1721. minimal impact when the security information associated with an object is
  1722. extended in the future (to include mandatory access control information).
  1723. Arguments:
  1724. SecurityInformation - Identifies the object's security information to be
  1725. queried.
  1726. DesiredAccess - Points to an access mask to be set to represent the
  1727. accesses necessary to query the information specified in the
  1728. SecurityInformation parameter.
  1729. Return Value:
  1730. None.
  1731. --*/
  1732. {
  1733. //
  1734. // Figure out accesses needed to perform the indicated operation(s).
  1735. //
  1736. (*DesiredAccess) = 0;
  1737. if ((SecurityInformation & OWNER_SECURITY_INFORMATION) ||
  1738. (SecurityInformation & GROUP_SECURITY_INFORMATION) ||
  1739. (SecurityInformation & DACL_SECURITY_INFORMATION)) {
  1740. (*DesiredAccess) |= READ_CONTROL;
  1741. }
  1742. if ((SecurityInformation & SACL_SECURITY_INFORMATION)) {
  1743. (*DesiredAccess) |= ACCESS_SYSTEM_SECURITY;
  1744. }
  1745. return;
  1746. } // end function
  1747. /* ******************************************************************
  1748. This routines filter out odd user inputs . .. ../ / _: and
  1749. unc //xxx/xxx. The routine adds a backslash to root level
  1750. directories only. For the "FROM" String.
  1751. ****************************************************************** */
  1752. BOOL CleanUpSource(IN LPTSTR InString,
  1753. OUT LPTSTR OutString,
  1754. OUT BOOL *DirectoryFlag)
  1755. {
  1756. LPTSTR searchchar,
  1757. schar,
  1758. OutstringAddr=NULL;
  1759. char CurDir[STANDARD_BUFFER_SIZE],
  1760. SaveCurDir[STANDARD_BUFFER_SIZE],
  1761. TempBuff[STANDARD_BUFFER_SIZE];
  1762. DWORD DirNameLen;
  1763. BOOL Valid=TRUE;
  1764. strcpy(OutString, InString);
  1765. OutstringAddr=OutString;
  1766. // Check for ":" file type
  1767. searchchar = strchr(OutString, ':');
  1768. if(searchchar != NULL)
  1769. {
  1770. // Have a device type root dir
  1771. // Check the next char of NULL
  1772. searchchar++;
  1773. if(*searchchar == (CHAR) NULL)
  1774. {
  1775. // add a "\" after the ":"
  1776. *searchchar = 0x5c;
  1777. searchchar++;
  1778. // Terminate the string
  1779. *searchchar = (CHAR) NULL;
  1780. *DirectoryFlag = TRUE;
  1781. return(TRUE);
  1782. }
  1783. // Have a : Check for "\"
  1784. // Note this takes care of _:\ paths Can't Do Checking on redirected
  1785. // drives with findfirstfile program will blow out later
  1786. if(*searchchar == 0x5c)
  1787. {
  1788. //check for NULL
  1789. searchchar++;
  1790. if(*searchchar == (CHAR) NULL)
  1791. {
  1792. *DirectoryFlag = TRUE;
  1793. return(TRUE);
  1794. }
  1795. }
  1796. // Need to check for relative path stuff ".\.\.." etc
  1797. if(IsRelativeString(InString))
  1798. {
  1799. strcpy(TempBuff, InString);
  1800. // Save Current directory
  1801. DirNameLen = GetCurrentDirectory(STANDARD_BUFFER_SIZE,
  1802. (LPTSTR) SaveCurDir);
  1803. if(DirNameLen == 0)
  1804. return(FALSE);
  1805. // Find the end directory
  1806. searchchar = strrchr(InString, 0x5c);
  1807. schar = strrchr(TempBuff, 0x5c);
  1808. if(schar == NULL)
  1809. return(FALSE);
  1810. // Chech for . or ..
  1811. schar++;
  1812. if(*schar == '.')
  1813. {
  1814. schar++;
  1815. if(*schar == '.')
  1816. {
  1817. schar++;
  1818. *schar == (CHAR) NULL;
  1819. searchchar+3;
  1820. }
  1821. }
  1822. else
  1823. {
  1824. schar--;
  1825. *schar == (CHAR) NULL;
  1826. }
  1827. // Have the path now get the real path
  1828. if(!SetCurrentDirectory(TempBuff))
  1829. return(FALSE);
  1830. // Now Save the current directory
  1831. DirNameLen = GetCurrentDirectory(STANDARD_BUFFER_SIZE, (LPTSTR) CurDir);
  1832. if(DirNameLen == 0)
  1833. return(FALSE);
  1834. *OutstringAddr = (CHAR) NULL;
  1835. // Build The String with real path
  1836. strcpy(OutString, CurDir);
  1837. // Remove end "\" from "C:\" GetCurrentDir.. returns with "\" on root
  1838. RemoveEndSlash(OutString);
  1839. strcat(OutString, searchchar);
  1840. // return to the user's diretory
  1841. if(!SetCurrentDirectory(SaveCurDir))
  1842. return(FALSE);
  1843. }
  1844. // Check for wild card
  1845. if(IsWildCard(OutString))
  1846. {
  1847. *DirectoryFlag = FALSE;
  1848. return(TRUE);
  1849. }
  1850. // Check for Direcory or file
  1851. if(!IsDirectory(OutString, &Valid))
  1852. *DirectoryFlag = FALSE;
  1853. else
  1854. *DirectoryFlag = TRUE;
  1855. if(Valid == FALSE)
  1856. return(FALSE);
  1857. return(TRUE);
  1858. }
  1859. // Have a nondevice name
  1860. // Check for "\\" in first 2 chars in file path for UNC path
  1861. if(strncmp(InString, "\\\\", 2) == 0)
  1862. {
  1863. // Bump pointer
  1864. InString +=3;
  1865. // Serarch for the next "\"
  1866. searchchar = strchr(InString, 0x5c);
  1867. if(searchchar == NULL)
  1868. return(FALSE);
  1869. // Have the 3rd one check for fourth on in typical UNC string
  1870. searchchar++;
  1871. searchchar = strchr(searchchar, 0x5c);
  1872. if(searchchar == NULL)
  1873. { // Have UNC Pth Only
  1874. // Need to add "\" to end of string
  1875. strcat(OutString, "\\");
  1876. *DirectoryFlag = TRUE;
  1877. return(TRUE);
  1878. }
  1879. else
  1880. {
  1881. // Have the fouth "\" need to check for file or directory
  1882. // Check for wild card
  1883. if(IsWildCard(OutString))
  1884. {
  1885. *DirectoryFlag = FALSE;
  1886. return(TRUE);
  1887. }
  1888. // Check for Direcory or file
  1889. if(!IsDirectory(OutString, &Valid))
  1890. *DirectoryFlag = FALSE;
  1891. else
  1892. *DirectoryFlag = TRUE;
  1893. if(Valid == FALSE)
  1894. return(FALSE);
  1895. return(TRUE);
  1896. }
  1897. } // End of "\\"
  1898. // Check for a "\"
  1899. if(*OutString == 0x5c)
  1900. {
  1901. // Have a leading "\" check next char
  1902. OutString++;
  1903. if(*OutString != (CHAR) NULL)
  1904. {
  1905. // Check for wild card
  1906. if(IsWildCard(InString))
  1907. {
  1908. *DirectoryFlag = FALSE;
  1909. return(TRUE);
  1910. }
  1911. // Check for directory
  1912. if(!IsDirectory(InString, &Valid))
  1913. *DirectoryFlag = FALSE;
  1914. else
  1915. *DirectoryFlag = TRUE;
  1916. if(Valid == FALSE)
  1917. return(FALSE);
  1918. return(TRUE);
  1919. }
  1920. // Have a single need to get full "_:\"
  1921. DirNameLen = GetCurrentDirectory(STANDARD_BUFFER_SIZE, (LPTSTR) CurDir);
  1922. if(DirNameLen == 0)
  1923. return(FALSE);
  1924. // Now feed the result in to StripRootDir
  1925. // Set OutString to a NULL char to recive the string
  1926. OutString--;
  1927. *OutString = (CHAR) NULL;
  1928. if(!StripRootDir( (LPTSTR) CurDir, OutString))
  1929. return(FALSE);
  1930. *DirectoryFlag = TRUE;
  1931. return(TRUE);
  1932. } // End of "\"
  1933. // Now check for .. ../
  1934. if(strncmp(InString, "..", 2) == 0)
  1935. {
  1936. // Save Current directory
  1937. DirNameLen = GetCurrentDirectory(STANDARD_BUFFER_SIZE, (LPTSTR) SaveCurDir);
  1938. if(DirNameLen == 0)
  1939. return(FALSE);
  1940. // Chech the Input string for the last Slash
  1941. searchchar = strrchr(InString, 0x5c);
  1942. if(searchchar == NULL)
  1943. { // Just have ..
  1944. // set current dir to where the path (InString) is
  1945. if(!SetCurrentDirectory(InString))
  1946. return(FALSE);
  1947. // Now Save the current directory
  1948. DirNameLen = GetCurrentDirectory(STANDARD_BUFFER_SIZE, (LPTSTR) CurDir);
  1949. if(DirNameLen == 0)
  1950. return(FALSE);
  1951. strcpy(OutString, CurDir);
  1952. *DirectoryFlag = TRUE;
  1953. // return to the user's diretory
  1954. if(!SetCurrentDirectory(SaveCurDir))
  1955. return(FALSE);
  1956. return(TRUE);
  1957. }
  1958. else // Have smething after the ..
  1959. {
  1960. // Need to check for a ending ".."
  1961. schar = strstr(searchchar, "..");
  1962. if(schar != NULL)
  1963. {
  1964. // set current dir to where the path (InString) is
  1965. if(!SetCurrentDirectory(InString))
  1966. return(FALSE);
  1967. // Now Save the current directory
  1968. DirNameLen = GetCurrentDirectory(STANDARD_BUFFER_SIZE, (LPTSTR) CurDir);
  1969. if(DirNameLen == 0)
  1970. return(FALSE);
  1971. // Save the path
  1972. strcpy(OutString, CurDir);
  1973. *DirectoryFlag = TRUE;
  1974. // return to the user's diretory
  1975. if(!SetCurrentDirectory(SaveCurDir))
  1976. return(FALSE);
  1977. return(TRUE);
  1978. }
  1979. // Save the last "\" Position
  1980. schar = strrchr(OutString, 0x5c);
  1981. // Terminate the string after the last slash
  1982. *schar = (CHAR) NULL;
  1983. // set current dir to where the path (OutString) is
  1984. if(!SetCurrentDirectory(OutString))
  1985. return(FALSE);
  1986. // Now Save the current directory
  1987. DirNameLen = GetCurrentDirectory(STANDARD_BUFFER_SIZE, (LPTSTR) CurDir);
  1988. if(DirNameLen == 0)
  1989. return(FALSE);
  1990. // Save the path
  1991. strcpy(OutString, CurDir);
  1992. // Copy anything after and including the "\" for the input string
  1993. strcat(OutString, searchchar);
  1994. // Check for wildcard
  1995. if(IsWildCard(InString))
  1996. {
  1997. // Restore dir path
  1998. if(!SetCurrentDirectory(SaveCurDir))
  1999. return(FALSE);
  2000. *DirectoryFlag = FALSE;
  2001. return(TRUE);
  2002. }
  2003. // Check for Direcory or file
  2004. if(!IsDirectory(OutString, &Valid))
  2005. *DirectoryFlag = FALSE;
  2006. else
  2007. *DirectoryFlag = TRUE;
  2008. // Restore dir path
  2009. if(!SetCurrentDirectory(SaveCurDir))
  2010. return(FALSE);
  2011. if(Valid == FALSE)
  2012. return(FALSE);
  2013. return(TRUE);
  2014. }
  2015. } // End of "..\"
  2016. // "." and ".\"
  2017. if(*InString == '.')
  2018. {
  2019. // Save Current directory
  2020. DirNameLen = GetCurrentDirectory(STANDARD_BUFFER_SIZE, (LPTSTR) SaveCurDir);
  2021. if(DirNameLen == 0)
  2022. return(FALSE);
  2023. // Chech the Input string for the last Slash
  2024. searchchar = strrchr(InString, 0x5c);
  2025. if(searchchar == NULL)
  2026. { // Just have . or something after it ._
  2027. // set current dir to where the path (InString) is
  2028. if(!SetCurrentDirectory(InString))
  2029. {
  2030. strcpy(OutString, SaveCurDir);
  2031. // Add "\" directory
  2032. strcat(OutString, "\\");
  2033. strcat(OutString, InString);
  2034. *DirectoryFlag = FALSE;
  2035. return(TRUE);
  2036. }
  2037. // Now Save the current directory
  2038. DirNameLen = GetCurrentDirectory(STANDARD_BUFFER_SIZE, (LPTSTR) CurDir);
  2039. if(DirNameLen == 0)
  2040. return(FALSE);
  2041. strcpy(OutString, CurDir);
  2042. *DirectoryFlag = TRUE;
  2043. // return to the user's diretory
  2044. if(!SetCurrentDirectory(SaveCurDir))
  2045. return(FALSE);
  2046. return(TRUE);
  2047. }
  2048. else // Have smething after the .
  2049. {
  2050. // Need to check for a ending ".."
  2051. schar = strstr(searchchar, "..");
  2052. if(schar != NULL)
  2053. {
  2054. // set current dir to where the path (InString) is
  2055. if(!SetCurrentDirectory(InString))
  2056. return(FALSE);
  2057. // Now Save the current directory
  2058. DirNameLen = GetCurrentDirectory(STANDARD_BUFFER_SIZE, (LPTSTR) CurDir);
  2059. if(DirNameLen == 0)
  2060. return(FALSE);
  2061. // Save the path
  2062. strcpy(OutString, CurDir);
  2063. *DirectoryFlag = TRUE;
  2064. // return to the user's diretory
  2065. if(!SetCurrentDirectory(SaveCurDir))
  2066. return(FALSE);
  2067. return(TRUE);
  2068. }
  2069. // Save the last "\" Position
  2070. schar = strrchr(OutString, 0x5c);
  2071. // Terminate the string after the last slash
  2072. *schar = (CHAR) NULL;
  2073. // set current dir to where the path (OutString) is
  2074. if(!SetCurrentDirectory(OutString))
  2075. return(FALSE);
  2076. // Now Save the current directory
  2077. DirNameLen = GetCurrentDirectory(STANDARD_BUFFER_SIZE, (LPTSTR) CurDir);
  2078. if(DirNameLen == 0)
  2079. return(FALSE);
  2080. // Save the path
  2081. strcpy(OutString, CurDir);
  2082. // Copy anything after and including the "\" for the input string
  2083. strcat(OutString, searchchar);
  2084. // Check for wildcard
  2085. if(IsWildCard(InString))
  2086. {
  2087. // Restore dir path
  2088. if(!SetCurrentDirectory(SaveCurDir))
  2089. return(FALSE);
  2090. *DirectoryFlag = FALSE;
  2091. return(TRUE);
  2092. }
  2093. // Check for Direcory or file
  2094. if(!IsDirectory(OutString, &Valid))
  2095. *DirectoryFlag = FALSE;
  2096. else
  2097. *DirectoryFlag = TRUE;
  2098. // Restore dir path
  2099. if(!SetCurrentDirectory(SaveCurDir))
  2100. return(FALSE);
  2101. if(Valid == FALSE)
  2102. return(FALSE);
  2103. return(TRUE);
  2104. }
  2105. } // End of "." ".\"
  2106. // Now only have a file name or directory local
  2107. DirNameLen = GetCurrentDirectory(STANDARD_BUFFER_SIZE, (LPTSTR) CurDir);
  2108. if(DirNameLen == 0)
  2109. return(FALSE);
  2110. strcpy(OutString, CurDir);
  2111. // Check if last last char slash
  2112. if(!IsLastCharSlash(OutString))
  2113. strcat(OutString, "\\");
  2114. strcat(OutString, InString);
  2115. // Check for wild Card
  2116. if(IsWildCard(InString))
  2117. {
  2118. *DirectoryFlag = FALSE;
  2119. return(TRUE);
  2120. }
  2121. // Check for Directory
  2122. if(!IsDirectory(OutString, &Valid))
  2123. *DirectoryFlag = FALSE;
  2124. else
  2125. *DirectoryFlag = TRUE;
  2126. if(Valid == FALSE)
  2127. return(FALSE);
  2128. return(TRUE);
  2129. }
  2130. /* ********************************************************************
  2131. *********************************************************************** */
  2132. BOOL IsDirectory(IN LPTSTR InTestFile,
  2133. IN BOOL *FileValid)
  2134. {
  2135. WIN32_FIND_DATA FindFileData;
  2136. HANDLE FindFileHandle;
  2137. char IsBuff[STANDARD_BUFFER_SIZE];
  2138. strcpy(IsBuff, InTestFile);
  2139. if(RemoveEndSlash((LPTSTR) IsBuff))
  2140. FindFileHandle = FindFirstFile(IsBuff, &FindFileData);
  2141. else
  2142. FindFileHandle = FindFirstFile(InTestFile, &FindFileData);
  2143. if(FindFileHandle == INVALID_HANDLE_VALUE)
  2144. {
  2145. // printf("\n problem with findfirstfile in IsDirectory");
  2146. *FileValid = FALSE;
  2147. return(FALSE);
  2148. }
  2149. if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  2150. {
  2151. FindClose(FindFileHandle); // changed by a-zexu @ 10/19/97
  2152. return(TRUE);
  2153. }
  2154. FindClose(FindFileHandle); // changed by a-zexu @ 10/19/97
  2155. return(FALSE);
  2156. }
  2157. BOOL IsWildCard(LPSTR psz)
  2158. {
  2159. char ch;
  2160. while (ch = *psz++)
  2161. {
  2162. if (ch == '*' || ch == '?')
  2163. return(TRUE);
  2164. }
  2165. return(FALSE);
  2166. }
  2167. BOOL RemoveEndSlash(LPSTR TestString)
  2168. {
  2169. LPTSTR slashptr;
  2170. slashptr = strrchr(TestString, 0x5c);
  2171. if(slashptr == NULL)
  2172. return(FALSE);
  2173. // Check Next char for NULL
  2174. slashptr++;
  2175. if(*slashptr == (CHAR) NULL)
  2176. {
  2177. slashptr--;
  2178. *slashptr = (CHAR) NULL;
  2179. return(TRUE);
  2180. }
  2181. return(FALSE);
  2182. }
  2183. BOOL SetSlash(IN LPTSTR InString,
  2184. IN OUT LPTSTR TestString)
  2185. {
  2186. LPTSTR slashptr;
  2187. strcpy(TestString, InString);
  2188. slashptr = strrchr(TestString, 0x5c);
  2189. if(slashptr == NULL)
  2190. return(FALSE);
  2191. slashptr++;
  2192. *slashptr = (CHAR) NULL;
  2193. return(TRUE);
  2194. }
  2195. BOOL AddDotSlash(LPSTR TestString)
  2196. {
  2197. LPTSTR slashptr;
  2198. // Find End of String
  2199. slashptr = strrchr(TestString, (CHAR) NULL);
  2200. if(slashptr == NULL)
  2201. return(FALSE);
  2202. // Check previous char for "\"
  2203. slashptr--;
  2204. if(*slashptr == 0x5c)
  2205. {
  2206. slashptr++;
  2207. *slashptr = '.';
  2208. slashptr++;
  2209. *slashptr = (CHAR) NULL;
  2210. }
  2211. else
  2212. {
  2213. slashptr++;
  2214. *slashptr = 0x5c;
  2215. slashptr++;
  2216. *slashptr = '.';
  2217. slashptr++;
  2218. *slashptr = (CHAR) NULL;
  2219. }
  2220. return(TRUE);
  2221. }
  2222. BOOL AddWildCards(LPSTR TestString)
  2223. {
  2224. LPTSTR slashptr;
  2225. // Find End of String
  2226. slashptr = strrchr(TestString, (CHAR) NULL);
  2227. if(slashptr == NULL)
  2228. return(FALSE);
  2229. // Check previous char for "\"
  2230. slashptr--;
  2231. if(*slashptr == 0x5c)
  2232. {
  2233. slashptr++;
  2234. *slashptr = '*';
  2235. slashptr++;
  2236. *slashptr = '.';
  2237. slashptr++;
  2238. *slashptr = '*';
  2239. slashptr++;
  2240. *slashptr = (CHAR) NULL;
  2241. }
  2242. else
  2243. {
  2244. slashptr++;
  2245. *slashptr = 0x5c;
  2246. slashptr++;
  2247. *slashptr = '*';
  2248. slashptr++;
  2249. *slashptr = '.';
  2250. slashptr++;
  2251. *slashptr = '*';
  2252. slashptr++;
  2253. *slashptr = (CHAR) NULL;
  2254. }
  2255. return(TRUE);
  2256. }
  2257. BOOL IsLastCharSlash(LPSTR TestString)
  2258. {
  2259. LPTSTR slashptr;
  2260. // Find End of String
  2261. slashptr = strrchr(TestString, (CHAR) NULL);
  2262. if(slashptr == NULL)
  2263. return(FALSE);
  2264. // Check previous char for "\"
  2265. slashptr--;
  2266. if(*slashptr == 0x5c)
  2267. return(TRUE);
  2268. return(FALSE);
  2269. }
  2270. BOOL IsRelativeString(LPSTR TestString)
  2271. {
  2272. LPTSTR slashptr;
  2273. // Start looking for Relative strings order is important
  2274. slashptr = strstr(TestString, "..\\");
  2275. if(slashptr != NULL)
  2276. return(TRUE);
  2277. slashptr = strstr(TestString, ".\\");
  2278. if(slashptr != NULL)
  2279. return(TRUE);
  2280. slashptr = strstr(TestString, "\\..");
  2281. if(slashptr != NULL)
  2282. return(TRUE);
  2283. slashptr = strstr(TestString, "\\.");
  2284. if(slashptr != NULL)
  2285. {
  2286. // Check Next Char for NULL or "\"
  2287. slashptr++;
  2288. if(*slashptr == (CHAR) NULL);
  2289. return(TRUE);
  2290. if(*slashptr == 0x5c);
  2291. return(TRUE);
  2292. }
  2293. return(FALSE);
  2294. }
  2295. BOOL RemoveEndDot(LPSTR TestString)
  2296. {
  2297. LPTSTR slashptr;
  2298. // Find End of String
  2299. slashptr = strrchr(TestString, (CHAR) NULL);
  2300. if(slashptr == NULL)
  2301. return(FALSE);
  2302. // Check previous char for "."
  2303. slashptr--;
  2304. if(*slashptr == '.')
  2305. {
  2306. *slashptr = (CHAR) NULL;
  2307. }
  2308. return(TRUE);
  2309. }
  2310. /* *********************************************************************
  2311. ********************************************************************* */
  2312. BOOL StripRootDir(IN LPTSTR InDir,
  2313. OUT LPTSTR OutRootDir)
  2314. {
  2315. LPTSTR searchchar;
  2316. strcpy(OutRootDir, InDir);
  2317. // Check for ":" file type
  2318. searchchar = strchr(OutRootDir, ':');
  2319. if(searchchar != NULL)
  2320. {
  2321. // Have a device type root dir
  2322. searchchar++;
  2323. // add a "\" after the ":"
  2324. *searchchar = 0x5c;
  2325. searchchar++;
  2326. // Terminate the string
  2327. *searchchar = (CHAR) NULL;
  2328. return(TRUE);
  2329. }
  2330. else // Have a nondevice name
  2331. {
  2332. // Check for "\\" in first 2 chars in file path for UNC path
  2333. if( strncmp(OutRootDir, "\\\\", 2) == 0)
  2334. {
  2335. // Bump pointer
  2336. OutRootDir +=3;
  2337. // Serarch for the next "\"
  2338. searchchar = strchr(OutRootDir, 0x5c);
  2339. if(searchchar == NULL)
  2340. return(FALSE);
  2341. // Have the 3rd one check for fourth on in typical UNC string
  2342. searchchar++;
  2343. searchchar = strchr(searchchar, 0x5c);
  2344. if(searchchar == NULL)
  2345. { // Have UNC Pth Only
  2346. // Need to add "\" to end of string
  2347. OutRootDir += strlen(OutRootDir);
  2348. *OutRootDir = 0x5c;
  2349. ++OutRootDir;
  2350. *OutRootDir = (CHAR) NULL;
  2351. return(TRUE);
  2352. }
  2353. else
  2354. {
  2355. // Have the fouth "\"
  2356. ++searchchar;
  2357. // Add NULL
  2358. *searchchar = (CHAR) NULL;
  2359. return(TRUE);
  2360. }
  2361. }
  2362. else // Have a "\" or whatever
  2363. {
  2364. *OutRootDir = (CHAR) NULL;
  2365. return(TRUE);
  2366. }
  2367. }
  2368. // Should not get here
  2369. return(FALSE);
  2370. }
  2371. // End of File