From d8cdc9ec2a57cda2ad9eba6c047bce4e054b2d21 Mon Sep 17 00:00:00 2001 From: David Geeraerts Date: Thu, 17 Dec 2020 15:08:11 -0800 Subject: [PATCH] Version 0.0.0 (2020-12-17) - see change log for details --- .gitignore | 4 +- ADDS_Tool.cmd | 438 +++++++++++++++++++++++++++------- ADDS_Tool_ToDo.md | 1 + ChangeLog.md | 21 +- DSQUERY_Attributes.txt | 20 ++ Notes.md | 3 +- README.md | 46 +++- images/ADDS_T_Main_Banner.png | Bin 0 -> 13632 bytes 8 files changed, 444 insertions(+), 89 deletions(-) create mode 100644 DSQUERY_Attributes.txt create mode 100644 images/ADDS_T_Main_Banner.png diff --git a/.gitignore b/.gitignore index cc7f2e3..5854616 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,6 @@ /Errors #Files -ADDS_USER_QUERY.cmd \ No newline at end of file +ADDS_USER_QUERY.cmd +DSQUERY_Attributes_Sorted.txt +*.backup diff --git a/ADDS_Tool.cmd b/ADDS_Tool.cmd index c722a21..0b4eb71 100644 --- a/ADDS_Tool.cmd +++ b/ADDS_Tool.cmd @@ -31,7 +31,7 @@ SET $PROGRAM_NAME=Active_Directory_Domain_Services_Tool SET $Version=0.0.0 -SET $BUILD=2020-12-15 09:30 +SET $BUILD=2020-12-17 15:30 Title %$PROGRAM_NAME% Version: %$Version% Prompt ADT$G color 8F @@ -114,7 +114,30 @@ SET "$AD_SERVER_SEARCH=-s %$DC%" :: Dependency Checks :: assumes ready to go SET $PREREQUISITE_STATUS=1 +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + +:PID + :: Program information including PID + tasklist /FI "WINDOWTITLE eq %$PROGRAM_NAME%*" > "%$LogPath%\var\var_TaskInfo_PID.txt" + for /F "skip=3 tokens=2 delims= " %%P IN ('tasklist /FI "WINDOWTITLE eq %$PROGRAM_NAME%*"') DO echo %%P> "%$LogPath%\var\var_$PID.txt" + SET /P $PID= < "%$LogPath%\var\var_$PID.txt" +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + + +:fISO8601 + :: Function to ensure ISO 8601 Date format yyyy-mmm-dd + :: Easiest way to get ISO date + @powershell Get-Date -format "yyyy-MM-dd" > "%$LogPath%\var\var_ISO8601_Date.txt" + SET /P $ISO_DATE= < "%$LogPath%\var\var_ISO8601_Date.txt" +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + +:UTC + :: Universal Time Coordinate + FOR /F "tokens=1 delims=()" %%P IN ('wmic timezone get Description ^| findstr /C:"UTC" /I') DO ECHO %%P > "%$LogPath%\var\var_$UTC.txt" + SET /P $UTC= < "%$LogPath%\var\var_$UTC.txt" + FOR /F "tokens=2 delims==" %%P IN ('wmic timezone get StandardName /value ^| findstr /C:"=" /I') DO ECHO %%P > "%$LogPath%\var\var_$UTC_STANDARD_NAME.txt" + SET /P $UTC_STANDARD_NAME= < "%$LogPath%\var\var_$UTC_STANDARD_NAME.txt" :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :CD @@ -128,11 +151,13 @@ SET $PREREQUISITE_STATUS=1 :wLog :: Start session and write to log Echo Start Session %DATE% %TIME% > "%$LogPath%\%$SESSION_LOG%" + echo UTC: %$UTC% %$UTC_STANDARD_NAME% >> "%$LogPath%\%$SESSION_LOG%" Echo Program Name: %$PROGRAM_NAME% >> "%$LogPath%\%$SESSION_LOG%" Echo Program Version: %$Version% >> "%$LogPath%\%$SESSION_LOG%" Echo Program Build: %$BUILD% >> "%$LogPath%\%$SESSION_LOG%" Echo PC: %COMPUTERNAME% >> "%$LogPath%\%$SESSION_LOG%" Echo Session User: %USERNAME% >> "%$LogPath%\%$SESSION_LOG%" + echo PID: %$PID% >> "%$LogPath%\%$SESSION_LOG%" :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :DUC @@ -384,20 +409,28 @@ GoTo end :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :subSK -:: Sub-routin for Search Key - - +:: Sub-routin for Search Key +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:subSET + :: Start Elapse Time + SET $START_TIME=%TIME% + GoTo:EOF +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:subTLT + :: Total Lapse Time + @PowerShell.exe -c "$span=([datetime]'%Time%' - [datetime]'%$START_TIME%'); '{0:00}:{1:00}:{2:00}' -f $span.Hours, $span.Minutes, $span.Seconds" > "%$LogPath%\var\var_Total_Lapsed_Time.txt" + SET /P $TOTAL_LAPSE_TIME= < "%$LogPath%\var\var_Total_Lapsed_Time.txt" + GoTo:EOF +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :sUniversal :: Search Universal SET $LAST_SEARCH_TYPE=Universal call :SM - SET $LAST_SEARCH_ATTRIBUTE=name SET $SEARCH_KEY= :: Close previous Windows taskkill /F /FI "WINDOWTITLE eq %$LAST_SEARCH_LOG% - Notepad" 2>nul 1>nul @@ -405,25 +438,25 @@ GoTo end echo Choose attribute to search against: echo ^(default is name^; leave blank for default^) SET /P $LAST_SEARCH_ATTRIBUTE=Attribute: - echo. - echo ^(Don't use "*", wildcard will be used automatically.^) + IF NOT DEFINED $LAST_SEARCH_ATTRIBUTE SET $LAST_SEARCH_ATTRIBUTE=name + call :SM + echo use "*" wildcard, e.g. Key*, *key* echo If left blank, will abort. - IF NOT DEFINED $SEARCH_KEY (SET $SEARCH_KEY_LAST=NA) ELSE (SET $SEARCH_KEY_LAST=%$SEARCH_KEY%) SET $SEARCH_KEY= - SET /P $SEARCH_KEY=Choose a search key ^(word^): - IF NOT DEFINED $SEARCH_KEY (SET $SEARCH_KEY=%$SEARCH_KEY_LAST%) - IF /I "%$SEARCH_KEY%"=="NA" GoTo jumpSUC - echo Selected {%$SEARCH_KEY%} as search key. - echo %$SEARCH_KEY% | FIND /I "*" - IF %ERRORLEVEL% EQU 0 GoTo SUC + SET /P $SEARCH_KEY=Choose a search key: + IF NOT DEFINED $SEARCH_KEY GoTo Search SET $LAST_SEARCH_KEY=%$SEARCH_KEY% + call :SM + echo Selected {%$SEARCH_KEY%} as search key. echo Searching... REM If Forestroot, then searches GC Global Catalog. set "$AD_SERVER_SEARCH=-s %$DC%.%$DOMAIN%" if %$AD_BASE%==forestroot SET "$AD_SERVER_SEARCH=-gc" - + :: Start Elapse Time + call :subSET IF EXIST "%$LogPath%\%$LAST_SEARCH_LOG%" DEL /Q "%$LogPath%\%$LAST_SEARCH_LOG%" Echo Start search: %DATE% %Time% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo UTC: %$UTC% %$UTC_STANDARD_NAME% >> "%$LogPath%\%$LAST_SEARCH_LOG%" Echo Search Type: %$LAST_SEARCH_TYPE% >> "%$LogPath%\%$LAST_SEARCH_LOG%" echo Search Attribute: %$LAST_SEARCH_ATTRIBUTE% >> "%$LogPath%\%$LAST_SEARCH_LOG%" Echo Search Term: %$SEARCH_KEY% >> "%$LogPath%\%$LAST_SEARCH_LOG%" @@ -434,12 +467,12 @@ GoTo end echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" :: No point in sorting since it won't match the details from attr * if "%$SESSION_USER%"=="%$DOMAIN_USER%" ( - DSQUERY * %$AD_BASE% -scope %$AD_SCOPE% -limit %$sLimit% -filter "(&(objectClass=*)(%$LAST_SEARCH_ATTRIBUTE%=*%$SEARCH_KEY%*))" %$AD_SERVER_SEARCH% -attr name distinguishedName > "%$LogPath%\var\var_Last_Search_N_DN.txt") ELSE ( - DSQUERY * %$AD_BASE% -scope %$AD_SCOPE% -limit %$sLimit% -filter "(&(objectClass=*)(%$LAST_SEARCH_ATTRIBUTE%=*%$SEARCH_KEY%*))" -attr name distinguishedName %$AD_SERVER_SEARCH% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% > "%$LogPath%\var\var_Last_Search_N_DN.txt" + DSQUERY * %$AD_BASE% -scope %$AD_SCOPE% -limit %$sLimit% -filter "(&(objectClass=*)(%$LAST_SEARCH_ATTRIBUTE%=%$SEARCH_KEY%))" %$AD_SERVER_SEARCH% -attr name distinguishedName > "%$LogPath%\var\var_Last_Search_N_DN.txt") ELSE ( + DSQUERY * %$AD_BASE% -scope %$AD_SCOPE% -limit %$sLimit% -filter "(&(objectClass=*)(%$LAST_SEARCH_ATTRIBUTE%=%$SEARCH_KEY%))" -attr name distinguishedName %$AD_SERVER_SEARCH% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% > "%$LogPath%\var\var_Last_Search_N_DN.txt" ) if "%$SESSION_USER%"=="%$DOMAIN_USER%" ( - DSQUERY * %$AD_BASE% -scope %$AD_SCOPE% -limit %$sLimit% -filter "(&(objectClass=*)(%$LAST_SEARCH_ATTRIBUTE%=*%$SEARCH_KEY%*))" %$AD_SERVER_SEARCH% -attr distinguishedName > "%$LogPath%\var\var_Last_Search_DN.txt") ELSE ( - DSQUERY * %$AD_BASE% -scope %$AD_SCOPE% -limit %$sLimit% -filter "(&(objectClass=*)(%$LAST_SEARCH_ATTRIBUTE%=*%$SEARCH_KEY%*))" -attr distinguishedName %$AD_SERVER_SEARCH% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% > "%$LogPath%\var\var_Last_Search_DN.txt" + DSQUERY * %$AD_BASE% -scope %$AD_SCOPE% -limit %$sLimit% -filter "(&(objectClass=*)(%$LAST_SEARCH_ATTRIBUTE%=%$SEARCH_KEY%))" %$AD_SERVER_SEARCH% -attr distinguishedName > "%$LogPath%\var\var_Last_Search_DN.txt") ELSE ( + DSQUERY * %$AD_BASE% -scope %$AD_SCOPE% -limit %$sLimit% -filter "(&(objectClass=*)(%$LAST_SEARCH_ATTRIBUTE%=%$SEARCH_KEY%))" -attr distinguishedName %$AD_SERVER_SEARCH% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% > "%$LogPath%\var\var_Last_Search_DN.txt" ) FOR /F "tokens=3 delims=:" %%K IN ('FIND /I /C "=" "%$LogPath%\var\var_Last_Search_N_DN.txt"') DO echo %%K > "%$LogPath%\var\var_Last_Search_Count.txt" :: remove leading space @@ -450,6 +483,7 @@ GoTo end echo Number of search results: %$LAST_SEARCH_COUNT% IF %$LAST_SEARCH_COUNT% EQU 0 (Echo Nothing found! Try again with broader wildcard.) IF %$LAST_SEARCH_COUNT% EQU 0 GoTo jumpSUC + echo Processing... type "%$LogPath%\var\var_Last_Search_N_DN.txt" >> "%$LogPath%\%$LAST_SEARCH_LOG%" echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" echo ---------------------------------------------------------------------- >> "%$LogPath%\%$LAST_SEARCH_LOG%" @@ -484,8 +518,12 @@ GoTo SkipSUL echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%") ) :SkipSUL - - + call :subTLT + echo Total Search Time: %$TOTAL_LAPSE_TIME% + echo Total Search Time: %$TOTAL_LAPSE_TIME% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo End search: %DATE% %Time% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" type "%$LogPath%\%$LAST_SEARCH_LOG%" >> "%$LogPath%\%$SEARCH_SESSION_LOG%" :: Search counter increment Call :fSC @@ -543,11 +581,15 @@ GoTo SkipSUL SET /P $SEARCH_KEY=Choose a search key ^(word^): IF NOT DEFINED $SEARCH_KEY (SET $SEARCH_KEY=%$SEARCH_KEY_LAST%) IF /I "%$SEARCH_KEY%"=="NA" GoTo skipSGO + call :SM echo Selected {%$SEARCH_KEY%} as search key. SET $LAST_SEARCH_KEY=%$SEARCH_KEY% - echo Searching... + echo Searching... + :: Start Elapse Time + call :subSET IF EXIST "%$LogPath%\%$LAST_SEARCH_LOG%" DEL /Q "%$LogPath%\%$LAST_SEARCH_LOG%" echo Start search %DATE% %Time% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo UTC: %$UTC% %$UTC_STANDARD_NAME% >> "%$LogPath%\%$LAST_SEARCH_LOG%" echo Search Type: %$LAST_SEARCH_TYPE% >> "%$LogPath%\%$LAST_SEARCH_LOG%" echo Search Attribute: %$LAST_SEARCH_ATTRIBUTE% >> "%$LogPath%\%$LAST_SEARCH_LOG%" echo Search Term: %$SEARCH_KEY% >> "%$LogPath%\%$LAST_SEARCH_LOG%" @@ -629,7 +671,12 @@ GoTo jumpSGL echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%") ) :jumpSGL - + call :subTLT + echo Total Search Time: %$TOTAL_LAPSE_TIME% + echo Total Search Time: %$TOTAL_LAPSE_TIME% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo End search: %DATE% %Time% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" IF %$LAST_SEARCH_COUNT% EQU 0 (Echo Nothing found! Try again with broader wildcard.) & (echo.) & (timeout /t 10) IF %$LAST_SEARCH_COUNT% EQU 0 GoTo skipSGO :: Search counter increment @@ -656,11 +703,14 @@ GoTo jumpSGL SET /P $SEARCH_KEY=Choose a search key ^(word^): IF NOT DEFINED $SEARCH_KEY (SET $SEARCH_KEY=%$SEARCH_KEY_LAST%) IF /I "%$SEARCH_KEY%"=="NA" GoTo skipSGDA + call :SM echo Selected {%$SEARCH_KEY%} as search key. SET $LAST_SEARCH_KEY=%$SEARCH_KEY% - echo Searching... + echo Searching... + call :subSET IF EXIST "%$LogPath%\%$LAST_SEARCH_LOG%" DEL /Q "%$LogPath%\%$LAST_SEARCH_LOG%" echo Start search %DATE% %Time% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo UTC: %$UTC% %$UTC_STANDARD_NAME% >> "%$LogPath%\%$LAST_SEARCH_LOG%" echo Search Type: %$LAST_SEARCH_TYPE% >> "%$LogPath%\%$LAST_SEARCH_LOG%" echo Search Attribute: %$LAST_SEARCH_ATTRIBUTE% >> "%$LogPath%\%$LAST_SEARCH_LOG%" echo Search Term: %$SEARCH_KEY% >> "%$LogPath%\%$LAST_SEARCH_LOG%" @@ -717,14 +767,14 @@ GoTo jumpSGL if NOT "%$SESSION_USER%"=="%$DOMAIN_USER%" GoTo jumpSGDO :: Session user is a domain user FOR /F "USEBACKQ tokens=* delims=" %%N IN ("%$LogPath%\var\var_Last_Search_DN.txt") DO ( - DSQUERY * %$AD_BASE% -scope %$AD_SCOPE% -limit %$sLimit% -filter "(distinguishedName=%%N)" -attr name %$AD_SERVER_SEARCH% >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( - DSQUERY * %$AD_BASE% -scope %$AD_SCOPE% -limit %$sLimit% -filter "(distinguishedName=%%N)" -attr description %$AD_SERVER_SEARCH% >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( - DSQUERY * %$AD_BASE% -scope %$AD_SCOPE% -limit %$sLimit% -filter "(distinguishedName=%%N)" -attr displayName %$AD_SERVER_SEARCH% >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( - DSGET GROUP "%%N" -dn %$AD_SERVER_SEARCH% 2> nul >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + DSQUERY * %$AD_BASE% -scope %$AD_SCOPE% -limit %$sLimit% -filter "(distinguishedName=%%~N)" -attr name %$AD_SERVER_SEARCH% >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + DSQUERY * %$AD_BASE% -scope %$AD_SCOPE% -limit %$sLimit% -filter "(distinguishedName=%%~N)" -attr description %$AD_SERVER_SEARCH% >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + DSQUERY * %$AD_BASE% -scope %$AD_SCOPE% -limit %$sLimit% -filter "(distinguishedName=%%~N)" -attr displayName %$AD_SERVER_SEARCH% >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + DSGET GROUP %%N -dn %$AD_SERVER_SEARCH% 2> nul >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( echo Members: >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( - DSGET GROUP "%%N" -members %$AD_SERVER_SEARCH% 2> nul | DSGET USER -upn -fn -mi -ln -display -email 2> nul >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + DSGET GROUP %%N -members %$AD_SERVER_SEARCH% 2> nul | DSGET USER -upn -fn -mi -ln -display -email 2> nul >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( echo Details: >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( - DSQUERY * -filter "(distinguishedName=%%N)" -attr * %$AD_SERVER_SEARCH% >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + DSQUERY * -filter "(distinguishedName=%%~N)" -attr * %$AD_SERVER_SEARCH% >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( echo ---------------------------------------------------------------------- >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%") ) @@ -732,19 +782,24 @@ GoTo jumpSGDL :jumpSGDO :: Session user is a local user FOR /F "USEBACKQ tokens=* delims=" %%N IN ("%$LogPath%\var\var_Last_Search_DN.txt") DO ( - DSQUERY * %$AD_BASE% -scope %$AD_SCOPE% -limit %$sLimit% -filter "(distinguishedName=%%N)" -attr name %$AD_SERVER_SEARCH% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( - DSQUERY * %$AD_BASE% -scope %$AD_SCOPE% -limit %$sLimit% -filter "(distinguishedName=%%N)" -attr description %$AD_SERVER_SEARCH% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( - DSQUERY * %$AD_BASE% -scope %$AD_SCOPE% -limit %$sLimit% -filter "(distinguishedName=%%N)" -attr displayName %$AD_SERVER_SEARCH% >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( - DSGET GROUP "%%N" -dn %$AD_SERVER_SEARCH% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% 2> nul >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + DSQUERY * %$AD_BASE% -scope %$AD_SCOPE% -limit %$sLimit% -filter "(distinguishedName=%%~N)" -attr name %$AD_SERVER_SEARCH% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + DSQUERY * %$AD_BASE% -scope %$AD_SCOPE% -limit %$sLimit% -filter "(distinguishedName=%%~N)" -attr description %$AD_SERVER_SEARCH% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + DSQUERY * %$AD_BASE% -scope %$AD_SCOPE% -limit %$sLimit% -filter "(distinguishedName=%%~N)" -attr displayName %$AD_SERVER_SEARCH% >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + DSGET GROUP %%N -dn %$AD_SERVER_SEARCH% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% 2> nul >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( echo Members: >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( - DSGET GROUP "%%N" -members %$AD_SERVER_SEARCH% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% 2> nul | DSGET USER -upn -fn -mi -ln -display -email 2> nul >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + DSGET GROUP %%N -members %$AD_SERVER_SEARCH% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% 2> nul | DSGET USER -upn -fn -mi -ln -display -email 2> nul >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( echo Details: >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( - DSQUERY * -filter "(distinguishedName=%%N)" -attr * %$AD_SERVER_SEARCH% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + DSQUERY * -filter "(distinguishedName=%%~N)" -attr * %$AD_SERVER_SEARCH% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( echo ---------------------------------------------------------------------- >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%") ) :jumpSGDL - + call :subTLT + echo Total Search Time: %$TOTAL_LAPSE_TIME% + echo Total Search Time: %$TOTAL_LAPSE_TIME% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo End search: %DATE% %Time% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" IF %$LAST_SEARCH_COUNT% EQU 0 (Echo Nothing found! Try again with broader wildcard.) & (echo.) & (timeout /t 10) IF %$LAST_SEARCH_COUNT% EQU 0 GoTo skipSGDA :: Search counter increment @@ -772,11 +827,14 @@ GoTo jumpSGDL SET /P $SEARCH_KEY=Choose a search key ^(word^): IF NOT DEFINED $SEARCH_KEY (SET $SEARCH_KEY=%$SEARCH_KEY_LAST%) IF /I "%$SEARCH_KEY%"=="NA" GoTo skipSGDNA + call :SM echo Selected {%$SEARCH_KEY%} as search key. SET $LAST_SEARCH_KEY=%$SEARCH_KEY% - echo Searching... + echo Searching... + call :subSET IF EXIST "%$LogPath%\%$LAST_SEARCH_LOG%" DEL /Q "%$LogPath%\%$LAST_SEARCH_LOG%" echo Start search %DATE% %Time% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo UTC: %$UTC% %$UTC_STANDARD_NAME% >> "%$LogPath%\%$LAST_SEARCH_LOG%" echo Search Type: %$LAST_SEARCH_TYPE% >> "%$LogPath%\%$LAST_SEARCH_LOG%" echo Search Attribute: %$LAST_SEARCH_ATTRIBUTE% >> "%$LogPath%\%$LAST_SEARCH_LOG%" echo Search Term: %$SEARCH_KEY% >> "%$LogPath%\%$LAST_SEARCH_LOG%" @@ -861,7 +919,12 @@ GoTo jumpSGDNL echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%") ) :jumpSGDNL - + call :subTLT + echo Total Search Time: %$TOTAL_LAPSE_TIME% + echo Total Search Time: %$TOTAL_LAPSE_TIME% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo End search: %DATE% %Time% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" IF %$LAST_SEARCH_COUNT% EQU 0 (Echo Nothing found! Try again with broader wildcard.) & (echo.) & (timeout /t 10) IF %$LAST_SEARCH_COUNT% EQU 0 GoTo skipSGDNA :: Search counter increment @@ -892,12 +955,231 @@ GoTo jumpSGDNL :sServer :: Search Server SET $LAST_SEARCH_TYPE=Server + SET $LAST_SEARCH_ATTRIBUTE=name call :SM SET $SEARCH_KEY= :: Close previous Windows taskkill /F /FI "WINDOWTITLE eq %$LAST_SEARCH_LOG% - Notepad" 2>nul 1>nul - REM UNDER DEVELOPMENT - GoTo err40 + + echo Use wildcard "*"; if "*" is used alone, will search for all domain controllers. + echo ^(If left blank, will abort.^) + SET /P $SEARCH_KEY=Choose a search key: + IF NOT DEFINED $SEARCH_KEY GoTo Menu + call :SM + echo Selected {%$SEARCH_KEY%} as search key. + SET $LAST_SEARCH_KEY=%$SEARCH_KEY% + echo %$SEARCH_KEY%> "%$LogPath%\var\var_$SEARCH_KEY.txt" + + :: Check on Wildcard * + IF "%$SEARCH_KEY%"=="*" (SET $SERVER_SEARCH_GLOBAL=0) ELSE (SET $SERVER_SEARCH_GLOBAL=1) + echo %$SERVER_SEARCH_GLOBAL% > "%$LogPath%\var\var_$SERVER_SEARCH_GLOBAL.txt" + REM If Forestroot, then searches GC Global Catalog. + set "$AD_SERVER_SEARCH=-s %$DC%.%$DOMAIN%" + if %$AD_BASE%==forestroot SET "$AD_SERVER_SEARCH=-gc" + :: Search Servers + + IF %$SERVER_SEARCH_GLOBAL% EQU 0 SET $AD_BASE=forestroot + + call :SM + :: Log output + call :subSET + IF EXIST "%$LogPath%\%$LAST_SEARCH_LOG%" DEL /Q "%$LogPath%\%$LAST_SEARCH_LOG%" + Echo Start search %DATE% %Time% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo UTC: %$UTC% %$UTC_STANDARD_NAME% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + Echo Search Type: %$LAST_SEARCH_TYPE% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo Search Attribute: %$LAST_SEARCH_ATTRIBUTE% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + Echo Search Term: %$SEARCH_KEY% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo Search AD Root: %$AD_BASE% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo Search AD Scope: %$AD_SCOPE% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo Domain Controller: %$DC% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + Echo Domain: %$DOMAIN% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + + echo Selected {%$SEARCH_KEY%} as search key. + + :: Search type? Domain or Global + IF /I "%$AD_BASE%"=="forestroot" GoTo sServerG + +:sServerN + echo Searching... + :: Search for servers using search key + :: Unsorted + if %$SORTED% EQU 1 GoTo sServerNS + if "%$SESSION_USER%"=="%$DOMAIN_USER%" ( + DSQUERY SERVER -domain %$DOMAIN% -o rdn -name "%$SEARCH_KEY%" -limit %$sLimit% > "%$LogPath%\var\var_Last_Search_N.txt") else ( + DSQUERY SERVER -domain %$DOMAIN% -o rdn -name "%$SEARCH_KEY%" -limit %$sLimit% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% > "%$LogPath%\var\var_Last_Search_N.txt" + ) + if "%$SESSION_USER%"=="%$DOMAIN_USER%" ( + DSQUERY SERVER -domain %$DOMAIN% -o dn -name "%$SEARCH_KEY%" -limit %$sLimit% > "%$LogPath%\var\var_Last_Search_DN.txt") ELSE ( + DSQUERY SERVER -domain %$DOMAIN% -o dn -name "%$SEARCH_KEY%" -limit %$sLimit% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% > "%$LogPath%\var\var_Last_Search_DN.txt" + ) + +GoTo sServerO + +:sServerNS + :: Search for servers using search key + :: sorted + if "%$SESSION_USER%"=="%$DOMAIN_USER%" ( + DSQUERY SERVER -domain %$DOMAIN% -o rdn -name "%$SEARCH_KEY%" -limit %$sLimit% | sort > "%$LogPath%\var\var_Last_Search_N.txt") else ( + DSQUERY SERVER -domain %$DOMAIN% -o rdn -name "%$SEARCH_KEY%" -limit %$sLimit% | sort -u %$DOMAIN_USER% -p %$cUSERPASSWORD% > "%$LogPath%\var\var_Last_Search_N.txt" + ) + if "%$SESSION_USER%"=="%$DOMAIN_USER%" ( + DSQUERY SERVER -domain %$DOMAIN% -o dn -name "%$SEARCH_KEY%" -limit %$sLimit% | sort > "%$LogPath%\var\var_Last_Search_DN.txt") ELSE ( + DSQUERY SERVER -domain %$DOMAIN% -o dn -name "%$SEARCH_KEY%" -limit %$sLimit% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% | sort > "%$LogPath%\var\var_Last_Search_DN.txt" + ) + +GoTo sServerO + +:sServerG + echo Global Server search... + :: Global Server search + :: unsorted + if %$SORTED% EQU 1 GoTo sServerGS + if "%$SESSION_USER%"=="%$DOMAIN_USER%" ( + DSQUERY SERVER -forest -o rdn -limit %$sLimit% > "%$LogPath%\var\var_Last_Search_N.txt") else ( + DSQUERY SERVER -forest -o rdn -gc -limit %$sLimit% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% > "%$LogPath%\var\var_Last_Search_N.txt" + ) + if "%$SESSION_USER%"=="%$DOMAIN_USER%" ( + DSQUERY SERVER -forest -o dn -limit %$sLimit% > "%$LogPath%\var\var_Last_Search_DN.txt") ELSE ( + DSQUERY SERVER -forest -o dn -limit %$sLimit% -u %$DOMAIN_USER% -p %$cUSERPASSWORD%> "%$LogPath%\var\var_Last_Search_DN.txt" + ) + if %$SORTED% NEQ 1 GoTo sServerO + +:sServerGS + :: Global Server search + :: sorted + + if "%$SESSION_USER%"=="%$DOMAIN_USER%" ( + DSQUERY SERVER -forest -o rdn -limit %$sLimit% | sort > "%$LogPath%\var\var_Last_Search_N.txt") else ( + DSQUERY SERVER -forest -o rdn -limit %$sLimit% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% | sort > "%$LogPath%\var\var_Last_Search_N.txt" + ) + if "%$SESSION_USER%"=="%$DOMAIN_USER%" ( + DSQUERY SERVER -forest -o dn -limit %$sLimit% | sort > "%$LogPath%\var\var_Last_Search_DN.txt") ELSE ( + DSQUERY SERVER -forest -o dn -limit %$sLimit% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% | sort > "%$LogPath%\var\var_Last_Search_DN.txt" + ) + +:sServerO + :: Server search main output + FOR /F "tokens=3 delims=:" %%K IN ('FIND /I /C "=" "%$LogPath%\var\var_Last_Search_DN.txt"') DO echo %%K> "%$LogPath%\var\var_Last_Search_Count.txt" + :: remove leading space + FOR /F "tokens=1 delims= " %%P IN (%$LogPath%\var\var_Last_Search_Count.txt) DO echo %%P> "%$LogPath%\var\var_Last_Search_Count.txt" + SET /P $LAST_SEARCH_COUNT= < "%$LogPath%\var\var_Last_Search_Count.txt" + echo Number of search results: %$LAST_SEARCH_COUNT% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo Number of search results: %$LAST_SEARCH_COUNT% + IF %$LAST_SEARCH_COUNT% EQU 0 GoTo skipSO + echo Processing... + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo Server ^(DC's^) returned: >> "%$LogPath%\%$LAST_SEARCH_LOG%" + type "%$LogPath%\var\var_Last_Search_N.txt" >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo Server ^(DC's^) Distinguisged Names: >> "%$LogPath%\%$LAST_SEARCH_LOG%" + type "%$LogPath%\var\var_Last_Search_DN.txt" >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + + :: Check for local or domain user + if NOT "%$SESSION_USER%"=="%$DOMAIN_USER%" GoTo jumpsSL + :: Domain User + + echo Global Catalog Domain Controllers: >> "%$LogPath%\%$LAST_SEARCH_LOG%" + DSQUERY SERVER -forest -o rdn -isgc -limit %$sLimit% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo Schema master of the forest: >> "%$LogPath%\%$LAST_SEARCH_LOG%" + DSQUERY SERVER -forest -o rdn -hasfsmo schema -limit %$sLimit% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo Domain naming master of the forest: >> "%$LogPath%\%$LAST_SEARCH_LOG%" + DSQUERY SERVER -forest -o rdn -hasfsmo name -limit %$sLimit% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo Infrastructure master of the domain: >> "%$LogPath%\%$LAST_SEARCH_LOG%" + DSQUERY SERVER -forest -o rdn -hasfsmo infr -limit %$sLimit% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo Primary domain controller ^(PDC^) role owner: >> "%$LogPath%\%$LAST_SEARCH_LOG%" + DSQUERY SERVER -forest -o rdn -hasfsmo pdc -limit %$sLimit% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo Relative identifier master ^(RID master^): >> "%$LogPath%\%$LAST_SEARCH_LOG%" + DSQUERY SERVER -forest -o rdn -hasfsmo rid -limit %$sLimit% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo ---------------------------------------------------------------------- >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo Verbose Output: >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo ---------------------------------------------------------------------- >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + :: Detailed Output + FOR /F "USEBACKQ tokens=* delims=" %%N IN ("%$LogPath%\var\var_Last_Search_DN.txt") DO ( + DSQUERY * forestroot -filter "(distinguishedName=%%~N)" -attr name >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + DSQUERY * forestroot -filter "(distinguishedName=%%~N)" -attr description >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + DSQUERY * forestroot -filter "(distinguishedName=%%~N)" -attr displayName >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + echo distinguishedName >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + echo %%N >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + echo Details: >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + DSQUERY * forestroot -filter "(distinguishedName=%%~N)" -attr * >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + echo ---------------------------------------------------------------------- >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%") + ) + +GoTo skipsSL + +:jumpsSL + :: Session user is a local user + echo Global Catalog Domain Controllers: >> "%$LogPath%\%$LAST_SEARCH_LOG%" + DSQUERY SERVER -forest -o rdn -isgc -limit %$sLimit% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo Schema master of the forest: >> "%$LogPath%\%$LAST_SEARCH_LOG%" + DSQUERY SERVER -forest -o rdn -hasfsmo schema -limit %$sLimit% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo Domain naming master of the forest: >> "%$LogPath%\%$LAST_SEARCH_LOG%" + DSQUERY SERVER -forest -o rdn -hasfsmo name -limit %$sLimit% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo Infrastructure master of the domain: >> "%$LogPath%\%$LAST_SEARCH_LOG%" + DSQUERY SERVER -forest -o rdn -hasfsmo infr -limit %$sLimit% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo Primary domain controller ^(PDC^) role owner: >> "%$LogPath%\%$LAST_SEARCH_LOG%" + DSQUERY SERVER -forest -o rdn -hasfsmo pdc -limit %$sLimit% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo Relative identifier master ^(RID master^): >> "%$LogPath%\%$LAST_SEARCH_LOG%" + DSQUERY SERVER -forest -o rdn -hasfsmo rid -limit %$sLimit% -u %$DOMAIN_USER% -p %$cUSERPASSWORD% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo ---------------------------------------------------------------------- >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo Verbose Output: >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo ---------------------------------------------------------------------- >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + :: Detailed Output + FOR /F "USEBACKQ tokens=* delims=" %%N IN ("%$LogPath%\var\var_Last_Search_DN.txt") DO ( + DSQUERY * forestroot -filter "(distinguishedName=%%~N)" -attr name -u %$DOMAIN_USER% -p %$cUSERPASSWORD% >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + DSQUERY * forestroot -filter "(distinguishedName=%%~N)" -attr description -u %$DOMAIN_USER% -p %$cUSERPASSWORD% >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + DSQUERY * forestroot -filter "(distinguishedName=%%~N)" -attr displayName -u %$DOMAIN_USER% -p %$cUSERPASSWORD% >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + echo distinguishedName >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + echo %%N >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + echo Details: >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + DSQUERY * forestroot -filter "(distinguishedName=%%~N)" -attr * -u %$DOMAIN_USER% -p %$cUSERPASSWORD% >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + echo ---------------------------------------------------------------------- >> "%$LogPath%\%$LAST_SEARCH_LOG%") & ( + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%") + ) +:skipsSL + +:skipSO + call :subTLT + echo Total Search Time: %$TOTAL_LAPSE_TIME% + echo Total Search Time: %$TOTAL_LAPSE_TIME% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + :: skip server output + echo End search: %DATE% %Time% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + type "%$LogPath%\%$LAST_SEARCH_LOG%" >> "%$LogPath%\%$SEARCH_SESSION_LOG%" + IF %$LAST_SEARCH_COUNT% EQU 0 (Echo Nothing found! Try again with broader wildcard.) + IF %$LAST_SEARCH_COUNT% EQU 0 GoTo skipsServer + :: Search counter increment + Call :fSC + :: Open log files + @explorer "%$LogPath%\%$LAST_SEARCH_LOG%" + +:skipsServer + echo Search Again? + Choice /c yn /m "[y]es or [n]o": + IF %ERRORLEVEL% EQU 2 GoTo Search + IF %ERRORLEVEL% EQU 1 GoTo sServer +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :sOU @@ -914,11 +1196,14 @@ GoTo jumpSGDNL IF NOT DEFINED $SEARCH_KEY GoTo Menu IF /I "%$SEARCH_KEY%"=="NA" GoTo jumpsOU IF "%$SEARCH_KEY%"=="""" GoTo jumpsOU + call :SM echo Selected {%$SEARCH_KEY%} as search key. SET $LAST_SEARCH_KEY=%$SEARCH_KEY% echo Searching... + call :subSET IF EXIST "%$LogPath%\%$LAST_SEARCH_LOG%" DEL /Q "%$LogPath%\%$LAST_SEARCH_LOG%" Echo Start search %DATE% %Time% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo UTC: %$UTC% %$UTC_STANDARD_NAME% >> "%$LogPath%\%$LAST_SEARCH_LOG%" Echo Search Type: %$LAST_SEARCH_TYPE% >> "%$LogPath%\%$LAST_SEARCH_LOG%" Echo Search Term: %$SEARCH_KEY% >> "%$LogPath%\%$LAST_SEARCH_LOG%" echo Search AD Root: %$AD_BASE% >> "%$LogPath%\%$LAST_SEARCH_LOG%" @@ -962,6 +1247,11 @@ GoTo jumpSGDNL type "%$LogPath%\var\var_Last_Search_N.txt" >> "%$LogPath%\%$LAST_SEARCH_LOG%" echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" type "%$LogPath%\var\var_Last_Search_DN.txt" >> "%$LogPath%\%$LAST_SEARCH_LOG%" + call :subTLT + echo Total Search Time: %$TOTAL_LAPSE_TIME% + echo Total Search Time: %$TOTAL_LAPSE_TIME% >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" + echo End search: %DATE% %Time% >> "%$LogPath%\%$LAST_SEARCH_LOG%" echo. >> "%$LogPath%\%$LAST_SEARCH_LOG%" IF %$LAST_SEARCH_COUNT% EQU 0 (Echo Nothing found! Try again with broader wildcard.) & (echo.) & (timeout /t 10) IF %$LAST_SEARCH_COUNT% EQU 0 GoTo sOU @@ -987,33 +1277,6 @@ GoTo jumpSGDNL - - - - - - - - - - - - - - - - - - - - - - - - - - - ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :Uset :: User Settings @@ -1347,10 +1610,7 @@ SET "$DC_TAG=DS Settings" Echo AD Scope: %$AD_SCOPE% Echo Suppress Console Threshold: %$SUPPRESS_CONSOLE_THRESHOLD% Echo Sort: %$SORTED_N% - Echo. - Echo Instructions Echo ------------------------ - Echo Select echo. Echo %$AD_BASE%> "%$LOGPATH%\var\var_AD_Base.txt" Echo %$AD_SCOPE%> "%$LOGPATH%\var\var_AD_Scope.txt" @@ -1358,18 +1618,30 @@ SET "$DC_TAG=DS Settings" echo [1] domainroot echo [2] forestroot echo [3] custom OU + echo [4] load from previous Echo. - Choice /c 123 + Choice /c 1234 Echo. - If ERRORLevel 3 GoTo subADRoot + If ERRORLevel 4 GoTo subADB + If ERRORLevel 3 GoTo sOU If ERRORLevel 2 SET $AD_BASE=forestroot If ERRORLevel 1 SET $AD_BASE=domainroot + +:subADbase + REM if string already contains double-quotes, string comparison in quotes will crash; + REM e.g. "%$AD_BASE%"=="forestroot" --^> ""string""=="forestroot" + echo %$AD_BASE% | (FIND /I "=" 2> nul) & SET $AD_BASE_CUSTOM=%ERRORLEVEL% + echo %$AD_BASE_CUSTOM% > "%$LOGPATH%\var\var_$AD_BASE_CUSTOM.txt" + if %$AD_BASE_CUSTOM% EQU 0 GoTo skipADC + :: Not a custom OU base if /I "%$AD_BASE%"=="forestroot" (SET $AD_SCOPE=subtree) & (GoTo skipASS) - Echo Select AD Scope: + +:skipADC + echo Select AD Scope: echo [1] subtree echo [2] onelevel echo [3] base - Echo. + echo. Choice /c 123 Echo. If ERRORLevel 3 SET $AD_SCOPE=base @@ -1408,10 +1680,14 @@ SET "$DC_TAG=DS Settings" IF %ERRORLEVEL% EQU 1 GoTo uSetS :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: - - - - +:subADB + :: Subroutine to set AD Base with OU + IF NOT EXIST "%$LOGPATH%\var\var_OU_Base.txt" GoTo skipADB + SET /P $AD_BASE= < "%$LOGPATH%\var\var_OU_Base.txt" +:skipADB + IF NOT DEFINED $AD_BASE GoTo uSetS + IF NOT EXIST "%$LOGPATH%\var\var_OU_Base.txt" GoTo uSetS + GoTo subADbase :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: @@ -1529,7 +1805,7 @@ GoTo Search :: End session IF EXIST "%$LOGPATH%\%$SESSION_LOG%" Echo End Session %DATE% %TIME%. >> "%$LOGPATH%\%$SESSION_LOG%" IF EXIST "%$LOGPATH%\%$SESSION_LOG%" Echo. >> "%$LOGPATH%\%$SESSION_LOG%" - + IF EXIST "%$LogPath%\var\var_$PID.txt" del /q "%$LogPath%\var\var_$PID.txt" :: [FUTURE FEATURE] :: Save Session Settings :: IF /I NOT "%$SAVE_SETTINGS%"=="Yes" GoTo skipSSS diff --git a/ADDS_Tool_ToDo.md b/ADDS_Tool_ToDo.md index a991008..941ac43 100644 --- a/ADDS_Tool_ToDo.md +++ b/ADDS_Tool_ToDo.md @@ -13,6 +13,7 @@ - Choose Default Editor (Notepad) - include UTC - Include ISO8601 + - Search lapse time ## DONE ### Settings diff --git a/ChangeLog.md b/ChangeLog.md index de5663a..abaf832 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -17,6 +17,25 @@ [//]: # (#### Security) [//]: # (#### Deprecated) +--- + +## Version 0.0.0 Build: 2020-12- +#### Added +- End search time +- Server (DC) search +- ISO8601 date stamp +- recall custom OU in search settings +- Total lapse time for search(s) +- Session log includes PID +- UTC to logs + +#### Fixed +- Group search using description that had spaces in DN + +#### Removed +- Universal search using "*" wildcard + + --- ## Version 0.0.0 Build: 2020-12-15 @@ -33,8 +52,6 @@ - Forestroot search for OU ---- - ## Version 0.0.0 Build: 2020-12-08 #### Added - Under development diff --git a/DSQUERY_Attributes.txt b/DSQUERY_Attributes.txt new file mode 100644 index 0000000..832c0f9 --- /dev/null +++ b/DSQUERY_Attributes.txt @@ -0,0 +1,20 @@ +ADsPath +cn +description +displayName +distinguishedName +extensionAttribute1 +mail +mailNickname +member +name +objectCategory +objectClass +objectGUID +objectSid +primaryGroupID +sAMAccountName +sAMAccountType +userPrincipalName +whenChanged +whenCreated \ No newline at end of file diff --git a/Notes.md b/Notes.md index 75124bb..f4be905 100644 --- a/Notes.md +++ b/Notes.md @@ -2,4 +2,5 @@ ## Search - If Forestroot is the base, then searc must be against GC (Global Catalog) `-gc`. -- Test searches against results with spaces: use `scientifc*` as search key \ No newline at end of file +- Test searches against results with spaces: use `scientifc*` as search key +- `Query * -filter (attribute= Active Directory Domain Services Tool (ADDS_Tool)
+ +![Main Banner](./images/ADDS_T_Main_Banner.png) + +:bangbang: :construction: :bangbang: **UNDER DEVELOPMENT** -:rocket: + + :bangbang: :construction: :bangbang: + *Weekly build release* -## What's Working + +## Table of Contents + +- [Introduction](#introduction) +- [Dependencies](#Dependencies) +- [Features](#features) +- [Images](#Images) + +## Introduction + +Tool that is a wrapper for ADDS toolset: + - `DSQUERY` + - `DSGET` + - `DSADD` + - `DSMOD` + - `DSMOVE` + +## Dependencies + +ADDS_Tool requires (RSAT) [Remote Server Administrative Tools](https://docs.microsoft.com/en-us/troubleshoot/windows-server/system-management-components/remote-server-administration-tools). +The program will ask to install if not detected, using [DISM](https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/what-is-dism). +Must be runnig with administartive privilege in order to install RSAT. + +## Features + + What's Working + +*Currently only searching is working.* - [X] Main Menu - [X] Settings Menu @@ -13,7 +46,7 @@ - [ ] Search User - [X] Search Group - [ ] Search Computer -- [ ] Search Server +- [X] Search Server - [X] Search OU @@ -26,3 +59,8 @@ ### Parameters + + + + +:us: \ No newline at end of file diff --git a/images/ADDS_T_Main_Banner.png b/images/ADDS_T_Main_Banner.png new file mode 100644 index 0000000000000000000000000000000000000000..4167bc9fdb151e6e2b63a3df49bdbf18f4010f73 GIT binary patch literal 13632 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 Dm;|Hy literal 0 HcmV?d00001