diff --git a/.vs/OpenPasswordFilter/v14/.suo b/.vs/OpenPasswordFilter/v14/.suo new file mode 100644 index 0000000..5e075ac Binary files /dev/null and b/.vs/OpenPasswordFilter/v14/.suo differ diff --git a/Lists/opfgroups.txt b/Lists/opfgroups.txt new file mode 100644 index 0000000..e69de29 diff --git a/Lists/opfregex.txt b/Lists/opfregex.txt new file mode 100644 index 0000000..e69de29 diff --git a/OPFService/App.config b/OPFService/App.config index 77ed642..a3f4642 100644 --- a/OPFService/App.config +++ b/OPFService/App.config @@ -2,5 +2,5 @@ - + diff --git a/OPFService/NetworkService.cs b/OPFService/NetworkService.cs index 9e25c96..d5cbf12 100644 --- a/OPFService/NetworkService.cs +++ b/OPFService/NetworkService.cs @@ -21,51 +21,74 @@ using System.Net; using System.Net.Sockets; using System.IO; +using System.Diagnostics; + namespace OPFService { - class NetworkService { - OPFDictionary dict; + class NetworkService { + OPFDictionary dict; + OPFGroup group; + private void writeLog(string message, System.Diagnostics.EventLogEntryType level) { + using (EventLog eventLog = new EventLog("Application")) { + eventLog.Source = "Application"; + eventLog.WriteEntry(message, level, 100, 1); + } + } - public NetworkService(OPFDictionary d) { - dict = d; - } + public NetworkService(OPFDictionary d, OPFGroup g) { + dict = d; + group = g; + } - public void main() { - IPAddress ip = IPAddress.Parse("127.0.0.1"); - IPEndPoint local = new IPEndPoint(ip, 5999); - Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + public void main() { + IPAddress ip = IPAddress.Parse("127.0.0.1"); + IPEndPoint local = new IPEndPoint(ip, 5999); + Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - try { - listener.Bind(local); - listener.Listen(64); - while (true) { - Socket client = listener.Accept(); - new Thread(() => handle(client)).Start(); - } - } catch (Exception e) { - // don't know what to do here - } + try { + listener.Bind(local); + listener.Listen(64); + writeLog("OpenPasswordFilter is now running.", EventLogEntryType.Information); + while (true) { + Socket client = listener.Accept(); + new Thread(() => handle(client)).Start(); } + } catch (Exception e) { + // don't know what to do here + } + } - public void handle(Socket client) { - try { - NetworkStream netStream = new NetworkStream(client); - StreamReader istream = new StreamReader(netStream); - StreamWriter ostream = new StreamWriter(netStream); - string command = istream.ReadLine(); - if (command == "test") { - string password = istream.ReadLine(); - ostream.WriteLine(dict.contains(password) ? "false" : "true"); - ostream.Flush(); - } else { - ostream.WriteLine("ERROR"); - ostream.Flush(); - } - } catch (Exception e) { - - } - client.Close(); + /* + * if (user is in one of the listed groups or there are no groups listed) then + * if username/password combo is not acceptable then return "false" + * return "true" + * */ + public void handle(Socket client) { + try { + NetworkStream netStream = new NetworkStream(client); + StreamReader istream = new StreamReader(netStream); + StreamWriter ostream = new StreamWriter(netStream); + string command = istream.ReadLine(); + if (command == "test") { + string username = istream.ReadLine(); + string password = istream.ReadLine(); + writeLog("Validating password for user " + username, EventLogEntryType.Information); + if (group.contains(username)) { + writeLog("User in a restricted group", EventLogEntryType.Information); + ostream.WriteLine(dict.contains(password) ? "false" : "true"); + } else { + ostream.WriteLine("true"); + } + ostream.Flush(); + } else { + ostream.WriteLine("ERROR"); + ostream.Flush(); } + } catch (Exception e) { + + } + client.Close(); } + } } diff --git a/OPFService/OPFDictionary.cs b/OPFService/OPFDictionary.cs index 78b7e7b..710a44f 100644 --- a/OPFService/OPFDictionary.cs +++ b/OPFService/OPFDictionary.cs @@ -17,90 +17,115 @@ using System; using System.Collections.Generic; -using System.Collections; using System.IO; using System.Diagnostics; +using System.Text.RegularExpressions; namespace OPFService { - class OPFDictionary { - List matchlist; - List contlist; + class OPFDictionary { + HashSet matchlist; + List contlist; + List regexlist; - public OPFDictionary(string pathmatch, string pathcont) { - string line; - StreamReader infilematch = new StreamReader(pathmatch); - matchlist = new List(); - int a = 1; - while ((line = infilematch.ReadLine()) != null) - { - try - { - matchlist.Add(line.ToLower()); - a += 1; - } - catch - { - using (EventLog eventLog = new EventLog("Application")) - { - eventLog.Source = "Application"; - eventLog.WriteEntry("Died trying to ingest line number " + a.ToString() + " of opfmatch.txt.", EventLogEntryType.Information, 101, 1); - } - } - } - infilematch.Close(); - StreamReader infilecont = new StreamReader(pathcont); - contlist = new List(); - a = 1; - while ((line = infilecont.ReadLine()) != null) - { - try - { - contlist.Add(line.ToLower()); - a += 1; - } - catch - { - using (EventLog eventLog = new EventLog("Application")) - { - eventLog.Source = "Application"; - eventLog.WriteEntry("Died trying to ingest line number " + a.ToString() + " of opfcont.txt.", EventLogEntryType.Information, 101, 1); - } - } - } + public void writeLog(string message, System.Diagnostics.EventLogEntryType level) { + using (EventLog eventLog = new EventLog("Application")) { + eventLog.Source = "Application"; + eventLog.WriteEntry(message, level, 101, 1); + } + } + public OPFDictionary(string pathmatch, string pathcont, string pathregex) { + + writeLog("Opening Match Configuration File", EventLogEntryType.Information); + string line; + StreamReader infilematch = new StreamReader(pathmatch); + matchlist = new HashSet(); + int a = 1; + while ((line = infilematch.ReadLine()) != null) { + try { + matchlist.Add(line.ToLower()); + a += 1; + } catch { + using (EventLog eventLog = new EventLog("Application")) { + eventLog.Source = "Application"; + eventLog.WriteEntry("Died trying to ingest line number " + a.ToString() + " of opfmatch.txt.", EventLogEntryType.Error, 101, 1); + } + } + } + infilematch.Close(); + writeLog("Opening Contains Configuration File", EventLogEntryType.Information); + StreamReader infilecont = new StreamReader(pathcont); + contlist = new List(); + a = 1; + while ((line = infilecont.ReadLine()) != null) { + try { + contlist.Add(line.ToLower()); + a += 1; + } catch { + using (EventLog eventLog = new EventLog("Application")) { + eventLog.Source = "Application"; + eventLog.WriteEntry("Died trying to ingest line number " + a.ToString() + " of opfcont.txt.", EventLogEntryType.Error, 101, 1); + } + } + } + infilematch.Close(); + writeLog("Opening Regular Expression Configuration File", EventLogEntryType.Information); + StreamReader infileregex = new StreamReader(pathregex); + regexlist = new List(); + a = 1; + while ((line = infileregex.ReadLine()) != null) { + try { + regexlist.Add(new Regex(line, RegexOptions.IgnoreCase)); + a += 1; + } catch { + using (EventLog eventLog = new EventLog("Application")) { + eventLog.Source = "Application"; + eventLog.WriteEntry("Died trying to ingest line number " + a.ToString() + " of opfregex.txt.", EventLogEntryType.Error, 101, 1); + } } + } + infileregex.Close(); + + writeLog("Successfully parsed all configuration files", EventLogEntryType.Information); + + } - public Boolean contains(string word) { - foreach (string badstr in contlist) - { - if (word.ToLower().Contains(badstr)) - { - using (EventLog eventLog = new EventLog("Application")) - { - eventLog.Source = "Application"; - eventLog.WriteEntry("Password attempt contains poison string " + badstr +", case insensitive.", EventLogEntryType.Information, 101, 1); - } - return true; - } - } - if (matchlist.Contains(word)) - { - using (EventLog eventLog = new EventLog("Application")) - { - eventLog.Source = "Application"; - eventLog.WriteEntry("Password attempt matched a string in the bad password list", EventLogEntryType.Information, 101, 1); - } - return true; - } - else - { - using (EventLog eventLog = new EventLog("Application")) - { - eventLog.Source = "Application"; - eventLog.WriteEntry("Password passed custom filter.", EventLogEntryType.Information, 101, 1); - } - return false; - } + public Boolean contains(string word) { + foreach (string badstr in contlist) { + if (word.ToLower().Contains(badstr)) { + using (EventLog eventLog = new EventLog("Application")) { + eventLog.Source = "Application"; + eventLog.WriteEntry("Password attempt contains poison string " + badstr + ", case insensitive.", EventLogEntryType.Information, 101, 1); + } + return true; } + } + + if (matchlist.Contains(word)) { + using (EventLog eventLog = new EventLog("Application")) { + eventLog.Source = "Application"; + eventLog.WriteEntry("Password attempt matched a string in the bad password list", EventLogEntryType.Information, 101, 1); + } + return true; + } + + foreach (Regex r in regexlist) { + + Match m = r.Match(word); + if (m.Success) { + using (EventLog eventLog = new EventLog("Application")) { + eventLog.Source = "Application"; + eventLog.WriteEntry("Password attempt matched this regular express: " + r.ToString(), EventLogEntryType.Information, 101, 1); + } + return true; + } + } + + using (EventLog eventLog = new EventLog("Application")) { + eventLog.Source = "Application"; + eventLog.WriteEntry("Password passed custom filter.", EventLogEntryType.Information, 101, 1); + } + return false; } + } } diff --git a/OPFService/OPFGroup.cs b/OPFService/OPFGroup.cs new file mode 100644 index 0000000..77cefa9 --- /dev/null +++ b/OPFService/OPFGroup.cs @@ -0,0 +1,88 @@ +// This file is part of OpenPasswordFilter. +// +// OpenPasswordFilter is free software; you can redistribute it and / or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OpenPasswordFilter is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with OpenPasswordFilter; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 - 1307 USA +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Diagnostics; +using System.DirectoryServices.AccountManagement; + +namespace OPFService { + class OPFGroup { + List grouplist; + + public void writeLog(string message, System.Diagnostics.EventLogEntryType level) { + using (EventLog eventLog = new EventLog("Application")) { + eventLog.Source = "Application"; + eventLog.WriteEntry(message, level, 101, 1); + } + } + + public OPFGroup(string pathgroups) { + string line; + + StreamReader infilematch = new StreamReader(pathgroups); + grouplist = new List(); + int a = 1; + while ((line = infilematch.ReadLine()) != null) { + try { + grouplist.Add(line.ToLower()); + writeLog("groups are: " + line, EventLogEntryType.Information); + a += 1; + } catch { + writeLog("Died trying to ingest line number " + a.ToString() + " of groups file.", EventLogEntryType.Error); + } + } + infilematch.Close(); + writeLog("Succesfully read " + (a - 1).ToString() + " groups.", EventLogEntryType.Information); + } + + public Boolean contains(string username) { + + // if the groups file is empty then we always check the passwords + if (grouplist.Count == 0) { + writeLog("No groups found. User's password will be validated.", EventLogEntryType.Information); + return true; + } + + PrincipalContext ctx = null; + GroupPrincipal groupCtx = null; + + ctx = new System.DirectoryServices.AccountManagement.PrincipalContext(ContextType.Domain); + + foreach (String groupname in grouplist) { + //writeLog("trying [" + groupname + "]", EventLogEntryType.Information); + groupCtx = GroupPrincipal.FindByIdentity(ctx, groupname); + if (groupCtx != null) { + //writeLog("found [" + groupCtx.ToString() + "]. Finding members", EventLogEntryType.Information); + foreach (Principal user in groupCtx.GetMembers(true)) { + if (user.SamAccountName == username) { + writeLog("User " + username + " is in restricted group " + groupname + " and their password will be validated.", EventLogEntryType.Information); + ctx.Dispose(); + groupCtx.Dispose(); + return true; + } + } + groupCtx.Dispose(); + } + } + ctx.Dispose(); + writeLog("User " + username + " is not in a restricted group", EventLogEntryType.Information); + return false; + } + } +} diff --git a/OPFService/OPFService.csproj b/OPFService/OPFService.csproj index f6a5b4e..62a39a6 100644 --- a/OPFService/OPFService.csproj +++ b/OPFService/OPFService.csproj @@ -9,9 +9,24 @@ Properties OPFService OPFService - v3.5 + v4.5.2 512 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true AnyCPU @@ -22,6 +37,7 @@ DEBUG;TRACE prompt 4 + false x86 @@ -31,6 +47,7 @@ TRACE prompt 4 + false true @@ -60,6 +77,7 @@ x86 prompt MinimumRecommendedRules.ruleset + false bin\x86\Release\ @@ -69,11 +87,13 @@ x86 prompt MinimumRecommendedRules.ruleset + false + @@ -85,6 +105,7 @@ + Component @@ -111,6 +132,13 @@ ProjectInstaller.cs + + + False + .NET Framework 3.5 SP1 + true + +