├── .gitattributes ├── KeyOnline.sln ├── KeyOnline ├── ConfigWin.Designer.cs ├── ConfigWin.cs ├── ConfigWin.resx ├── FingerPrint.cs ├── KeyOnline.cs ├── KeyOnline.csproj ├── KeyOnline.sln ├── Properties │ └── AssemblyInfo.cs ├── README.md ├── StatusWin.Designer.cs ├── StatusWin.cs ├── StatusWin.resx ├── Toolbox.cs └── Web References │ └── KeyServerWS │ ├── Default.disco │ ├── Default.wsdl │ ├── Reference.cs │ └── Reference.map ├── KeyServer ├── Default.asmx ├── KeyServer.csproj ├── Keys.xml ├── Permissions.xml ├── Properties │ └── AssemblyInfo.cs ├── README.md ├── Requests.xml ├── Soap.cs └── Web.config └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto -------------------------------------------------------------------------------- /KeyOnline.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | # SharpDevelop 5.1 5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeyOnline", "KeyOnline\KeyOnline.csproj", "{AB7F26CB-B578-4521-86ED-43875F238870}" 6 | EndProject 7 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeyServer", "KeyServer\KeyServer.csproj", "{33B9B663-FC0E-4E7D-A1FB-79841C8428E2}" 8 | EndProject 9 | Global 10 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 11 | Debug|Any CPU = Debug|Any CPU 12 | Release|Any CPU = Release|Any CPU 13 | EndGlobalSection 14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 15 | {AB7F26CB-B578-4521-86ED-43875F238870}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 16 | {AB7F26CB-B578-4521-86ED-43875F238870}.Debug|Any CPU.Build.0 = Debug|Any CPU 17 | {AB7F26CB-B578-4521-86ED-43875F238870}.Release|Any CPU.ActiveCfg = Release|Any CPU 18 | {AB7F26CB-B578-4521-86ED-43875F238870}.Release|Any CPU.Build.0 = Release|Any CPU 19 | {33B9B663-FC0E-4E7D-A1FB-79841C8428E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 20 | {33B9B663-FC0E-4E7D-A1FB-79841C8428E2}.Debug|Any CPU.Build.0 = Debug|Any CPU 21 | {33B9B663-FC0E-4E7D-A1FB-79841C8428E2}.Release|Any CPU.ActiveCfg = Release|Any CPU 22 | {33B9B663-FC0E-4E7D-A1FB-79841C8428E2}.Release|Any CPU.Build.0 = Release|Any CPU 23 | EndGlobalSection 24 | EndGlobal 25 | -------------------------------------------------------------------------------- /KeyOnline/ConfigWin.Designer.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Created by SharpDevelop. 3 | * User: Patrice 4 | * Date: 04/06/2017 5 | * Time: 21:56 6 | * 7 | * To change this template use Tools | Options | Coding | Edit Standard Headers. 8 | */ 9 | namespace KeyOnline.Forms 10 | { 11 | partial class ConfigWin 12 | { 13 | /// 14 | /// Designer variable used to keep track of non-visual components. 15 | /// 16 | private System.ComponentModel.IContainer components = null; 17 | private System.Windows.Forms.Label labelURL; 18 | private System.Windows.Forms.Label labelLogin; 19 | private System.Windows.Forms.Label labelPassword; 20 | private System.Windows.Forms.TextBox textBoxURL; 21 | private System.Windows.Forms.TextBox textBoxLogin; 22 | private System.Windows.Forms.TextBox textBoxPassword; 23 | private System.Windows.Forms.Button buttonOK; 24 | private System.Windows.Forms.Button buttonCancel; 25 | 26 | /// 27 | /// Disposes resources used by the form. 28 | /// 29 | /// true if managed resources should be disposed; otherwise, false. 30 | protected override void Dispose(bool disposing) 31 | { 32 | if (disposing) { 33 | if (components != null) { 34 | components.Dispose(); 35 | } 36 | } 37 | base.Dispose(disposing); 38 | } 39 | 40 | /// 41 | /// This method is required for Windows Forms designer support. 42 | /// Do not change the method contents inside the source code editor. The Forms designer might 43 | /// not be able to load this method if it was changed manually. 44 | /// 45 | private void InitializeComponent() 46 | { 47 | this.labelURL = new System.Windows.Forms.Label(); 48 | this.labelLogin = new System.Windows.Forms.Label(); 49 | this.labelPassword = new System.Windows.Forms.Label(); 50 | this.textBoxURL = new System.Windows.Forms.TextBox(); 51 | this.textBoxLogin = new System.Windows.Forms.TextBox(); 52 | this.textBoxPassword = new System.Windows.Forms.TextBox(); 53 | this.buttonOK = new System.Windows.Forms.Button(); 54 | this.buttonCancel = new System.Windows.Forms.Button(); 55 | this.SuspendLayout(); 56 | // 57 | // labelURL 58 | // 59 | this.labelURL.Location = new System.Drawing.Point(13, 13); 60 | this.labelURL.Name = "labelURL"; 61 | this.labelURL.Size = new System.Drawing.Size(84, 17); 62 | this.labelURL.TabIndex = 0; 63 | this.labelURL.Text = "KeyServer URL"; 64 | // 65 | // labelLogin 66 | // 67 | this.labelLogin.Location = new System.Drawing.Point(13, 39); 68 | this.labelLogin.Name = "labelLogin"; 69 | this.labelLogin.Size = new System.Drawing.Size(84, 17); 70 | this.labelLogin.TabIndex = 1; 71 | this.labelLogin.Text = "Login"; 72 | // 73 | // labelPassword 74 | // 75 | this.labelPassword.Location = new System.Drawing.Point(13, 65); 76 | this.labelPassword.Name = "labelPassword"; 77 | this.labelPassword.Size = new System.Drawing.Size(84, 17); 78 | this.labelPassword.TabIndex = 2; 79 | this.labelPassword.Text = "Password"; 80 | // 81 | // textBoxURL 82 | // 83 | this.textBoxURL.Location = new System.Drawing.Point(103, 10); 84 | this.textBoxURL.Name = "textBoxURL"; 85 | this.textBoxURL.Size = new System.Drawing.Size(242, 20); 86 | this.textBoxURL.TabIndex = 3; 87 | // 88 | // textBoxLogin 89 | // 90 | this.textBoxLogin.Location = new System.Drawing.Point(103, 39); 91 | this.textBoxLogin.Name = "textBoxLogin"; 92 | this.textBoxLogin.Size = new System.Drawing.Size(100, 20); 93 | this.textBoxLogin.TabIndex = 4; 94 | // 95 | // textBoxPassword 96 | // 97 | this.textBoxPassword.Location = new System.Drawing.Point(103, 66); 98 | this.textBoxPassword.Name = "textBoxPassword"; 99 | this.textBoxPassword.Size = new System.Drawing.Size(100, 20); 100 | this.textBoxPassword.TabIndex = 5; 101 | this.textBoxPassword.UseSystemPasswordChar = true; 102 | // 103 | // buttonOK 104 | // 105 | this.buttonOK.Location = new System.Drawing.Point(218, 103); 106 | this.buttonOK.Name = "buttonOK"; 107 | this.buttonOK.Size = new System.Drawing.Size(49, 23); 108 | this.buttonOK.TabIndex = 6; 109 | this.buttonOK.Text = "OK"; 110 | this.buttonOK.UseVisualStyleBackColor = true; 111 | this.buttonOK.Click += new System.EventHandler(this.Button1Click); 112 | // 113 | // buttonCancel 114 | // 115 | this.buttonCancel.Location = new System.Drawing.Point(273, 103); 116 | this.buttonCancel.Name = "buttonCancel"; 117 | this.buttonCancel.Size = new System.Drawing.Size(75, 23); 118 | this.buttonCancel.TabIndex = 7; 119 | this.buttonCancel.Text = "Cancel"; 120 | this.buttonCancel.UseVisualStyleBackColor = true; 121 | this.buttonCancel.Click += new System.EventHandler(this.Button2Click); 122 | // 123 | // ConfigWin 124 | // 125 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 126 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 127 | this.ClientSize = new System.Drawing.Size(360, 138); 128 | this.Controls.Add(this.buttonCancel); 129 | this.Controls.Add(this.buttonOK); 130 | this.Controls.Add(this.textBoxPassword); 131 | this.Controls.Add(this.textBoxLogin); 132 | this.Controls.Add(this.textBoxURL); 133 | this.Controls.Add(this.labelPassword); 134 | this.Controls.Add(this.labelLogin); 135 | this.Controls.Add(this.labelURL); 136 | this.Name = "ConfigWin"; 137 | this.Text = "KeyServer Configuration"; 138 | this.ResumeLayout(false); 139 | this.PerformLayout(); 140 | 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /KeyOnline/ConfigWin.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Created by SharpDevelop. 3 | * User: Patrice 4 | * Date: 04/06/2017 5 | * Time: 21:56 6 | * 7 | * To change this template use Tools | Options | Coding | Edit Standard Headers. 8 | */ 9 | using System; 10 | using System.Drawing; 11 | using System.Windows.Forms; 12 | 13 | using KeePass; 14 | using KeePass.Plugins; 15 | 16 | using KeyOnline; 17 | 18 | namespace KeyOnline.Forms 19 | { 20 | /// 21 | /// Description of ConfigWin. 22 | /// 23 | public partial class ConfigWin : Form 24 | { 25 | private IPluginHost m_host = null; 26 | 27 | // Constantes Fichier Config 28 | private string configBase; 29 | private string urlField; 30 | private string loginField; 31 | private string passwordField; 32 | 33 | public ConfigWin(IPluginHost host) 34 | { 35 | // 36 | // The InitializeComponent() call is required for Windows Forms designer support. 37 | // 38 | InitializeComponent(); 39 | 40 | m_host = host; 41 | 42 | // Constantes Fichier Config 43 | configBase = "KeyServer."; 44 | urlField = configBase + "url"; 45 | loginField = configBase + "login"; 46 | passwordField = configBase + "Password"; 47 | SecureString secPassword = new SecureString(); 48 | 49 | // Lecture des informations de configuration 50 | this.textBoxURL.Text = m_host.CustomConfig.GetString(urlField); 51 | this.textBoxLogin.Text = m_host.CustomConfig.GetString(loginField); 52 | secPassword.Encrypted = m_host.CustomConfig.GetString(passwordField); 53 | this.textBoxPassword.Text = secPassword.Decrypted; 54 | 55 | // 56 | // TODO: Add constructor code after the InitializeComponent() call. 57 | // 58 | } 59 | 60 | void Button1Click(object sender, EventArgs e) 61 | { // Bouton OK 62 | 63 | SecureString secPassword = new SecureString(); 64 | 65 | // Ecriture des informations de configuration 66 | m_host.CustomConfig.SetString(urlField,this.textBoxURL.Text); 67 | m_host.CustomConfig.SetString(loginField,this.textBoxLogin.Text); 68 | secPassword.Decrypted = this.textBoxPassword.Text; 69 | m_host.CustomConfig.SetString(passwordField,secPassword.Encrypted); 70 | 71 | // Fermeture de la fenêtre 72 | this.Close(); 73 | } 74 | 75 | void Button2Click(object sender, EventArgs e) 76 | { // Bouton Annuler 77 | this.Close(); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /KeyOnline/ConfigWin.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /KeyOnline/FingerPrint.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Code from : https://www.codeproject.com/Articles/28678/Generating-Unique-Key-Finger-Print-for-a-Computer 3 | 4 | Introduction 5 | For licensing purposes, according to me, the best and secure way is to generate a unique key 6 | for the client's machine and provide a corresponding license key for that key. For this purpose, 7 | you can take help of the unique id of the client's computer motherboard, BIOS and processor. 8 | When you get these IDs, you can generate any key of your preferable format. 9 | 10 | Year ago, I found a very handy and useful code in C# by searching the Internet to get these IDs. 11 | And it's serving me perfectly so far. Thanks to the original author of the code. 12 | 13 | I added some additional code to generate a 128 bit key of a machine. The output is a nice looking 14 | key in hexadecimal format (eg. 4876-8DB5-EE85-69D3-FE52-8CF7-395D-2EA9). 15 | 16 | Suggestions 17 | I have a few suggestions in this regard: 18 | 19 | Generate a key from only the Motherboard, Processor and BIOS since the user normally doesn't 20 | change these parts. 21 | Don't use MAC ID, Graphics Card ID AND Disk ID since it's very common to change these devices. 22 | It takes significant time to get IDs of devices. So make the finger print generating function 23 | static and save it in a static variable so that it generates the key only once in the whole application. 24 | */ 25 | 26 | using System; 27 | using System.Management; 28 | using System.Security.Cryptography; 29 | using System.Security; 30 | using System.Collections; 31 | using System.Text; 32 | 33 | namespace Security 34 | { 35 | /// 36 | /// Generates a 16 byte Unique Identification code of a computer 37 | /// Example: 4876-8DB5-EE85-69D3-FE52-8CF7-395D-2EA9 38 | /// 39 | public class FingerPrint 40 | { 41 | private static string fingerPrint = string.Empty; 42 | public string Value() 43 | { 44 | if (string.IsNullOrEmpty(fingerPrint)) 45 | { 46 | fingerPrint = GetHash("CPU >> " + cpuId() + "\nBIOS >> " + biosId() + "\nBASE >> " + baseId() 47 | +"\nDISK >> "+ diskId() + "\nVIDEO >> " + videoId() +"\nMAC >> "+ macId() 48 | ); 49 | // fingerPrint = "CPU >> " + cpuId() + "\nBIOS >> " + biosId() + "\nBASE >> " + baseId() 50 | // +"\nDISK >> "+ diskId() + "\nVIDEO >> " + videoId() +"\nMAC >> "+ macId(); 51 | } 52 | return fingerPrint; 53 | } 54 | private static string GetHash(string s) 55 | { 56 | MD5 sec = new MD5CryptoServiceProvider(); 57 | ASCIIEncoding enc = new ASCIIEncoding(); 58 | byte[] bt = enc.GetBytes(s); 59 | return GetHexString(sec.ComputeHash(bt)); 60 | } 61 | private static string GetHexString(byte[] bt) 62 | { 63 | string s = string.Empty; 64 | for (int i = 0; i < bt.Length; i++) 65 | { 66 | byte b = bt[i]; 67 | int n, n1, n2; 68 | n = (int)b; 69 | n1 = n & 15; 70 | n2 = (n >> 4) & 15; 71 | if (n2 > 9) 72 | s += ((char)(n2 - 10 + (int)'A')).ToString(); 73 | else 74 | s += n2.ToString(); 75 | if (n1 > 9) 76 | s += ((char)(n1 - 10 + (int)'A')).ToString(); 77 | else 78 | s += n1.ToString(); 79 | if ((i + 1) != bt.Length && (i + 1) % 2 == 0) s += "-"; 80 | } 81 | return s; 82 | } 83 | #region Original Device ID Getting Code 84 | //Return a hardware identifier 85 | private static string identifier(string wmiClass, string wmiProperty, string wmiMustBeTrue) 86 | { 87 | string result = ""; 88 | System.Management.ManagementClass mc = new System.Management.ManagementClass(wmiClass); 89 | System.Management.ManagementObjectCollection moc = mc.GetInstances(); 90 | foreach (System.Management.ManagementObject mo in moc) 91 | { 92 | if (mo[wmiMustBeTrue].ToString() == "True") 93 | { 94 | //Only get the first one 95 | if (result == "") 96 | { 97 | try 98 | { 99 | result = mo[wmiProperty].ToString(); 100 | break; 101 | } 102 | catch 103 | { 104 | } 105 | } 106 | } 107 | } 108 | return result; 109 | } 110 | //Return a hardware identifier 111 | private static string identifier(string wmiClass, string wmiProperty) 112 | { 113 | string result = ""; 114 | System.Management.ManagementClass mc = new System.Management.ManagementClass(wmiClass); 115 | System.Management.ManagementObjectCollection moc = mc.GetInstances(); 116 | foreach (System.Management.ManagementObject mo in moc) 117 | { 118 | //Only get the first one 119 | if (result == "") 120 | { 121 | try 122 | { 123 | result = mo[wmiProperty].ToString(); 124 | break; 125 | } 126 | catch 127 | { 128 | } 129 | } 130 | } 131 | return result; 132 | } 133 | private static string cpuId() 134 | { 135 | //Uses first CPU identifier available in order of preference 136 | //Don't get all identifiers, as very time consuming 137 | string retVal = identifier("Win32_Processor", "UniqueId"); 138 | if (retVal == "") //If no UniqueID, use ProcessorID 139 | { 140 | retVal = identifier("Win32_Processor", "ProcessorId"); 141 | if (retVal == "") //If no ProcessorId, use Name 142 | { 143 | retVal = identifier("Win32_Processor", "Name"); 144 | if (retVal == "") //If no Name, use Manufacturer 145 | { 146 | retVal = identifier("Win32_Processor", "Manufacturer"); 147 | } 148 | //Add clock speed for extra security 149 | retVal += identifier("Win32_Processor", "MaxClockSpeed"); 150 | } 151 | } 152 | return retVal; 153 | } 154 | //BIOS Identifier 155 | private static string biosId() 156 | { 157 | return identifier("Win32_BIOS", "Manufacturer") 158 | + identifier("Win32_BIOS", "SMBIOSBIOSVersion") 159 | + identifier("Win32_BIOS", "IdentificationCode") 160 | + identifier("Win32_BIOS", "SerialNumber") 161 | + identifier("Win32_BIOS", "ReleaseDate") 162 | + identifier("Win32_BIOS", "Version"); 163 | } 164 | //Main physical hard drive ID 165 | private static string diskId() 166 | { 167 | return identifier("Win32_DiskDrive", "Model") 168 | + identifier("Win32_DiskDrive", "Manufacturer") 169 | + identifier("Win32_DiskDrive", "Signature") 170 | + identifier("Win32_DiskDrive", "TotalHeads"); 171 | } 172 | //Motherboard ID 173 | private static string baseId() 174 | { 175 | return identifier("Win32_BaseBoard", "Model") 176 | + identifier("Win32_BaseBoard", "Manufacturer") 177 | + identifier("Win32_BaseBoard", "Name") 178 | + identifier("Win32_BaseBoard", "SerialNumber"); 179 | } 180 | //Primary video controller ID 181 | private static string videoId() 182 | { 183 | return identifier("Win32_VideoController", "DriverVersion") 184 | + identifier("Win32_VideoController", "Name"); 185 | } 186 | //First enabled network card ID 187 | private static string macId() 188 | { 189 | return identifier("Win32_NetworkAdapterConfiguration", "MACAddress", "IPEnabled"); 190 | } 191 | #endregion 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /KeyOnline/KeyOnline.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Created by SharpDevelop. 3 | * User: Patrice 4 | * Date: 28/05/2017 5 | * Time: 16:41 6 | * 7 | * To change this template use Tools | Options | Coding | Edit Standard Headers. 8 | */ 9 | using System; 10 | using System.IO; 11 | using System.Net; 12 | using System.Text; 13 | using System.Windows.Forms; 14 | //using System.Management; 15 | using Security; 16 | 17 | using KeePass.App; 18 | using KeePass.Plugins; 19 | using KeePassLib.Keys; 20 | 21 | using KeyOnline.Forms; 22 | 23 | namespace KeyOnline 24 | { 25 | public sealed class KeyOnlineExt : Plugin 26 | { 27 | private IPluginHost m_host = null; 28 | private KeyOnline m_provider = null; 29 | 30 | // Objects for menu items 31 | private ToolStripSeparator m_tsSeparator = null; 32 | private ToolStripMenuItem m_tsmiMenuItem = null; 33 | 34 | public override bool Initialize(IPluginHost host) 35 | { 36 | m_provider = new KeyOnline(host); 37 | m_host = host; 38 | 39 | // Add Key Provider 40 | m_host.KeyProviderPool.Add(m_provider); 41 | 42 | // Add "KeyServer Configuration" to the Tools menu 43 | AddConfigMenu(); 44 | 45 | return true; 46 | } 47 | 48 | public override void Terminate() 49 | { 50 | // Remove all of our menu items 51 | ToolStripItemCollection tsMenu = m_host.MainWindow.ToolsMenu.DropDownItems; 52 | m_tsmiMenuItem.Click -= this.OpenConfigForm; 53 | tsMenu.Remove(m_tsmiMenuItem); 54 | tsMenu.Remove(m_tsSeparator); 55 | 56 | // Remove KeyProvider 57 | m_host.KeyProviderPool.Remove(m_provider); 58 | } 59 | 60 | // Open KeyServer Configuration Form 61 | private void OpenConfigForm(object sender, EventArgs e) 62 | { 63 | ConfigWin ConfigForm = new ConfigWin(m_host); 64 | ConfigForm.ShowDialog(); 65 | } 66 | 67 | // Add "KeyServer Configuration" to the Tools menu 68 | private void AddConfigMenu() 69 | { 70 | // Get a reference to the 'Tools' menu item container 71 | ToolStripItemCollection tsMenu = m_host.MainWindow.ToolsMenu.DropDownItems; 72 | 73 | // Add a separator at the bottom 74 | m_tsSeparator = new ToolStripSeparator(); 75 | tsMenu.Add(m_tsSeparator); 76 | 77 | // Add menu item 78 | m_tsmiMenuItem = new ToolStripMenuItem(); 79 | m_tsmiMenuItem.Text = "Configure KeyServer"; 80 | m_tsmiMenuItem.Click += this.OpenConfigForm; 81 | tsMenu.Add(m_tsmiMenuItem); 82 | } 83 | } 84 | 85 | public sealed class KeyOnline : KeyProvider 86 | { 87 | private IPluginHost m_host = null; 88 | 89 | // Constants 90 | // Name of custom items in Keepass.config.xml 91 | const string configBase = "KeyServer."; 92 | const string urlField = configBase + "url"; 93 | const string loginField = configBase + "login"; 94 | const string passwordField = configBase + "Password"; 95 | 96 | // HarwareId generated during plugin initialization 97 | private string HardwareId = string.Empty; 98 | 99 | /// 100 | /// Init: Calculate hardwareid. 101 | /// 102 | public KeyOnline(IPluginHost host) 103 | { 104 | m_host = host; 105 | FingerPrint clFingerPrint = new FingerPrint(); 106 | HardwareId = clFingerPrint.Value(); 107 | } 108 | 109 | public override string Name 110 | { 111 | get { return "KeyOnline Key Provider"; } 112 | } 113 | 114 | public override byte[] GetKey(KeyProviderQueryContext ctx) 115 | { 116 | //Apply Policy restrictions. 117 | PolicyApply(); 118 | 119 | SecureString secPassword = new SecureString(); 120 | 121 | // Reads config values for Keepass.config.xml 122 | string ksURL = m_host.CustomConfig.GetString(urlField); 123 | string ksLogin = m_host.CustomConfig.GetString(loginField); 124 | string ksPassword = m_host.CustomConfig.GetString(passwordField); 125 | 126 | // Open config window if a parameter is missing 127 | if ((ksURL == null) || (ksLogin == null) || (ksPassword == null)) 128 | { 129 | ConfigWin ConfigForm = new ConfigWin(m_host); 130 | ConfigForm.ShowDialog(); 131 | 132 | ksURL = m_host.CustomConfig.GetString(urlField); 133 | ksLogin = m_host.CustomConfig.GetString(loginField); 134 | ksPassword = m_host.CustomConfig.GetString(passwordField); 135 | } 136 | 137 | // Open Debug Window 138 | StatusWin StatusForm = new StatusWin(); 139 | StatusForm.Show(); 140 | 141 | // Create Webservice object 142 | StatusForm.StatusLog.Text = "Invoking Web Service..."; 143 | KeyServerWS.Soap ksws = new KeyServerWS.Soap(); 144 | // Use URL from Keepass.config.xml 145 | ksws.Url = ksURL; 146 | StatusForm.StatusLog.AppendText("Done\r\n"); 147 | 148 | // Retrieve database filename 149 | string dbFilename = Path.GetFileName(ctx.DatabasePath); 150 | StatusForm.StatusLog.AppendText("Querying key with parameters :\r\n"); 151 | StatusForm.StatusLog.AppendText(String.Format(" - FileName : {0}\r\n",dbFilename)); 152 | StatusForm.StatusLog.AppendText(String.Format(" - UserName : {0}\r\n",ksLogin)); 153 | StatusForm.StatusLog.AppendText(String.Format(" - HadwareId : {0}\r\n",HardwareId)); 154 | 155 | string dbKey = null; 156 | try { 157 | secPassword.Encrypted = ksPassword; 158 | NetworkCredential ksCreds = new NetworkCredential(); 159 | ksCreds.UserName = ksLogin; 160 | ksCreds.Password = secPassword.Decrypted; 161 | ksws.Credentials = ksCreds; 162 | dbKey = ksws.GetKey(dbFilename,ksLogin,HardwareId); 163 | StatusForm.StatusLog.AppendText("Done\r\n"); 164 | StatusForm.StatusLog.AppendText(String.Format("Key Found : {0}\r\n",dbKey)); 165 | } catch (Exception) { 166 | MessageBox.Show("Connection Error...\r\nCheck configuration.\r\n(Tools / Configure KeyServer)"); 167 | StatusForm.Close(); 168 | return null; 169 | } 170 | 171 | if (dbKey == String.Empty) 172 | { 173 | MessageBox.Show("Error : Access denied or database not found"); 174 | StatusForm.Close(); 175 | return null; 176 | } 177 | 178 | return Encoding.ASCII.GetBytes(dbKey); 179 | } 180 | 181 | // Apply restricted Plugin Policy 182 | private void PolicyApply() 183 | { 184 | KeePass.App.AppPolicy.Current.ChangeMasterKey = false; 185 | KeePass.App.AppPolicy.Current.ChangeMasterKeyNoKey = false; 186 | KeePass.App.AppPolicy.Current.Export = false; 187 | KeePass.App.AppPolicy.Current.ExportNoKey = false; 188 | KeePass.App.AppPolicy.Current.Print = false; 189 | KeePass.App.AppPolicy.Current.PrintNoKey = false; 190 | KeePass.App.AppPolicy.Current.UnhidePasswords = false; 191 | KeePass.App.AppPolicy.Current.EditTriggers = false; 192 | KeePass.App.AppPolicy.Current.CopyWholeEntries = false; 193 | 194 | EventHandler ehEditEntryOpen = delegate(object sender, KeePass.UI.GwmWindowEventArgs e) 195 | { 196 | if (e.Form.Name=="PwEntryForm") { KeePass.App.AppPolicy.Current.UnhidePasswords = true; } 197 | }; 198 | KeePass.UI.GlobalWindowManager.WindowAdded += ehEditEntryOpen; 199 | EventHandler ehEditEntryClose = delegate(object sender, KeePass.UI.GwmWindowEventArgs e) 200 | { 201 | if (e.Form.Name=="PwEntryForm") { KeePass.App.AppPolicy.Current.UnhidePasswords = false; } 202 | }; 203 | KeePass.UI.GlobalWindowManager.WindowRemoved += ehEditEntryClose; 204 | } 205 | 206 | } 207 | } 208 | 209 | -------------------------------------------------------------------------------- /KeyOnline/KeyOnline.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | {AB7F26CB-B578-4521-86ED-43875F238870} 5 | {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 6 | Debug 7 | AnyCPU 8 | Library 9 | KeyOnline 10 | KeyOnline 11 | v2.0 12 | Properties 13 | False 14 | False 15 | False 16 | 17 | 18 | 19 | AnyCPU 20 | 21 | 22 | bin\Debug\ 23 | True 24 | Full 25 | False 26 | True 27 | DEBUG;TRACE 28 | 29 | 30 | bin\Release\ 31 | False 32 | None 33 | True 34 | False 35 | TRACE 36 | 37 | 38 | 39 | ..\..\Build\KeePass\Debug\KeePass.exe 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | ConfigWin.cs 54 | 55 | 56 | 57 | 58 | 59 | 60 | StatusWin.cs 61 | 62 | 63 | True 64 | True 65 | Reference.map 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | ConfigWin.cs 74 | 75 | 76 | StatusWin.cs 77 | 78 | 79 | 80 | 81 | Static 82 | http://localhost/Default.asmx 83 | Web References\KeyServerWS 84 | KeyOnline.KeyServerWS 85 | 86 | 87 | 88 | 89 | 90 | 91 | MSDiscoCodeGenerator 92 | Reference.cs 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /KeyOnline/KeyOnline.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | # SharpDevelop 5.1 5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeyOnline", "KeyOnline.csproj", "{AB7F26CB-B578-4521-86ED-43875F238870}" 6 | EndProject 7 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeyOnlineWS", "..\KeyOnlineWS\KeyOnlineWS.csproj", "{05209D0D-79DC-4F13-8E3D-C64946AFCE46}" 8 | EndProject 9 | Global 10 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 11 | Debug|Any CPU = Debug|Any CPU 12 | Release|Any CPU = Release|Any CPU 13 | EndGlobalSection 14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 15 | {AB7F26CB-B578-4521-86ED-43875F238870}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 16 | {AB7F26CB-B578-4521-86ED-43875F238870}.Debug|Any CPU.Build.0 = Debug|Any CPU 17 | {AB7F26CB-B578-4521-86ED-43875F238870}.Release|Any CPU.ActiveCfg = Release|Any CPU 18 | {AB7F26CB-B578-4521-86ED-43875F238870}.Release|Any CPU.Build.0 = Release|Any CPU 19 | {05209D0D-79DC-4F13-8E3D-C64946AFCE46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 20 | {05209D0D-79DC-4F13-8E3D-C64946AFCE46}.Debug|Any CPU.Build.0 = Debug|Any CPU 21 | {05209D0D-79DC-4F13-8E3D-C64946AFCE46}.Release|Any CPU.ActiveCfg = Release|Any CPU 22 | {05209D0D-79DC-4F13-8E3D-C64946AFCE46}.Release|Any CPU.Build.0 = Release|Any CPU 23 | EndGlobalSection 24 | EndGlobal 25 | -------------------------------------------------------------------------------- /KeyOnline/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | #region Using directives 2 | using System; 3 | using System.Reflection; 4 | using System.Runtime.InteropServices; 5 | 6 | #endregion 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle ("KeyOnline")] 11 | [assembly: AssemblyDescription ("Securely grab database keys online")] 12 | [assembly: AssemblyConfiguration ("")] 13 | [assembly: AssemblyCompany ("Patrice LE TEXIER")] 14 | [assembly: AssemblyProduct ("KeePass Plugin")] 15 | [assembly: AssemblyCopyright ("Copyright 2017")] 16 | [assembly: AssemblyTrademark ("")] 17 | [assembly: AssemblyCulture ("")] 18 | // This sets the default COM visibility of types in the assembly to invisible. 19 | // If you need to expose a type to COM, use [ComVisible(true)] on that type. 20 | [assembly: ComVisible (false)] 21 | // The assembly version has following format : 22 | // 23 | // Major.Minor.Build.Revision 24 | // 25 | // You can specify all the values or you can use the default the Revision and 26 | // Build Numbers by using the '*' as shown below: 27 | [assembly: AssemblyVersion ("1.0.*")] 28 | -------------------------------------------------------------------------------- /KeyOnline/README.md: -------------------------------------------------------------------------------- 1 | # Client part 2 | 3 | This is the client part. This plugin is installed in Keepass. 4 | -------------------------------------------------------------------------------- /KeyOnline/StatusWin.Designer.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Created by SharpDevelop. 3 | * User: Patrice 4 | * Date: 31/05/2017 5 | * Time: 21:42 6 | * 7 | * To change this template use Tools | Options | Coding | Edit Standard Headers. 8 | */ 9 | namespace KeyOnline 10 | { 11 | partial class StatusWin 12 | { 13 | /// 14 | /// Designer variable used to keep track of non-visual components. 15 | /// 16 | private System.ComponentModel.IContainer components = null; 17 | public System.Windows.Forms.TextBox StatusLog; 18 | 19 | /// 20 | /// Disposes resources used by the form. 21 | /// 22 | /// true if managed resources should be disposed; otherwise, false. 23 | protected override void Dispose(bool disposing) 24 | { 25 | if (disposing) { 26 | if (components != null) { 27 | components.Dispose(); 28 | } 29 | } 30 | base.Dispose(disposing); 31 | } 32 | 33 | /// 34 | /// This method is required for Windows Forms designer support. 35 | /// Do not change the method contents inside the source code editor. The Forms designer might 36 | /// not be able to load this method if it was changed manually. 37 | /// 38 | private void InitializeComponent() 39 | { 40 | this.StatusLog = new System.Windows.Forms.TextBox(); 41 | this.SuspendLayout(); 42 | // 43 | // StatusLog 44 | // 45 | this.StatusLog.Location = new System.Drawing.Point(12, 12); 46 | this.StatusLog.Multiline = true; 47 | this.StatusLog.Name = "StatusLog"; 48 | this.StatusLog.Size = new System.Drawing.Size(313, 116); 49 | this.StatusLog.TabIndex = 0; 50 | this.StatusLog.TextChanged += new System.EventHandler(this.TextBox1TextChanged); 51 | // 52 | // StatusWin 53 | // 54 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 55 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 56 | this.ClientSize = new System.Drawing.Size(337, 140); 57 | this.Controls.Add(this.StatusLog); 58 | this.Name = "StatusWin"; 59 | this.Text = "StatusWin"; 60 | this.ResumeLayout(false); 61 | this.PerformLayout(); 62 | 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /KeyOnline/StatusWin.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Created by SharpDevelop. 3 | * User: Patrice 4 | * Date: 31/05/2017 5 | * Time: 21:42 6 | * 7 | * To change this template use Tools | Options | Coding | Edit Standard Headers. 8 | */ 9 | using System; 10 | using System.Drawing; 11 | using System.Windows.Forms; 12 | 13 | namespace KeyOnline 14 | { 15 | /// 16 | /// Description of StatusWin. 17 | /// 18 | public partial class StatusWin : Form 19 | { 20 | public StatusWin() 21 | { 22 | // 23 | // The InitializeComponent() call is required for Windows Forms designer support. 24 | // 25 | InitializeComponent(); 26 | 27 | // 28 | // TODO: Add constructor code after the InitializeComponent() call. 29 | // 30 | } 31 | void TextBox1TextChanged(object sender, EventArgs e) 32 | { 33 | 34 | } 35 | void StatusOkClick(object sender, EventArgs e) 36 | { 37 | 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /KeyOnline/StatusWin.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /KeyOnline/Toolbox.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Created by SharpDevelop. 3 | * User: Patrice 4 | * Date: 10/06/2017 5 | * Time: 10:30 6 | * 7 | * To change this template use Tools | Options | Coding | Edit Standard Headers. 8 | */ 9 | using System; 10 | using System.Text; 11 | using System.Security.Cryptography; 12 | 13 | namespace KeyOnline 14 | { 15 | public class SecureString 16 | { 17 | /// 18 | /// Entropy byte array for data encryption 19 | /// 20 | private byte[] EncryptEntropy = { 1, 2, 3, 5, 7, 11, 13, 17 }; 21 | private string EncryptedValue = string.Empty; 22 | 23 | /// 24 | /// Function EncryptStringLocalUser 25 | /// Encrypts a string using local user information 26 | /// 27 | 28 | public string Encrypted 29 | { 30 | get { return this.EncryptedValue; } 31 | set { this.EncryptedValue = value; } 32 | } 33 | 34 | public string Decrypted 35 | { 36 | get { return this.Decrypt(this.EncryptedValue); } 37 | set { this.EncryptedValue = this.Encrypt(value); } 38 | } 39 | 40 | private string Encrypt(string inputstr) 41 | { 42 | // Convert password to UTF8 byte array; 43 | byte[] PasswordDecrypted = Encoding.UTF8.GetBytes(inputstr); 44 | // Encrypt Password using local user informations 45 | byte[] PasswordEncrypted = ProtectedData.Protect(PasswordDecrypted,EncryptEntropy,DataProtectionScope.CurrentUser); 46 | // Clear decrypted password array for security 47 | Array.Clear(PasswordDecrypted,0,PasswordDecrypted.Length); 48 | // Convert Encrypted Password to Base64 for easy storage 49 | string PasswordFinal = Convert.ToBase64String(PasswordEncrypted); 50 | // Clear Encrypted Password array for security 51 | Array.Clear(PasswordEncrypted,0,PasswordEncrypted.Length); 52 | 53 | return PasswordFinal; 54 | } 55 | 56 | /// 57 | /// Function DecryptStringLocalUser 58 | /// Decrypts a string using local user information 59 | /// 60 | private string Decrypt(string inputstr) 61 | { 62 | // Convert Password to byte array 63 | byte[] PasswordEncrypted = Convert.FromBase64String(inputstr); 64 | // Decrypt Password using local user informations 65 | byte[] PasswordDecrypted = ProtectedData.Unprotect(PasswordEncrypted,EncryptEntropy,DataProtectionScope.CurrentUser); 66 | // Clear PasswordEncrypted for security 67 | Array.Clear(PasswordEncrypted,0,PasswordEncrypted.Length); 68 | // Convert password to UTF8 string 69 | string PasswordFinal = Encoding.UTF8.GetString(PasswordDecrypted); 70 | // Clear PasswordDecrypted for security 71 | Array.Clear(PasswordDecrypted,0,PasswordDecrypted.Length); 72 | 73 | return PasswordFinal; 74 | } 75 | 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /KeyOnline/Web References/KeyServerWS/Default.disco: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /KeyOnline/Web References/KeyServerWS/Default.wsdl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /KeyOnline/Web References/KeyServerWS/Reference.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace KeyOnline.KeyServerWS { 12 | using System; 13 | using System.Web.Services; 14 | using System.Diagnostics; 15 | using System.Web.Services.Protocols; 16 | //using System.Xml.Serialization; 17 | using System.ComponentModel; 18 | 19 | 20 | /// 21 | [System.CodeDom.Compiler.GeneratedCodeAttribute("SharpDevelop", "5.1.0.5216-0e58df71")] 22 | [System.Diagnostics.DebuggerStepThroughAttribute()] 23 | [System.ComponentModel.DesignerCategoryAttribute("code")] 24 | [System.Web.Services.WebServiceBindingAttribute(Name="SoapSoap", Namespace="http://tempuri.org/")] 25 | public partial class Soap : System.Web.Services.Protocols.SoapHttpClientProtocol { 26 | 27 | /// 28 | public Soap() { 29 | this.Url = "http://localhost/Default.asmx"; 30 | } 31 | 32 | /// 33 | [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/Login", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] 34 | public bool Login(string userName, string password) { 35 | object[] results = this.Invoke("Login", new object[] { 36 | userName, 37 | password}); 38 | return ((bool)(results[0])); 39 | } 40 | 41 | /// 42 | public System.IAsyncResult BeginLogin(string userName, string password, System.AsyncCallback callback, object asyncState) { 43 | return this.BeginInvoke("Login", new object[] { 44 | userName, 45 | password}, callback, asyncState); 46 | } 47 | 48 | /// 49 | public bool EndLogin(System.IAsyncResult asyncResult) { 50 | object[] results = this.EndInvoke(asyncResult); 51 | return ((bool)(results[0])); 52 | } 53 | 54 | /// 55 | [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/Logout", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] 56 | public void Logout() { 57 | this.Invoke("Logout", new object[0]); 58 | } 59 | 60 | /// 61 | public System.IAsyncResult BeginLogout(System.AsyncCallback callback, object asyncState) { 62 | return this.BeginInvoke("Logout", new object[0], callback, asyncState); 63 | } 64 | 65 | /// 66 | public void EndLogout(System.IAsyncResult asyncResult) { 67 | this.EndInvoke(asyncResult); 68 | } 69 | 70 | /// 71 | [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/GetKey", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] 72 | public string GetKey(string db, string username, string hardwareid) { 73 | object[] results = this.Invoke("GetKey", new object[] { 74 | db, 75 | username, 76 | hardwareid}); 77 | return ((string)(results[0])); 78 | } 79 | 80 | /// 81 | public System.IAsyncResult BeginGetKey(string db, string username, string hardwareid, System.AsyncCallback callback, object asyncState) { 82 | return this.BeginInvoke("GetKey", new object[] { 83 | db, 84 | username, 85 | hardwareid}, callback, asyncState); 86 | } 87 | 88 | /// 89 | public string EndGetKey(System.IAsyncResult asyncResult) { 90 | object[] results = this.EndInvoke(asyncResult); 91 | return ((string)(results[0])); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /KeyOnline/Web References/KeyServerWS/Reference.map: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /KeyServer/Default.asmx: -------------------------------------------------------------------------------- 1 | <%@ WebService Language="C#" Class="KeyServer.Soap" %> -------------------------------------------------------------------------------- /KeyServer/KeyServer.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | {33B9B663-FC0E-4E7D-A1FB-79841C8428E2} 5 | {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} 6 | Debug 7 | AnyCPU 8 | Library 9 | KeyServer 10 | KeyServer 11 | Properties 12 | 13 | 14 | AnyCPU 15 | 16 | 17 | bin\ 18 | True 19 | Full 20 | False 21 | True 22 | DEBUG;TRACE 23 | 24 | 25 | bin\ 26 | False 27 | None 28 | True 29 | False 30 | TRACE 31 | 32 | 33 | 34 | 4.0 35 | 36 | 37 | 38 | 3.5 39 | 40 | 41 | 42 | 3.5 43 | 44 | 45 | 46 | 47 | 48 | 49 | 3.5 50 | 51 | 52 | 53 | 54 | 55 | Default.asmx 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /KeyServer/Keys.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | Db1.db 20 | AZERTYUIOP 21 | 22 | 23 | NewDatabase.kdbx 24 | 44444444 25 | 26 | -------------------------------------------------------------------------------- /KeyServer/Permissions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | NewDatabase.kdbx 21 | VM-Win7\Patrice 22 | 94E4-DD7F-BFB0-502C-10DD-8453-B122-7D34 23 | 24 | 25 | NewDatabase.kdbx 26 | User2 27 | 94E4-DD7F-BFB0-502C-10DD-8453-B122-7D34 28 | 29 | -------------------------------------------------------------------------------- /KeyServer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | #region Using directives 2 | 3 | using System; 4 | using System.Reflection; 5 | using System.Runtime.InteropServices; 6 | 7 | #endregion 8 | 9 | // General Information about an assembly is controlled through the following 10 | // set of attributes. Change these attribute values to modify the information 11 | // associated with an assembly. 12 | [assembly: AssemblyTitle("KeyServer")] 13 | [assembly: AssemblyDescription("")] 14 | [assembly: AssemblyConfiguration("")] 15 | [assembly: AssemblyCompany("")] 16 | [assembly: AssemblyProduct("KeyServer")] 17 | [assembly: AssemblyCopyright("Copyright 2017")] 18 | [assembly: AssemblyTrademark("")] 19 | [assembly: AssemblyCulture("")] 20 | 21 | // This sets the default COM visibility of types in the assembly to invisible. 22 | // If you need to expose a type to COM, use [ComVisible(true)] on that type. 23 | [assembly: ComVisible(false)] 24 | 25 | // The assembly version has following format : 26 | // 27 | // Major.Minor.Build.Revision 28 | // 29 | // You can specify all the values or you can use the default the Revision and 30 | // Build Numbers by using the '*' as shown below: 31 | [assembly: AssemblyVersion("1.0.*")] 32 | -------------------------------------------------------------------------------- /KeyServer/README.md: -------------------------------------------------------------------------------- 1 | # Server part 2 | 3 | This is the server part. This part is hosted on a web server, and is used to authenticate the user and the device trying to open a protected database. 4 | 5 | For testing purpose, i run this part on Cassini Web Server. 6 | (https://cassinidev.codeplex.com/) 7 | I use it with the following parameters : 8 | - Physical Path = root of KeyServer folder 9 | - VirtualPath = / 10 | - Port = Specific / 80 11 | - HostName = (empty) 12 | - Options : NTLM Authentication Required 13 | 14 | The file "Permissions.xml" contains hardwareid and usernames allowed to access a database. 15 | The file "Keys.xml" contains database names and keys. 16 | The file "Requests.xml" logs keys requests. 17 | 18 | # THIS CODE IS ONLY FOR TESTING PURPOSES. 19 | # DO NOT USE PRODUCTION DATA. 20 | -------------------------------------------------------------------------------- /KeyServer/Requests.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | NewDatabase.kdbx 21 | VM-Win7\Patrice 22 | 94E4-DD7F-BFB0-502C-10DD-8453-B122-7D34 23 | 24 | -------------------------------------------------------------------------------- /KeyServer/Soap.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Created by SharpDevelop. 3 | * User: Patrice 4 | * Date: 31/05/2017 5 | * Time: 19:48 6 | * 7 | * To change this template use Tools | Options | Coding | Edit Standard Headers. 8 | */ 9 | using System; 10 | using System.Data; 11 | using System.IO; 12 | using System.Web; 13 | using System.Web.Services; 14 | using System.Web.Services.Protocols; 15 | 16 | namespace KeyServer 17 | { 18 | [WebService] 19 | public class Soap : System.Web.Services.WebService 20 | { 21 | // Path of XML files 22 | const string XmlPath = @"C:\@Almeria\KeePass\KeyOnline\KeyServer\"; 23 | 24 | /// 25 | /// Logs into the web service 26 | /// 27 | /// The User Name to login in as 28 | /// User's password 29 | /// True on successful login. 30 | // [WebMethod(EnableSession=true)] 31 | // public bool Login(string userName, string password) 32 | // { 33 | // //NOTE: There are better ways of doing authentication. This is just illustrates Session usage. 34 | // UserName = userName; 35 | // return true; 36 | // } 37 | 38 | /// 39 | /// Logs out of the Session. 40 | /// 41 | // [WebMethod(EnableSession=true)] 42 | // public void Logout() 43 | // { 44 | // Context.Session.Abandon(); 45 | // } 46 | 47 | /// 48 | /// Main Method 49 | /// Check permissions and return key. 50 | /// 51 | [WebMethod(EnableSession=true)] 52 | public string GetKey(string db, string hardwareid) 53 | { 54 | // Log request 55 | DataTable RequestLog = CreateLogTable(); 56 | DataRow RequestLogRow; 57 | 58 | RequestLogRow = RequestLog.NewRow(); 59 | RequestLogRow["db"] = db; 60 | RequestLogRow["user"] = UserName; 61 | RequestLogRow["hardwareid"] = hardwareid; 62 | RequestLog.Rows.Add(RequestLogRow); 63 | 64 | string RequestLogPath = XmlPath + "Requests.xml"; 65 | FileStream RequestLogStream = File.Create(RequestLogPath); 66 | RequestLog.WriteXml(RequestLogStream,XmlWriteMode.WriteSchema); 67 | RequestLogStream.Close(); 68 | 69 | // Check permission in permission.xml 70 | if (CheckPermission(db,UserName,hardwareid)) 71 | { 72 | return GetDbKey(db); 73 | } 74 | else 75 | { 76 | return string.Empty; 77 | } 78 | } 79 | 80 | /// 81 | /// UserName of the logged in user. 82 | /// 83 | private string UserName { 84 | get {return (string)User.Identity.Name;} 85 | //get {return (string)Context.Session["User"];} 86 | //set {Context.Session["User"] = value;} 87 | } 88 | 89 | /// 90 | /// Returns the key of the specified db 91 | /// 92 | private string GetDbKey(string db) 93 | { 94 | DataTable DbKeys = new DataTable(); 95 | string Key = string.Empty; 96 | DbKeys.ReadXml(XmlPath + "Keys.xml"); 97 | 98 | DataRow[] foundRows = DbKeys.Select("db = '" + db + "'"); 99 | if ( foundRows.Length > 0 ) 100 | { 101 | Key = (string)foundRows[0][1]; 102 | } 103 | return Key; 104 | } 105 | 106 | /// 107 | /// Checks if the specified user and hardwareid is allowed to open the specified db. 108 | /// Returns true when a result is found. 109 | /// 110 | private Boolean CheckPermission(string db, string username, string hardwareid) 111 | { 112 | DataTable Permissions = new DataTable(); 113 | Permissions.ReadXml(XmlPath + "Permissions.xml"); 114 | 115 | DataRow[] foundRows; 116 | foundRows = Permissions.Select("db = '" + db + "' AND user='" + username + "' AND hardwareid = '" + hardwareid + "'"); 117 | 118 | return (foundRows.Length > 0); 119 | } 120 | 121 | /// 122 | /// Returns a DataTable to log requests 123 | /// Columns : 124 | /// - db = Filename (ex : mypasswords.kdbx) 125 | /// - user = username 126 | /// - hardwareid = 16 byte Unique Identification code of a computer 127 | /// Example: 4876-8DB5-EE85-69D3-FE52-8CF7-395D-2EA9 128 | /// 129 | private DataTable CreateLogTable() 130 | { 131 | DataTable RequestLog = new DataTable("RequestLog"); 132 | DataColumn column; 133 | 134 | column = new DataColumn(); 135 | column.DataType = Type.GetType("System.String"); 136 | column.ColumnName = "db"; 137 | RequestLog.Columns.Add(column); 138 | 139 | column = new DataColumn(); 140 | column.DataType = Type.GetType("System.String"); 141 | column.ColumnName = "user"; 142 | RequestLog.Columns.Add(column); 143 | 144 | column = new DataColumn(); 145 | column.DataType = Type.GetType("System.String"); 146 | column.ColumnName = "hardwareid"; 147 | RequestLog.Columns.Add(column); 148 | 149 | return RequestLog; 150 | } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /KeyServer/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 12 | 13 | 18 | 19 | 31 | 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # KeePassKeyServer 2 | 3 | Keepass-KeyServer is a key provider plugin for KeePass. 4 | 5 | # NOT FOR PRODUCTION USE 6 | # DO NOT USE WITH SENSITIVE DATA 7 | 8 | The goal is to manage database access over the internet, using a remote "key server". 9 | 10 | I'm working with a team of technicians, which copy password databases on their laptop. 11 | I want to control the diffusion of such informations, and eventualy revoke access to a database. 12 | (if a technician leaves the company for example). 13 | 14 | The plugin will send informations to the key server to authenticate : 15 | - the computer (using a hardware id) 16 | - the user (using a username / password) 17 | - the location ? (using ip address of the client) 18 | 19 | The plugin could also check : 20 | - keepass and plugin version (using certificate thumbprint of keepass and plugin executables for example ?) 21 | - if a validated keepass policy is enforced, to disable features like changing the master key, export and synchronisation features, triggers, ... 22 | --------------------------------------------------------------------------------