Skip to content

Commit

Permalink
Implemented password changing for Linux hosts.
Browse files Browse the repository at this point in the history
  • Loading branch information
cristianst85 committed Sep 12, 2016
1 parent 8947e4a commit 76dc967
Show file tree
Hide file tree
Showing 16 changed files with 163 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using NUnit.Framework;
using QuickConnectPlugin.PasswordChanger;

namespace QuickConnectPlugin.Tests.PasswordChanger {

[Ignore("IntegrationTest")]
[TestFixture]
public class LinuxPasswordChangerTests {

[TestCase("opensuse13.1", "root", "12345678", Description = "openSUSE 13.1")]
public void ChangePassword(String ipAddress, String username, String password) {
var linuxPasswordChanger = new LinuxPasswordChanger();
Assert.DoesNotThrow(() => linuxPasswordChanger.ChangePassword(ipAddress, username, password, password));
}
}
}
14 changes: 7 additions & 7 deletions QuickConnectPlugin.Tests/QuickConnectPlugin.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
<Compile Include="PasswordChanger\BatchPasswordChangerWorkerTests.cs" />
<Compile Include="PasswordChanger\HostTypeSafeConverterTests.cs" />
<Compile Include="PasswordChanger\ESXiPasswordChangerTests.cs" />
<Compile Include="PasswordChanger\LinuxPasswordChangerTests.cs" />
<Compile Include="PasswordChanger\MockPasswordChangerFactory.cs" />
<Compile Include="PasswordChanger\HostTypeConverterTests.cs" />
<Compile Include="PasswordChanger\MockPasswordChanger.cs" />
Expand All @@ -92,19 +93,18 @@
<Compile Include="PasswordChanger\Services\PasswordChangerServiceTests.cs" />
<Compile Include="Services\WindowsRegistryServiceTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\QuickConnectPlugin\QuickConnectPlugin.csproj">
<Project>{6027B153-E1DA-4272-9F9D-D870C27DB630}</Project>
<Name>QuickConnectPlugin</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<ProjectReference Include="..\QuickConnectPlugin\QuickConnectPlugin.csproj">
<Project>{6027B153-E1DA-4272-9F9D-D870C27DB630}</Project>
<Name>QuickConnectPlugin</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
Expand Down
15 changes: 15 additions & 0 deletions QuickConnectPlugin/Commons/AssemblyUtils.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Reflection;
using System.Resources;

namespace QuickConnectPlugin.Commons {

Expand Down Expand Up @@ -37,6 +38,20 @@ public static Assembly AssemblyResolver(object sender, ResolveEventArgs args) {
return null;
}

public static Assembly AssemblyResolverFromResources(object sender, ResolveEventArgs args) {
string resourceName = new AssemblyName(args.Name).Name.Replace(".", "_").Replace("-", "_");
if (resourceName.EndsWith("_resources")) {
return null;
}
var baseAssembly = System.Reflection.Assembly.GetCallingAssembly();
ResourceManager resourceManager = new System.Resources.ResourceManager(baseAssembly.GetName().Name + ".Properties.Resources", baseAssembly);
byte[] resourceData = (byte[])resourceManager.GetObject(resourceName);
if (resourceData != null) {
return Assembly.Load(resourceData);
}
return null;
}

public static String GetExecutingAssemblyName() {
return System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
}
Expand Down
4 changes: 2 additions & 2 deletions QuickConnectPlugin/FormAbout.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion QuickConnectPlugin/FormAbout.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public FormAbout() {
this.richTextBoxCopyright.LinkClicked += new LinkClickedEventHandler(richTextBoxCopyright_LinkClicked);
this.linkLabelContact.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabelContact_LinkClicked);
this.linkLabelSource.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabelSource_LinkClicked);

this.richTextBoxCopyright.Text = this.richTextBoxCopyright.Text.Replace("{sshNetLibVersion}", AssemblyUtils.GetVersion("Renci.SshNet").ToString());
}

[Conditional("DEBUG")]
Expand Down
10 changes: 10 additions & 0 deletions QuickConnectPlugin/FormAbout.resx
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,14 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="richTextBoxCopyright.Text" xml:space="preserve">
<value>Menu items icons from Crystal Clear icon set
Copyright (c) Everaldo Coelho, http://www.everaldo.com/
License: GNU Lesser General Public License v2.1 or later.

SSH.NET library v{sshNetLibVersion}
Copyright (c) 2012-2016, RENCI. All rights reserved.
https://github.com/sshnet/SSH.NET
License: MIT License.</value>
</data>
</root>
46 changes: 46 additions & 0 deletions QuickConnectPlugin/PasswordChanger/LinuxPasswordChanger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;
using System.IO;
using Renci.SshNet;
using Renci.SshNet.Common;

namespace QuickConnectPlugin.PasswordChanger {

public class LinuxPasswordChanger : IPasswordChanger {

public void ChangePassword(string host, string username, string password, string newPassword) {
KeyboardInteractiveAuthenticationMethod authMethod = new KeyboardInteractiveAuthenticationMethod(username);
authMethod.AuthenticationPrompt += new EventHandler<AuthenticationPromptEventArgs>((sender, e) => authenticationPrompted(sender, e, password));

ConnectionInfo connectionInfo = new ConnectionInfo(host, username, authMethod);

using (SshClient sshclient = new SshClient(connectionInfo)) {
sshclient.Connect();
using (var shellStream = sshclient.CreateShellStream("xterm", 80, 24, 800, 600, 1024)) {
using (var writer = new StreamWriter(shellStream) { AutoFlush = true }) {
writer.WriteLine("sudo passwd");
processShellStream(shellStream, "New Password");
writer.WriteLine(newPassword);
processShellStream(shellStream, "Reenter New Password");
writer.WriteLine(newPassword);
processShellStream(shellStream, "Password changed.");
}
}
}
}

private void processShellStream(ShellStream shellStream, String expectedString) {
var res = shellStream.Expect(expectedString, TimeSpan.FromSeconds(2));
if (res == null) {
throw new Exception(String.Format("Error changing password. Expected '{0}' string from shell, but got null.", expectedString));
}
}

private void authenticationPrompted(object sender, AuthenticationPromptEventArgs e, String password) {
foreach (AuthenticationPrompt prompt in e.Prompts) {
if (prompt.Request.StartsWith("Password:", StringComparison.InvariantCultureIgnoreCase)) {
prompt.Response = password;
}
}
}
}
}
11 changes: 11 additions & 0 deletions QuickConnectPlugin/PasswordChanger/LinuxPasswordChangerFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;

namespace QuickConnectPlugin.PasswordChanger {

public class LinuxPasswordChangerFactory : IPasswordChangerGenericFactory<IPasswordChanger> {

public IPasswordChanger Create() {
return new LinuxPasswordChanger();
}
}
}
10 changes: 10 additions & 0 deletions QuickConnectPlugin/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions QuickConnectPlugin/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@
<value>..\Resources\1454812927_remote.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="Renci_SshNet" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Renci.SshNet.dll;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="success" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\1472349739_agt_action_success.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
Expand Down
10 changes: 9 additions & 1 deletion QuickConnectPlugin/QuickConnectPlugin.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>QuickConnectPlugin</RootNamespace>
<AssemblyName>QuickConnectPlugin</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
Expand All @@ -37,6 +38,10 @@
<ExecutableExtension>.exe</ExecutableExtension>
<HintPath>..\libs\KeePass.exe</HintPath>
</Reference>
<Reference Include="Renci.SshNet, Version=2016.0.0.0, Culture=neutral, PublicKeyToken=1cee9f8bde3db106, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>Resources\Renci.SshNet.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
Expand All @@ -63,8 +68,10 @@
<Compile Include="IFieldMapper.cs" />
<Compile Include="IHasTitle.cs" />
<Compile Include="IHostPwEntry.cs" />
<Compile Include="PasswordChanger\LinuxPasswordChangerFactory.cs" />
<Compile Include="PasswordChanger\HostTypeSafeConverter.cs" />
<Compile Include="PasswordChanger\IHostTypeConverter.cs" />
<Compile Include="PasswordChanger\LinuxPasswordChanger.cs" />
<Compile Include="PasswordChanger\Services\PasswordChangerServiceWrapper.cs" />
<Compile Include="PasswordChanger\WindowsPasswordChangerFactory.cs" />
<Compile Include="PasswordChanger\IPasswordChangerGenericFactory.cs" />
Expand Down Expand Up @@ -144,6 +151,7 @@
<Compile Include="Services\IRegistryService.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\Renci.SshNet.dll" />
<EmbeddedResource Include="FormBatchPasswordChanger.resx">
<DependentUpon>FormBatchPasswordChanger.cs</DependentUpon>
</EmbeddedResource>
Expand Down
11 changes: 11 additions & 0 deletions QuickConnectPlugin/QuickConnectPluginExt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class QuickConnectPluginExt : Plugin {
private EventHandler pluginMenuItemOptionsOnClickEventHandler;
private EventHandler pluginMenuItemAboutOnClickEventHandler;
private EventHandler pluginMenuItemBatchPasswordChangerOnClickEventHandler;
private ResolveEventHandler resourcesEventHandler;
private List<ToolStripItem> menuItems = new List<ToolStripItem>();

private bool? rdcIsOlderVersion;
Expand Down Expand Up @@ -116,6 +117,7 @@ public override bool Initialize(IPluginHost pluginHost) {
new PsPasswdWrapper(this.Settings.PsPasswdPath))
);
}
pwChangerFactory.Factories.Add(HostType.Linux, new LinuxPasswordChangerFactory());

var pwChangerServiceFactory = new PasswordChangerServiceFactory(
new PasswordDatabase(this.pluginHost.Database),
Expand Down Expand Up @@ -145,6 +147,9 @@ public override bool Initialize(IPluginHost pluginHost) {
entryContextMenu.Opened += new EventHandler(entryContextMenu_Opened);
entryContextMenu.Closed += new ToolStripDropDownClosedEventHandler(entryContextMenu_Closed);

resourcesEventHandler = new ResolveEventHandler(AssemblyUtils.AssemblyResolverFromResources);
AppDomain.CurrentDomain.AssemblyResolve += resourcesEventHandler;

return true;
}

Expand Down Expand Up @@ -317,6 +322,9 @@ private ToolStripMenuItem createChangePasswordMenuItem(HostPwEntry hostPwEntry)
) {
pwChanger = new WindowsPasswordChanger(new PsPasswdWrapper(this.Settings.PsPasswdPath));
}
else if (hostType == HostType.Linux) {
pwChanger = new LinuxPasswordChanger();
}
var menuItem = new ToolStripMenuItem() {
Text = "Change Password...",
Enabled = hostPwEntry.HasIPAddress && pwChanger != null
Expand Down Expand Up @@ -362,6 +370,9 @@ public override void Terminate() {
if (this.pluginMenuItemBatchPasswordChanger != null) {
this.pluginMenuItemBatchPasswordChanger.Click -= this.pluginMenuItemBatchPasswordChangerOnClickEventHandler;
}
if (this.resourcesEventHandler != null) {
AppDomain.CurrentDomain.ResourceResolve -= this.resourcesEventHandler;
}
}
}
}
Binary file added QuickConnectPlugin/Resources/Renci.SshNet.dll
Binary file not shown.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Connection method and Additional options can be mapped to the same field. This w

## Password Changer

This feature allows you to change passwords for Windows and ESXi hosts directly from KeePass.
This feature allows you to change passwords for Windows/Linux/ESXi hosts directly from KeePass.

### Requirements

Expand All @@ -57,3 +57,4 @@ You can download compiled binaries from [here](http://www.disruptivesoftware.ro/

* The source code in this repository is released under the GNU GPLv2 or later license. See the [bundled LICENSE](https://github.com/cristianst85/QuickConnectPlugin/blob/master/LICENSE) file for details.
* The menu items icons are from Crystal Clear icon set by [Everaldo Coelho](http://www.everaldo.com/) licensed under LGPL v2.1 or later.
* Includes [SSH.NET](https://github.com/sshnet/SSH.NET) library copyrighted by RENCI and released under MIT License.
19 changes: 19 additions & 0 deletions libs/Renci.SshNet.License.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
The MIT License (MIT)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Binary file added libs/Renci.SshNet.dll
Binary file not shown.

0 comments on commit 76dc967

Please sign in to comment.