/// <summary> /// /// </summary> /// <returns></returns> public static int Main(string[] args) { var log = ConsoleLogWriter.CreateLog("main", LogLevel.Info, "${Message}"); if (0 == args.Length) { log.Error("no dir given"); return(-1); } var src = Environment.CurrentDirectory; var trg = args[0]; if (1 < args.Length) { src = args[0]; trg = args[1]; } var syncer = new DirectorySynchronization(src, trg) { Log = log }; try{ syncer.Synchronize(); } catch (Exception ex) { log.Error("error " + ex.Message, ex); return(-2); } return(0); }
public void ResetDirectorySynchronizationCookie_Parameterless_SetsToEmpty() { var synchronization = new DirectorySynchronization(new byte[] { 1, 2, 3 }); synchronization.ResetDirectorySynchronizationCookie(); Assert.Empty(synchronization.GetDirectorySynchronizationCookie()); }
public void ResetDirectorySynchronizationCookie_Cookie_SetsToEmpty(byte[] cookie) { var synchronization = new DirectorySynchronization(new byte[] { 255, 255, 255 }); synchronization.ResetDirectorySynchronizationCookie(cookie); Assert.Equal(cookie ?? Array.Empty <byte>(), synchronization.GetDirectorySynchronizationCookie()); }
public void Ctor_Default() { var synchronization = new DirectorySynchronization(); Assert.Equal(DirectorySynchronizationOptions.None, synchronization.Option); Assert.Empty(synchronization.GetDirectorySynchronizationCookie()); }
public void Ctor_Synchronization(DirectorySynchronization otherSynchronization) { var synchronization = new DirectorySynchronization(otherSynchronization); Assert.Equal(otherSynchronization?.Option ?? DirectorySynchronizationOptions.None, synchronization.Option); Assert.Equal(otherSynchronization?.GetDirectorySynchronizationCookie() ?? Array.Empty <byte>(), synchronization.GetDirectorySynchronizationCookie()); }
public void Ctor_Option(DirectorySynchronizationOptions option) { var synchronization = new DirectorySynchronization(option); Assert.Equal(option, synchronization.Option); Assert.Empty(synchronization.GetDirectorySynchronizationCookie()); }
public void SyncThemasDiff() { var sync = new DirectorySynchronization(@"C:\z3projects\assoi\local\Draft\themas\.old\thema", @"C:\mnt\testthemas"); foreach (var fileItem in sync.GetDifference()) { Console.WriteLine(fileItem); } }
public void Copy_Invoke_ReturnsExpected() { var synchronization = new DirectorySynchronization(DirectorySynchronizationOptions.ObjectSecurity, new byte[] { 1, 2, 3 }); DirectorySynchronization copy = synchronization.Copy(); Assert.NotSame(synchronization, copy); Assert.Equal(DirectorySynchronizationOptions.ObjectSecurity, synchronization.Option); Assert.Equal(new byte[] { 1, 2, 3 }, synchronization.GetDirectorySynchronizationCookie()); }
public void SyncThemas() { var sync = new DirectorySynchronization(@"C:\z3projects\assoi\local\Draft\themas\.old\thema", @"C:\mnt\testthemas") { Log = ConsoleLogWriter.CreateLog("main", customFormat: "${Message}") }; sync.Synchronize(); }
public void Ctor_Option_Cookie(DirectorySynchronizationOptions option, byte[] cookie) { var synchronization = new DirectorySynchronization(option, cookie); Assert.Equal(option, synchronization.Option); byte[] synchronizationCookie = synchronization.GetDirectorySynchronizationCookie(); Assert.NotSame(synchronizationCookie, cookie); Assert.Equal(cookie ?? Array.Empty <byte>(), synchronizationCookie); }
public void ResetDirectorySynchronizationCookie_Cookie_MakesCopyOfCookie() { var cookie = new byte[] { 1, 2, 3 }; var synchronization = new DirectorySynchronization(); synchronization.ResetDirectorySynchronizationCookie(cookie); cookie[0] = 20; Assert.Equal(new byte[] { 1, 2, 3 }, synchronization.GetDirectorySynchronizationCookie()); }
private void InitializeDirectorySearcher(IJobExecutionContext context) { if (directorySearcher == null) { directorySearcher = (DirectorySearcher)context.JobDetail.JobDataMap[JOB_DATA_DIRECTORY_SEARCHER]; } if (directorySearcher == null) { var attributes = new HashSet <string>(); attributes.Add("objectGuid"); attributes.Add("distinguishedName"); attributes.Add("ou"); attributes.Add("sAMAccountName"); attributes.Add(AppConfiguration.OUAttributeFiltered); attributes.Add(AppConfiguration.OUAttributeEan); attributes.Add(AppConfiguration.OUAttributeDtrId); attributes.Add(AppConfiguration.OUAttributeEmail); attributes.Add(AppConfiguration.OUAttributeLocation); attributes.Add(AppConfiguration.OUAttributeLOSShortName); attributes.Add(AppConfiguration.OUAttributeName); attributes.Add(AppConfiguration.OUAttributePayoutUnitUUID); attributes.Add(AppConfiguration.OUAttributePhone); attributes.Add(AppConfiguration.OUAttributeLOSId); attributes.Add(AppConfiguration.OUAttributePost); attributes.Add(AppConfiguration.UserAttributeLocation); attributes.Add(AppConfiguration.UserAttributeMail); attributes.Add(AppConfiguration.UserAttributePersonCpr); attributes.Add(AppConfiguration.UserAttributePersonName); attributes.Add(AppConfiguration.UserAttributePhone); attributes.Add(AppConfiguration.UserAttributePositionName); attributes.Add(AppConfiguration.UserAttributeRacfID); attributes.Remove(null); attributes.Remove(""); var attributesArray = new string[attributes.Count]; attributes.CopyTo(attributesArray); DirectorySynchronization dirSync = new DirectorySynchronization(); dirSync.Option = DirectorySynchronizationOptions.ObjectSecurity; directorySearcher = new DirectorySearcher("(&(|(objectClass=user)(objectClass=organizationalUnit))(!(objectClass=computer)))", attributesArray); directorySearcher.SizeLimit = 500; directorySearcher.DirectorySynchronization = dirSync; context.JobDetail.JobDataMap.Put(JOB_DATA_DIRECTORY_SEARCHER, directorySearcher); } }
public void InitializeCookie(string qry) { //this is our searchroot DirectoryEntry entry = new DirectoryEntry( _adsPath, _username, _password, AuthenticationTypes.None //.Secure ); using (entry) { //we want to track all attributes (use null) string[] attribs = null; DirectorySearcher ds = new DirectorySearcher( entry, qry, attribs ); //we must use Subtree scope ds.SearchScope = SearchScope.Subtree; //pass in the flags we wish here DirectorySynchronization dSynch = new DirectorySynchronization( DirectorySynchronizationOptions.None ); ds.DirectorySynchronization = dSynch; using (SearchResultCollection src = ds.FindAll()) { Console.WriteLine( "Initially Found {0} objects", src.Count ); //get and store the cookie StoreCookie( dSynch.GetDirectorySynchronizationCookie() ); } } }
public DirectorySynchronization(DirectorySynchronization sync) { }
public void SyncThemas() { var sync = new DirectorySynchronization(@"C:\z3projects\assoi\local\Draft\themas\.old\thema", @"C:\mnt\testthemas"){Log=ConsoleLogWriter.CreateLog("main",customFormat:"${Message}")}; sync.Synchronize(); }
public void SyncThemasDiff(){ var sync = new DirectorySynchronization(@"C:\z3projects\assoi\local\Draft\themas\.old\thema", @"C:\mnt\testthemas"); foreach (var fileItem in sync.GetDifference()){ Console.WriteLine(fileItem); } }
static void Main(string[] args) { string ldapCookie = "adsync-cookie.dat"; string str_dcName = "dc01.isengard.local"; bool firstRun = true; _nullSids = new ConcurrentDictionary <string, byte>(); _guidMap = new ConcurrentDictionary <string, string>(); _baseGuids = new ConcurrentDictionary <string, string>(); _baseGuids.TryAdd("user", "bf967aba-0de6-11d0-a285-00aa003049e2"); _baseGuids.TryAdd("computer", "bf967a86-0de6-11d0-a285-00aa003049e2"); _baseGuids.TryAdd("group", "bf967a9c-0de6-11d0-a285-00aa003049e2"); _baseGuids.TryAdd("domain", "19195a5a-6da0-11d0-afd3-00c04fd930c9"); _baseGuids.TryAdd("gpo", "f30e3bc2-9ff0-11d1-b603-0000f80367c1"); System.DirectoryServices.DirectoryEntry rootDSE = new System.DirectoryServices.DirectoryEntry("LDAP://rootDSE"); System.Net.NetworkCredential cr = new System.Net.NetworkCredential(@"Administrator", "1qazxsw2..", "isengard.local"); LdapConnection connection = new LdapConnection(str_dcName); connection.Credential = cr; connection.Bind(); DirectorySynchronization sync = new DirectorySynchronization(); DirectorySearcher src2 = new DirectorySearcher(); if (File.Exists(ldapCookie)) { byte[] byteCookie = File.ReadAllBytes(ldapCookie); sync.ResetDirectorySynchronizationCookie(byteCookie); firstRun = false; } src2.DirectorySynchronization = sync; foreach (SearchResult res in src2.FindAll()) { ResultPropertyCollection fields = res.Properties; foreach (String ldapField in fields.PropertyNames) { foreach (Object myCollection in fields[ldapField]) { if (!firstRun) { if (ldapField == "distinguishedname") { Console.WriteLine(String.Format("[+] DN = {0}", myCollection)); } if (ldapField == "ntsecuritydescriptor") { Console.WriteLine("[+] Detected ACL Change: "); var aces = new List <ACL>(); var newDescriptor = new ActiveDirectorySecurity(); newDescriptor.SetSecurityDescriptorBinaryForm((byte[])myCollection); // todo add owner foreach (ActiveDirectoryAccessRule ace in newDescriptor.GetAccessRules(true, true, typeof(SecurityIdentifier))) { //Ignore null aces if (ace == null) { continue; } //Ignore Deny aces if (!ace.AccessControlType.Equals(AccessControlType.Allow)) { continue; } //Resolve the principal in the ACE var principal = GetAcePrincipal(ace, "isengard.local"); string name = new System.Security.Principal.SecurityIdentifier(principal).Translate(typeof(System.Security.Principal.NTAccount)).ToString(); //If its null, we don't care so move on if (principal == null) { continue; } //Interesting Domain ACEs - GenericAll, WriteDacl, WriteOwner, Replication Rights, AllExtendedRights var rights = ace.ActiveDirectoryRights; var objectAceType = ace.ObjectType.ToString(); if (rights.HasFlag(ActiveDirectoryRights.GenericAll)) { if (objectAceType == AllGuid || objectAceType == "") { aces.Add(new ACL { AceType = "", RightName = "GenericAll", PrincipalName = name, PrincipalType = principal }); } //GenericAll includes every other flag, so continue here so we don't duplicate privs continue; } if (rights.HasFlag(ActiveDirectoryRights.WriteDacl)) { aces.Add(new ACL { AceType = "", RightName = "WriteDacl", PrincipalName = name, PrincipalType = principal }); } if (rights.HasFlag(ActiveDirectoryRights.WriteOwner)) { aces.Add(new ACL { AceType = "", RightName = "WriteOwner", PrincipalName = name, PrincipalType = principal }); } if (rights.HasFlag(ActiveDirectoryRights.ExtendedRight)) { if (objectAceType == "1131f6aa-9c07-11d1-f79f-00c04fc2dcd2") { aces.Add(new ACL { AceType = "GetChanges", RightName = "ExtendedRight", PrincipalName = name, PrincipalType = principal }); } else if (objectAceType == "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2") { aces.Add(new ACL { AceType = "GetChangesAll", RightName = "ExtendedRight", PrincipalName = name, PrincipalType = principal }); } else if (objectAceType == AllGuid || objectAceType == "") { aces.Add(new ACL { AceType = "All", RightName = "ExtendedRight", PrincipalName = name, PrincipalType = principal }); } } } foreach (var ace in aces) { Console.WriteLine(String.Format("[+] {0} has {1}", ace.PrincipalName, ace.RightName)); } ; } if (ldapField == "useraccountcontrol") { Console.WriteLine(String.Format("[+] UAC edited: {0}", myCollection)); } } } } } File.WriteAllBytes(ldapCookie, sync.GetDirectorySynchronizationCookie()); }
/// <summary> /// Сравнение предыдущего и текущего состояния Active Directory на основе куки /// </summary> private static void CompareSnapshot() { var dirSync = new DirectorySynchronization(DirectorySynchronizationOptions.ObjectSecurity, _cookie); _directorySearcher = new DirectorySearcher(_directoryEntry) { DirectorySynchronization = dirSync }; foreach (SearchResult res in _directorySearcher.FindAll()) { var delta = res?.Properties; if (delta?.PropertyNames == null) { continue; } var found = false; foreach (string prop in delta.PropertyNames) { switch (prop.ToLower()) { case "objectguid": case "adspath": case "instancetype": case "whenchanged": case "lastlogontimestamp": case "lastlogon": case "pwdlastset": case "distinguishedname": break; case "cn": case "name": case "samaccountname": case "samaccounttype": case "description": case "operatingsystem": case "primarygroupid": case "useraccountcontrol": case "company": case "department": case "displayname": case "givenname": case "l": case "mail": case "memberof": case "member": case "physicaldeliveryofficename": case "sn": case "telephonenumber": case "title": case "userworkstations": case "parentguid": case "isdeleted": if (delta.Contains("isdeleted") && bool.TryParse(delta["isdeleted"][0].ToString(), out var deleted) && deleted) { ProcessDeleted(delta["distinguishedname"][0].ToString()); found = true; } else if (delta.Contains("parentguid")) { ProcessMoved(delta["distinguishedname"][0].ToString()); found = true; } else { ProcessChanged(res.GetDirectoryEntry(), prop, delta); found = true; } break; } } if (found) { OnAdChanged?.Invoke(); } _directorySearcher.DirectorySynchronization.ResetDirectorySynchronizationCookie(_cookie); InitializeSnapshot(); } }
public DirectorySynchronization(DirectorySynchronization sync) {}
public void GetSynchedChanges(string qry, bool saveState) { //this is our searchroot DirectoryEntry entry = new DirectoryEntry( _adsPath, _username, _password, AuthenticationTypes.None ); using (entry) { string[] attribs = null; DirectorySearcher ds = new DirectorySearcher( entry, qry, attribs ); //we must use Subtree scope ds.SearchScope = SearchScope.Subtree; //pass back in our saved cookie DirectorySynchronization dSynch = new DirectorySynchronization( DirectorySynchronizationOptions.None, RestoreCookie() ); ds.DirectorySynchronization = dSynch; using (SearchResultCollection src = ds.FindAll()) { Console.WriteLine( "Subsequently Changed: {0} objects", src.Count ); //return each object that has changed //and what attributes have changed. //keeping in mind that the attributes: //'objectGuid', 'instanceType', and //'adsPath' will always be returned as well foreach (SearchResult sr in src) { Console.WriteLine( "Detected Change in {0}", sr.Properties["AdsPath"][0] ); Console.WriteLine("Changed Values:"); Console.WriteLine("===============================:"); foreach (string prop in sr.Properties.PropertyNames) { foreach (object o in sr.Properties[prop]) { Console.WriteLine( "\t {0} : {1}", prop, o ); } } } if (saveState) { //get and store the cookie again StoreCookie( dSynch.GetDirectorySynchronizationCookie() ); } } } }