Skip to content

Commit

Permalink
Added /DomainPaths
Browse files Browse the repository at this point in the history
  • Loading branch information
NoMoreFood committed Aug 10, 2016
1 parent c6362c3 commit 48e6486
Show file tree
Hide file tree
Showing 10 changed files with 219 additions and 25 deletions.
10 changes: 8 additions & 2 deletions Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,11 @@ VOID BeginFileScan()

int wmain(int iArgs, WCHAR * aArgs[])
{
// print standard header
wprintf(L"===============================================================================\n");
wprintf(L"= Repacls Version %hs by Bryan Berns\n", VERSION_STRING);
wprintf(L"===============================================================================\n");

// translate
std::queue<std::wstring> oArgList;
for (int iArg = 1; iArg < iArgs; iArg++)
Expand Down Expand Up @@ -447,9 +452,10 @@ int wmain(int iArgs, WCHAR * aArgs[])
// ensure we have permissions to all files
EnablePrivs();

// not general information
// note parameter information
wprintf(L"\n");
wprintf(L"===============================================================================\n");
wprintf(L"= Repacls Version %hs by Bryan Berns\n", VERSION_STRING);
wprintf(L"= Initial Scan Details\n");
wprintf(L"===============================================================================\n");
for (std::vector<std::wstring>::iterator sScanPath = InputOutput::ScanPaths().begin();
sScanPath != InputOutput::ScanPaths().end(); sScanPath++)
Expand Down
107 changes: 107 additions & 0 deletions OperationDomainPaths.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#include <windows.h>
#include <lmshare.h>
#include <lmapibuf.h>
#include <iads.h>
#include <adshlp.h>
#include <atlBase.h>
#include <dsgetdc.h>

#pragma comment(lib,"activeds.lib")
#pragma comment(lib,"adsiid.lib")
#pragma comment(lib,"netapi32.lib")

#include "OperationDomainPaths.h"
#include "OperationSharePaths.h"
#include "InputOutput.h"

ClassFactory<OperationDomainPaths> * OperationDomainPaths::RegisteredFactory =
new ClassFactory<OperationDomainPaths>(GetCommand());

OperationDomainPaths::OperationDomainPaths(std::queue<std::wstring> & oArgList) : Operation(oArgList)
{
// exit if there are not enough arguments to part
std::vector<std::wstring> sSubArgs = ProcessAndCheckArgs(1, oArgList);

// initialize com only
static HRESULT hComInit = CoInitializeEx(NULL, 0);

// find a domain controller for the specified domain
PDOMAIN_CONTROLLER_INFO tDomainControllerInfo;
if (DsGetDcName(NULL, sSubArgs[0].c_str(), NULL, NULL,
DS_IS_FLAT_NAME | DS_RETURN_DNS_NAME | DS_TRY_NEXTCLOSEST_SITE | DS_FORCE_REDISCOVERY,
&tDomainControllerInfo) != ERROR_SUCCESS)
{
wprintf(L"ERROR: Could not locate domain controller for domain '%s'\n", sSubArgs[0].c_str());
exit(-1);
}

// create a string
std::wstring sPath = std::wstring(L"LDAP://") + (wcsrchr(tDomainControllerInfo->DomainControllerName, '\\') + 1);

// grab the dns suffix for later use
std::wstring sSuffix = tDomainControllerInfo->DomainName;
NetApiBufferFree(tDomainControllerInfo);

// bind to global catalog
CComPtr<IDirectorySearch> oSearch;
if (FAILED(ADsOpenObject(sPath.c_str(), NULL, NULL, ADS_SECURE_AUTHENTICATION,
IID_IDirectorySearch, (void**)&oSearch)))
{
wprintf(L"ERROR: Could not establish search for domain '%s'\n", sSubArgs[0].c_str());
exit(-1);
}

// setup preferences to search entire tree
ADS_SEARCHPREF_INFO SearchPref;
SearchPref.dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
SearchPref.vValue.dwType = ADSTYPE_INTEGER;
SearchPref.vValue.Integer = ADS_SCOPE_SUBTREE;

// set the search preference.
if (FAILED(oSearch->SetSearchPreference(&SearchPref, 1)))
{
wprintf(L"ERROR: Could not set search preference for domain '%s'\n", sSubArgs[0].c_str());
exit(-1);

}

// create the search filter
WCHAR sSearchFilter[] = L"(&(objectCategory=computer)(|(operatingSystem=*server*)(operatingSystem=*ontap*)(operatingSystem=*netapp*))(!(userAccountControl:1.2.840.113556.1.4.803:=8192))(!(userAccountControl:1.2.840.113556.1.4.803:=2)))";

// execute the search.
LPWSTR sAttributes[] = { L"cn" };
ADS_SEARCH_HANDLE hSearch;
if (FAILED(oSearch->ExecuteSearch(sSearchFilter, sAttributes, ARRAYSIZE(sAttributes), &hSearch)))
{
wprintf(L"ERROR: Could not execute search for domain '%s'\n", sSubArgs[0].c_str());
exit(-1);
}

// enumerate results
std::vector<std::wstring> sServers;
for (HRESULT hResult = oSearch->GetFirstRow(hSearch); hResult == S_OK; hResult = oSearch->GetNextRow(hSearch))
{
// get the data from the column
ADS_SEARCH_COLUMN oColumn;
if (FAILED(oSearch->GetColumn(hSearch, sAttributes[0], &oColumn)) ||
oColumn.dwADsType != ADSTYPE_CASE_IGNORE_STRING)
{
continue;
}

// add the server to our list
oArgList.push(L"/SharePaths");
oArgList.push(std::wstring(oColumn.pADsValues->CaseIgnoreString) + L"." + sSuffix +
((sSubArgs.size() == 2) ? (L":" + sSubArgs[1]) : L""));

// free the column.
oSearch->FreeColumn(&oColumn);
}

// close search handle
if (oSearch->CloseSearchHandle(hSearch) != NULL)
{
wprintf(L"ERROR: Could not close search for domain '%s'\n", sSubArgs[0].c_str());
exit(-1);
}
};
17 changes: 17 additions & 0 deletions OperationDomainPaths.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

#include "Operation.h"

class OperationDomainPaths : public Operation
{
private:

// statics used by command registration utility
static std::wstring GetCommand() { return L"DomainPaths"; }
static ClassFactory<OperationDomainPaths> * RegisteredFactory;

public:

// constructors
OperationDomainPaths(std::queue<std::wstring> & oArgList);
};
2 changes: 1 addition & 1 deletion OperationHelp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ or end of your command as to not confuse them with ordered parameters.
of '5' is usually adequate, but can be increased if performing changes
over a higher-latency connection. Since changes to a parent directory
often affect the inherited security on children, the security of children
objects are always processed after the the security on their parent objects
objects are always processed after the security on their parent objects
are fully processed.
/WhatIf
Expand Down
3 changes: 3 additions & 0 deletions OperationMigrateDomain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ SidActionResult OperationMigrateDomain::DetermineSid(WCHAR * const sSdPart, Obje
std::wstring sTargetAccountName = sTargetDomain + (wcsstr(sSourceAccountName.c_str(), L"\\") + 1);
PSID tTargetAccountSid = GetSidFromName(sTargetAccountName);

// do a reverse lookup to see if this might be a sid history item
if (GetNameFromSidEx(tTargetAccountSid) == sSourceAccountName) return SidActionResult::Nothing;

// stop processing if the account does not exist
if (tTargetAccountSid == nullptr) return SidActionResult::Nothing;

Expand Down
2 changes: 1 addition & 1 deletion OperationRemoveOrphan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ SidActionResult OperationRemoveOrphan::DetermineSid(WCHAR * const sSdPart, Objec

// see if the sid is unresolvable; if it is then this is not an orphan
bool bIsOrphan = false;
GetNameFromSid(tCurrentSid, NULL);
GetNameFromSid(tCurrentSid, &bIsOrphan);
if (!bIsOrphan) return SidActionResult::Nothing;

// update the sid in the ace
Expand Down
93 changes: 73 additions & 20 deletions OperationSharePaths.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#include <lmshare.h>
#include <lmapibuf.h>

#include <regex>

#pragma comment(lib, "netapi32.lib")

#include "OperationSharePaths.h"
Expand All @@ -16,65 +18,116 @@ OperationSharePaths::OperationSharePaths(std::queue<std::wstring> & oArgList) :
std::vector<std::wstring> sSubArgs = ProcessAndCheckArgs(1, oArgList);

// if extra arguments are specified, parse them
bool bStopOnErrors = false;
bool bAdminOnly = false;
bool bHiddenIncluded = false;
if (sSubArgs.size() == 2)
{
if (_wcsicmp(sSubArgs[1].c_str(), L"INCLUDEHIDDEN") == 0)
{
bHiddenIncluded = true;
}
else if (_wcsicmp(sSubArgs[1].c_str(), L"ADMINONLY") == 0)
{
bAdminOnly = true;
}
else
// further split the second arg into a command delimited list
std::wstring sArg = oArgList.front(); oArgList.pop();
std::wregex oRegex(L",");
std::wsregex_token_iterator oFirst{ sSubArgs[1].begin(), sSubArgs[1].end(), oRegex, -1 }, oLast;
std::vector<std::wstring> oShareArgs = { oFirst, oLast };

// enumerate list
for (std::vector<std::wstring>::iterator sShareArg = oShareArgs.begin();
sShareArg != oShareArgs.end(); sShareArg++)
{
wprintf(L"ERROR: Unrecognized parameter '%s' for command '%s'\n", sSubArgs[1].c_str(), sSubArgs[0].c_str());
exit(-1);
if (_wcsicmp((*sShareArg).c_str(), L"INCLUDEHIDDEN") == 0)
{
bHiddenIncluded = true;
}
else if (_wcsicmp((*sShareArg).c_str(), L"ADMINONLY") == 0)
{
bAdminOnly = true;
}
if (_wcsicmp((*sShareArg).c_str(), L"STOPONERROR") == 0)
{
bStopOnErrors = true;
}
else
{
wprintf(L"ERROR: Unrecognized parameter '%s' for command '%s'\n", sSubArgs[1].c_str(), sSubArgs[0].c_str());
exit(-1);
}
}
}

DWORD hResumeHandle = NULL;
DWORD iReturn = 0;
std::map<std::wstring, std::wstring> mPaths;
do
{
SHARE_INFO_502 * tInfo;
SHARE_INFO_2 * tInfo;
DWORD iEntries = 0;
DWORD iTotalEntries = 0;

// enumerate file share
iReturn = NetShareEnum((LPWSTR)sSubArgs[0].c_str(), 502, (LPBYTE*)&tInfo,
iReturn = NetShareEnum((LPWSTR)sSubArgs[0].c_str(), 2, (LPBYTE*)&tInfo,
MAX_PREFERRED_LENGTH, &iEntries, &iTotalEntries, &hResumeHandle);

// check for unknown error
if (iReturn != ERROR_SUCCESS && iReturn != ERROR_MORE_DATA)
{
wprintf(L"ERROR: Could not enumerate shares on '%s'\n", sSubArgs[0].c_str());
exit(-1);
if (bStopOnErrors) exit(-1); else return;
}

// process entries
for (DWORD iEntry = 0; iEntry < iEntries; iEntry++)
{
// skip non-disk shares (e.g, printers)
if ((tInfo[iEntry].shi502_type & STYPE_MASK) != STYPE_DISKTREE) continue;
if ((tInfo[iEntry].shi2_type & STYPE_MASK) != STYPE_DISKTREE) continue;

// skip administrative share unless admin command was specified
if (bAdminOnly && !CheckBitSet(tInfo[iEntry].shi502_type, STYPE_SPECIAL) ||
!bAdminOnly && CheckBitSet(tInfo[iEntry].shi502_type, STYPE_SPECIAL)) continue;
if (bAdminOnly && !CheckBitSet(tInfo[iEntry].shi2_type, STYPE_SPECIAL) ||
!bAdminOnly && CheckBitSet(tInfo[iEntry].shi2_type, STYPE_SPECIAL)) continue;

// skip hidden shares unless hidden command was specified
WCHAR * cEnd = (wcsrchr(tInfo[iEntry].shi502_netname, '$'));
WCHAR * cEnd = (wcsrchr(tInfo[iEntry].shi2_netname, '$'));
if (!bAdminOnly && !bHiddenIncluded && (cEnd != NULL && *(cEnd + 1) == '\0')) continue;

// add a trailing path if the path does not have one
std::wstring sLocalPath = tInfo[iEntry].shi2_path;
if (sLocalPath.back() != L'\\') sLocalPath += L'\\';

// convert to uppercase
std::transform(sLocalPath.begin(), sLocalPath.end(), sLocalPath.begin(), ::toupper);

// add path to the share list
InputOutput::ScanPaths().push_back(
L"\\\\" + sSubArgs[0] + L"\\" + tInfo[iEntry].shi502_netname);
mPaths[tInfo[iEntry].shi2_netname] = sLocalPath;
}

// cleanup
NetApiBufferFree(tInfo);
}
while (iReturn == ERROR_MORE_DATA);

// enumerate the shares and make sure there are no duplicates
// or child that are contained within parent paths
for (std::map<std::wstring, std::wstring>::const_iterator oPathOuter = mPaths.begin();
oPathOuter != mPaths.end(); oPathOuter++)
{
bool bAddToPathList = true;
for (std::map<std::wstring, std::wstring>::const_iterator oPathInner = oPathOuter;
oPathInner != mPaths.end(); oPathInner++)
{
// see if the path is a sub-path of another path
if (oPathInner->first != oPathOuter->first &&
oPathOuter->second.find(oPathInner->second) != std::wstring::npos)
{
wprintf(L"NOTE: Share '%s' is included in '%s' on '%s'; skipping\n",
oPathOuter->first.c_str(), oPathInner->first.c_str(), sSubArgs[0].c_str());
bAddToPathList = false;
break;
}
}

// add it the resultant array if not found in another path
if (bAddToPathList)
{
InputOutput::ScanPaths().push_back(
L"\\\\" + sSubArgs[0] + L"\\" + oPathOuter->first);
}
}
};
2 changes: 1 addition & 1 deletion OperationThreads.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ OperationThreads::OperationThreads(std::queue<std::wstring> & oArgList) : Operat

// store off the argument
InputOutput::MaxThreads() = (short)_wtoi(sSubArgs[0].c_str());
if (InputOutput::MaxThreads() == 0 || InputOutput::MaxThreads() > 32)
if (InputOutput::MaxThreads() == 0 || InputOutput::MaxThreads() > 50)
{
// complain
wprintf(L"ERROR: Invalid number of threads specified for parameter '%s'.\n", GetCommand().c_str());
Expand Down
2 changes: 2 additions & 0 deletions repacls.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@
<ClCompile Include="OperationAddAccountIfMissing.cpp" />
<ClCompile Include="OperationCheckCanonical.cpp" />
<ClCompile Include="OperationCompact.cpp" />
<ClCompile Include="OperationDomainPaths.cpp" />
<ClCompile Include="OperationExportDescriptor.cpp" />
<ClCompile Include="OperationFindAccount.cpp" />
<ClCompile Include="OperationFindDomain.cpp" />
Expand Down Expand Up @@ -208,6 +209,7 @@
<ClInclude Include="DriverKitPartial.h" />
<ClInclude Include="Functions.h" />
<ClInclude Include="InputOutput.h" />
<ClInclude Include="OperationDomainPaths.h" />
<ClInclude Include="OperationSharePaths.h" />
<ClInclude Include="OperationAddAccountIfMissing.h" />
<ClInclude Include="OperationCheckCanonical.h" />
Expand Down
6 changes: 6 additions & 0 deletions repacls.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@
<ClCompile Include="OperationSharePaths.cpp">
<Filter>Source\Operations</Filter>
</ClCompile>
<ClCompile Include="OperationDomainPaths.cpp">
<Filter>Source\Operations</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ConcurrentQueue.h">
Expand Down Expand Up @@ -186,6 +189,9 @@
<ClInclude Include="OperationSharePaths.h">
<Filter>Includes\Operations</Filter>
</ClInclude>
<ClInclude Include="OperationDomainPaths.h">
<Filter>Includes\Operations</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Includes">
Expand Down

0 comments on commit 48e6486

Please sign in to comment.