Skip to content

Commit d02a948

Browse files
committed
Added /SharePaths
1 parent 3310f63 commit d02a948

10 files changed

+154
-44
lines changed

InputOutput.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ class InputOutput
4545
return iMaxThreads;
4646
}
4747

48-
static std::wstring & BasePath()
48+
static std::vector<std::wstring> & ScanPaths()
4949
{
50-
static std::wstring sBasePath = L"";
51-
return sBasePath;
50+
static std::vector<std::wstring> vScanPaths;
51+
return vScanPaths;
5252
}
5353

5454
static void AddFile(const std::wstring & sLine)

Main.cpp

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -331,35 +331,36 @@ void AnalzyingQueue()
331331
}
332332
}
333333

334-
VOID BeginFileScan(std::wstring sScanPath)
334+
VOID BeginFileScan()
335335
{
336336
// startup some threads for processing
337337
std::vector<std::thread *> oThreads;
338338
for (USHORT iNum = 0; iNum < InputOutput::MaxThreads(); iNum++)
339339
oThreads.push_back(new std::thread(AnalzyingQueue));
340340

341-
// queue that is used to store the directory listing
342-
std::queue<ObjectEntry> oQueue;
343-
344-
// to get the process started, we need to have one entry so
345-
// we will set that to the passed argument
346-
ObjectEntry oEntryFirst;
347-
oEntryFirst.IsRoot = true;
341+
for (std::vector<std::wstring>::iterator sScanPath = InputOutput::ScanPaths().begin();
342+
sScanPath != InputOutput::ScanPaths().end(); sScanPath++)
343+
{
344+
// to get the process started, we need to have one entry so
345+
// we will set that to the passed argument
346+
ObjectEntry oEntryFirst;
347+
oEntryFirst.IsRoot = true;
348348

349-
// convert the path to a long path that is compatible with the other call
350-
UNICODE_STRING tPathU;
351-
RtlDosPathNameToNtPathName_U(sScanPath.c_str(), &tPathU, NULL, NULL);
349+
// convert the path to a long path that is compatible with the other call
350+
UNICODE_STRING tPathU;
351+
RtlDosPathNameToNtPathName_U((*sScanPath).c_str(), &tPathU, NULL, NULL);
352352

353-
// copy it to a null terminated string
354-
oEntryFirst.Name = std::wstring(tPathU.Buffer, tPathU.Length / sizeof(WCHAR));
355-
oEntryFirst.Attributes = GetFileAttributes(sScanPath.c_str());
353+
// copy it to a null terminated string
354+
oEntryFirst.Name = std::wstring(tPathU.Buffer, tPathU.Length / sizeof(WCHAR));
355+
oEntryFirst.Attributes = GetFileAttributes((*sScanPath).c_str());
356356

357-
// free the buffer returned previously
358-
RtlFreeUnicodeString(&tPathU);
357+
// free the buffer returned previously
358+
RtlFreeUnicodeString(&tPathU);
359359

360-
// add this entry to being processing
361-
iFilesToProcess++;
362-
oScanQueue.push(oEntryFirst);
360+
// add this entry to being processing
361+
iFilesToProcess++;
362+
oScanQueue.push(oEntryFirst);
363+
}
363364

364365
// wait until all threads complete
365366
while (iFilesToProcess > 0)
@@ -437,7 +438,7 @@ int wmain(int iArgs, WCHAR * aArgs[])
437438
}
438439

439440
// verify a path was specified
440-
if (InputOutput::BasePath().size() == 0)
441+
if (InputOutput::ScanPaths().size() == 0)
441442
{
442443
wprintf(L"%s\n", L"ERROR: No path was specified.");
443444
exit(-1);
@@ -450,14 +451,16 @@ int wmain(int iArgs, WCHAR * aArgs[])
450451
wprintf(L"===============================================================================\n");
451452
wprintf(L"= Repacls Version %hs by Bryan Berns\n", VERSION_STRING);
452453
wprintf(L"===============================================================================\n");
453-
wprintf(L"= Scan Path: %s\n", InputOutput::BasePath().c_str());
454+
for (std::vector<std::wstring>::iterator sScanPath = InputOutput::ScanPaths().begin();
455+
sScanPath != InputOutput::ScanPaths().end(); sScanPath++)
456+
wprintf(L"= Scan Path(s): %s\n", (*sScanPath).c_str());
454457
wprintf(L"= Maximum Threads: %d\n", (int)InputOutput::MaxThreads());
455458
wprintf(L"= What If Mode: %s\n", InputOutput::InWhatIfMode() ? L"Yes" : L"No");
456459
wprintf(L"===============================================================================\n");
457460

458461
// do the scan
459462
ULONGLONG iTimeStart = GetTickCount64();
460-
BeginFileScan(InputOutput::BasePath());
463+
BeginFileScan();
461464
ULONGLONG iTimeStop = GetTickCount64();
462465

463466
// print out statistics

Operation.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ typedef ACCESS_ACE *PACCESS_ACE;
2929
#define SidNotMatch(x,y) (!SidMatch(x,y))
3030

3131
// macros for checking file attributes
32-
#define CheckBitSet(x,y) ((x & y) != 0)
32+
#define CheckBitSet(x,y) (((x) & (y)) != 0)
3333
#define IsDirectory(x) CheckBitSet(x,FILE_ATTRIBUTE_DIRECTORY)
3434
#define IsHiddenSystem(x) (CheckBitSet(x,FILE_ATTRIBUTE_HIDDEN) && CheckBitSet(x,FILE_ATTRIBUTE_SYSTEM))
3535
#define IsReparsePoint(x) (CheckBitSet(x,FILE_ATTRIBUTE_REPARSE_POINT))

OperationHelp.cpp

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,25 @@ Global Options affect the entire command regardless of where they appear in the
3838
passed command line. It is recommended to include them at the very beginning
3939
or end of your command as to not confuse them with ordered parameters.
4040
41-
/Path
41+
/Path <Path>
4242
Specifies the file or directory to process. If a directory, the directory
4343
is processed recursively; all operations specified affect the directory
4444
and all files and folders under the directory (unless otherwise specified).
45-
This parameter is mandatory.
45+
This parameter is mandatory. This command can be specified multiple times.
46+
47+
/SharePaths <ComputerName>[:AdminOnly|IncludeHidden]
48+
Specifies a server that has one or more shares to process. This command is
49+
equivalent to specifying /Path for every share on a particular file server.
50+
By default, only non-administrative and non-hidden shares are scanned.
51+
To only scan administrative shares (e.g. C$), append :AdminOnly to the
52+
computer name. To include hidden, non-administrative shares, append
53+
:IncludeHidden to the computer name.
4654
4755
/Quiet
4856
Hides all non-error output. This option will greatly enhance performance if
4957
a large number of changes are being processed. Alternatively, it is
5058
advisable to redirect console output to a file (using the > redirector) if
51-
/Quiet cannot be specified.
59+
/Quiet cannot be specified.
5260
5361
/Threads <NumberOfThreads>
5462
Specifies the number of threads to use while processing. The default value
@@ -167,22 +175,22 @@ Commands That Can Alter Security (When /WhatIf Is Not Present)
167175
An optional qualifier after regular expression can be specified after the
168176
regular expression to refine what part of the security descriptor to scan.
169177
See Other Notes & Limitations section for more information.
178+
)";
170179

180+
std::wcout <<
181+
LR"(
171182
/SetOwner <Name|Sid>
172183
Will set the owner of the file to the name specified.
173184
174185
/UpdateHistoricalSids
175186
Will convert any instances of old SIDs present in the security descriptor
176187
to there to active SID currently associated with the account. This is
177188
especially useful after a domain migration and prior to removing
178-
excess SID history on accounts.
179-
)";
189+
excess SID history on accounts.
180190
181-
std::wcout <<
182-
LR"(
183191
Exclusive Options
184192
=================
185-
/Help or /? or /H
193+
/Help or /? or /H
186194
Shows this information.
187195
188196
/ResetChildren

OperationPath.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,6 @@ OperationPath::OperationPath(std::queue<std::wstring> & oArgList) : Operation(oA
1010
// exit if there are not enough arguments to part
1111
std::vector<std::wstring> sSubArgs = ProcessAndCheckArgs(1, oArgList, L"\\0");
1212

13-
// verify this parameter has only be specified once
14-
if (InputOutput::BasePath().size() > 0)
15-
{
16-
wprintf(L"%s\n", L"ERROR: Path can only be specified once.");
17-
exit(-1);
18-
}
19-
2013
// store off the argument
21-
InputOutput::BasePath() = sSubArgs[0];
14+
InputOutput::ScanPaths().push_back(sSubArgs[0]);
2215
};

OperationSharePaths.cpp

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#include <windows.h>
2+
#include <lmshare.h>
3+
#include <lmapibuf.h>
4+
5+
#pragma comment(lib, "netapi32.lib")
6+
7+
#include "OperationSharePaths.h"
8+
#include "InputOutput.h"
9+
10+
ClassFactory<OperationSharePaths> * OperationSharePaths::RegisteredFactory =
11+
new ClassFactory<OperationSharePaths>(GetCommand());
12+
13+
OperationSharePaths::OperationSharePaths(std::queue<std::wstring> & oArgList) : Operation(oArgList)
14+
{
15+
// exit if there are not enough arguments to part
16+
std::vector<std::wstring> sSubArgs = ProcessAndCheckArgs(1, oArgList);
17+
18+
// if extra arguments are specified, parse them
19+
bool bAdminOnly = false;
20+
bool bHiddenIncluded = false;
21+
if (sSubArgs.size() == 2)
22+
{
23+
if (_wcsicmp(sSubArgs[1].c_str(), L"INCLUDEHIDDEN") == 0)
24+
{
25+
bHiddenIncluded = true;
26+
}
27+
else if (_wcsicmp(sSubArgs[1].c_str(), L"ADMINONLY") == 0)
28+
{
29+
bAdminOnly = true;
30+
}
31+
else
32+
{
33+
wprintf(L"ERROR: Unrecognized parameter '%s' for command '%s'\n", sSubArgs[1].c_str(), sSubArgs[0].c_str());
34+
exit(-1);
35+
}
36+
}
37+
38+
DWORD hResumeHandle = NULL;
39+
DWORD iReturn = 0;
40+
do
41+
{
42+
SHARE_INFO_502 * tInfo;
43+
DWORD iEntries = 0;
44+
DWORD iTotalEntries = 0;
45+
46+
// enumerate file share
47+
iReturn = NetShareEnum((LPWSTR)sSubArgs[0].c_str(), 502, (LPBYTE*)&tInfo,
48+
MAX_PREFERRED_LENGTH, &iEntries, &iTotalEntries, &hResumeHandle);
49+
50+
// check for unknown error
51+
if (iReturn != ERROR_SUCCESS && iReturn != ERROR_MORE_DATA)
52+
{
53+
wprintf(L"ERROR: Could not enumerate shares on '%s'\n", sSubArgs[0].c_str());
54+
exit(-1);
55+
}
56+
57+
// process entries
58+
for (DWORD iEntry = 0; iEntry < iEntries; iEntry++)
59+
{
60+
// skip non-disk shares (e.g, printers)
61+
if ((tInfo[iEntry].shi502_type & STYPE_MASK) != STYPE_DISKTREE) continue;
62+
63+
// skip administrative share unless admin command was specified
64+
if (bAdminOnly && !CheckBitSet(tInfo[iEntry].shi502_type, STYPE_SPECIAL) ||
65+
!bAdminOnly && CheckBitSet(tInfo[iEntry].shi502_type, STYPE_SPECIAL)) continue;
66+
67+
// skip hidden shares unless hidden command was specified
68+
WCHAR * cEnd = (wcsrchr(tInfo[iEntry].shi502_netname, '$'));
69+
if (!bAdminOnly && !bHiddenIncluded && (cEnd != NULL && *(cEnd + 1) == '\0')) continue;
70+
71+
// add path to the share list
72+
InputOutput::ScanPaths().push_back(
73+
L"\\\\" + sSubArgs[0] + L"\\" + tInfo[iEntry].shi502_netname);
74+
}
75+
76+
// cleanup
77+
NetApiBufferFree(tInfo);
78+
}
79+
while (iReturn == ERROR_MORE_DATA);
80+
};

OperationSharePaths.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#pragma once
2+
3+
#include "Operation.h"
4+
5+
class OperationSharePaths : public Operation
6+
{
7+
private:
8+
9+
// statics used by command registration utility
10+
static std::wstring GetCommand() { return L"SharePaths"; }
11+
static ClassFactory<OperationSharePaths> * RegisteredFactory;
12+
13+
public:
14+
15+
// constructors
16+
OperationSharePaths(std::queue<std::wstring> & oArgList);
17+
};

Version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
#pragma once
22

3-
#define VERSION_STRING "1.5.0.0"
3+
#define VERSION_STRING "1.6.0.0"

repacls.vcxproj

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@
128128
</ItemDefinitionGroup>
129129
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
130130
<ClCompile>
131-
<WarningLevel>Level3</WarningLevel>
131+
<WarningLevel>Level4</WarningLevel>
132132
<PrecompiledHeader>
133133
</PrecompiledHeader>
134134
<Optimization>MaxSpeed</Optimization>
@@ -138,6 +138,7 @@
138138
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
139139
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
140140
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
141+
<DisableSpecificWarnings>4100</DisableSpecificWarnings>
141142
</ClCompile>
142143
<Link>
143144
<SubSystem>Console</SubSystem>
@@ -197,6 +198,7 @@
197198
<ClCompile Include="OperationReport.cpp" />
198199
<ClCompile Include="OperationResetChildren.cpp" />
199200
<ClCompile Include="OperationSetOwner.cpp" />
201+
<ClCompile Include="OperationSharePaths.cpp" />
200202
<ClCompile Include="OperationSidHistory.cpp" />
201203
<ClCompile Include="OperationThreads.cpp" />
202204
<ClCompile Include="OperationWhatIf.cpp" />
@@ -206,6 +208,7 @@
206208
<ClInclude Include="DriverKitPartial.h" />
207209
<ClInclude Include="Functions.h" />
208210
<ClInclude Include="InputOutput.h" />
211+
<ClInclude Include="OperationSharePaths.h" />
209212
<ClInclude Include="OperationAddAccountIfMissing.h" />
210213
<ClInclude Include="OperationCheckCanonical.h" />
211214
<ClInclude Include="OperationCompact.h" />

repacls.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@
8282
<ClCompile Include="OperationReport.cpp">
8383
<Filter>Source\Operations</Filter>
8484
</ClCompile>
85+
<ClCompile Include="OperationSharePaths.cpp">
86+
<Filter>Source\Operations</Filter>
87+
</ClCompile>
8588
</ItemGroup>
8689
<ItemGroup>
8790
<ClInclude Include="ConcurrentQueue.h">
@@ -180,6 +183,9 @@
180183
<ClInclude Include="Version.h">
181184
<Filter>Includes</Filter>
182185
</ClInclude>
186+
<ClInclude Include="OperationSharePaths.h">
187+
<Filter>Includes\Operations</Filter>
188+
</ClInclude>
183189
</ItemGroup>
184190
<ItemGroup>
185191
<Filter Include="Includes">

0 commit comments

Comments
 (0)