diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9e4253e --- /dev/null +++ b/.gitignore @@ -0,0 +1,355 @@ +Skip to content +This repository +Search +Pull requests +Issues +Marketplace +Explore + @bigpjo +Sign out +2,481 +63,978 29,350 github/gitignore + Code Pull requests 174 Projects 0 Insights +gitignore/VisualStudio.gitignore +96b153a 27 days ago +@shiftkey shiftkey Merge pull request #2576 from jerzywie/master +@shiftkey @arcresu @aroben @bbodenmiller @Haacked @niik @AArnott @Zenuka @sayedihashimi @saschanaz @LunicLynx @sfhardman @jamiehumphries @OsirisTerje @richorama @RehanSaeed @matma @JSkimming @jamesqo @elerch @cbadke @bdukes @anurse @anderslundsgard @alexanderKhaustov @julienshepherd + +325 lines (260 sloc) 5.36 KB +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ +**/Properties/launchSettings.json + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser +© 2018 GitHub, Inc. +Terms +Privacy +Security +Status +Help +Contact GitHub +API +Training +Shop +Blog +About +Press h to open a hovercard with more details. \ No newline at end of file diff --git a/CHANGELOG b/CHANGELOG index c0b937a..24830fa 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,9 @@ -2018-04-02 Version 1.8.1 (beta) +2018-04-08 Version 1.8.2 (beta) + enterprise mode now better reporting of login failures and includes change password dialog where user is required to change password + connectionString now in service app.config to allow to specify location for MyrtilleEnterprise.sdf or use SQL server + fixed issue with enterprise host create session including invalid /popup/ path in sessionURL + +2018-04-02 Version 1.8.1 (beta) enterprise mode data folder is now created by the installer (thanks hac) fixed installer error 1001 regarding CERTENROLLLib.CX509PrivateKey updated openssl to version 1.0.2o diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index ce3ff61..0ce592c 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -204,6 +204,8 @@ To enable enterprise mode, edit the app.config file of Myrtille.Services and unc - `EnterpriseDomain`, this is the name of your domain (i.e. MYDOMAIN or mydomain.local) if myrtille is part of it or the domain controller FQDN or IP otherwise - Restart Myrtille.Services windows service to use the new settings +To specify a customer path for the MyrtilleEnterprise database or use another SQL server amend Myrtille.Services app.config connectionString + If you wish to create your own enterprise adapter (with a different authentication, database or behavior), `Myrtille.Services.Contracts` contains the interfaces you need. ## Notes and limitations diff --git a/Myrtille.Enterprise/ActiveDirectory.cs b/Myrtille.Enterprise/ActiveDirectory.cs index 4e848cf..e577290 100644 --- a/Myrtille.Enterprise/ActiveDirectory.cs +++ b/Myrtille.Enterprise/ActiveDirectory.cs @@ -1,7 +1,9 @@ -/* - Enterprise mode, mimic behaviour of RDP gateways + +/* + Myrtille: A native HTML4/5 Remote Desktop Protocol client. - Copyright(c) 2017-2018 Olive Innovations + Copyright(c) 2014-2018 Cedric Coste + Copyright(c) 2018 Paul Oliver Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -20,9 +22,11 @@ limitations under the License. using System.Collections.Generic; using System.DirectoryServices; using System.DirectoryServices.AccountManagement; +using System.Runtime.InteropServices; using System.IO; using System.Linq; using System.Security.Cryptography; +using System.Security.Principal; using System.Text; using Myrtille.Helpers; using Myrtille.Services.Contracts; @@ -31,6 +35,7 @@ namespace Myrtille.Enterprise { public class ActiveDirectory : IEnterpriseAdapter { + public void Initialize() { using (var db = new MyrtilleEnterpriseDBContext()) @@ -55,8 +60,46 @@ public EnterpriseSession Authenticate(string username, string password, string a using (var context = new PrincipalContext(ContextType.Domain, domain, username, password)) { UserPrincipal user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username); + DirectoryEntry entry = (DirectoryEntry)user.GetUnderlyingObject(); + if(user.IsAccountLockedOut()) + { + return new EnterpriseSession + { + AuthenticationErrorCode = EnterpriseAuthenticationErrorCode.USER_ACCOUNT_LOCKED + }; + } + + if(user.Enabled != null && !(bool)user.Enabled) + { + return new EnterpriseSession + { + AuthenticationErrorCode = EnterpriseAuthenticationErrorCode.ACCOUNT_DISABLED + }; + } + + if(user.AccountExpirationDate != null && (DateTime)user.AccountExpirationDate <= DateTime.Now) + { + return new EnterpriseSession + { + AuthenticationErrorCode = EnterpriseAuthenticationErrorCode.ACCOUNT_EXPIRED + }; + } + + if (!user.PasswordNeverExpires )//&& !user.UserCannotChangePassword) + { + var expDate = (DateTime)entry.InvokeGet("PasswordExpirationDate"); + if (expDate <= DateTime.Now) + { + return new EnterpriseSession + { + AuthenticationErrorCode = EnterpriseAuthenticationErrorCode.PASSWORD_EXPIRED + }; + } + } + + var directoryGroups = new List(); try @@ -115,10 +158,27 @@ public EnterpriseSession Authenticate(string username, string password, string a } } } - catch (Exception e) + catch(DirectoryServicesCOMException e) + { + + var formattedError = (DirectoryExceptionHelper)e; + + return new EnterpriseSession + { + AuthenticationErrorCode = formattedError.ErrorCode + }; + } + catch(PrincipalOperationException e) { return null; } + catch (Exception e) + { + return new EnterpriseSession + { + AuthenticationErrorCode = EnterpriseAuthenticationErrorCode.UNKNOWN_ERROR + }; + } } /// @@ -502,7 +562,31 @@ public string CreateUserSession(string sessionID, long hostID, string username, return string.Format("?SI={0}&SD={1}&SK={2}",newSessionID,hostID,sessionKey); } } - + + /// + /// Change password for user + /// + /// + /// + /// + /// + public bool ChangeUserPassword(string username, string oldPassword, string newPassword, string domain) + { + try + { + using (var context = new PrincipalContext(ContextType.Domain, domain, username, oldPassword)) + { + UserPrincipal user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username); + user.ChangePassword(oldPassword, newPassword); + user.Save(); + } + return true; + }catch(Exception e) + { + return false; + } + } + #region aes encryption private static string AES_Encrypt(string stringToBeEncrypted, string passwordString) @@ -574,6 +658,7 @@ public string AES_Decrypt(string stringToBeDecrypted, string passwordString) return decryptedString; } + #endregion } } \ No newline at end of file diff --git a/Myrtille.Enterprise/Data/Host.cs b/Myrtille.Enterprise/Data/Host.cs index 498d64a..81c70b2 100644 --- a/Myrtille.Enterprise/Data/Host.cs +++ b/Myrtille.Enterprise/Data/Host.cs @@ -1,4 +1,23 @@ -using System.ComponentModel.DataAnnotations; +/* + Myrtille: A native HTML4/5 Remote Desktop Protocol client. + + Copyright(c) 2014-2018 Cedric Coste + Copyright(c) 2014-2018 Paul Oliver + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using Myrtille.Services.Contracts; diff --git a/Myrtille.Enterprise/Data/HostAccessGroups.cs b/Myrtille.Enterprise/Data/HostAccessGroups.cs index e5ac73e..2b9d19d 100644 --- a/Myrtille.Enterprise/Data/HostAccessGroups.cs +++ b/Myrtille.Enterprise/Data/HostAccessGroups.cs @@ -1,4 +1,22 @@ -using System.ComponentModel.DataAnnotations; +/* + Myrtille: A native HTML4/5 Remote Desktop Protocol client. + + Copyright(c) 2014-2018 Cedric Coste + Copyright(c) 2014-2018 Paul Oliver + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace Myrtille.Enterprise diff --git a/Myrtille.Enterprise/Data/MigrationConfiguration.cs b/Myrtille.Enterprise/Data/MigrationConfiguration.cs index 197cac2..11b55b9 100644 --- a/Myrtille.Enterprise/Data/MigrationConfiguration.cs +++ b/Myrtille.Enterprise/Data/MigrationConfiguration.cs @@ -1,3 +1,22 @@ +/* + Myrtille: A native HTML4/5 Remote Desktop Protocol client. + + Copyright(c) 2014-2018 Cedric Coste + Copyright(c) 2014-2018 Paul Oliver + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + using System.Data.Entity.Migrations; namespace Myrtille.Enterprise diff --git a/Myrtille.Enterprise/Data/MyrtilleEnterpriseDBContext.cs b/Myrtille.Enterprise/Data/MyrtilleEnterpriseDBContext.cs index 2bbcdf2..1503772 100644 --- a/Myrtille.Enterprise/Data/MyrtilleEnterpriseDBContext.cs +++ b/Myrtille.Enterprise/Data/MyrtilleEnterpriseDBContext.cs @@ -1,11 +1,31 @@ -using System.Data.Entity; +/* + Myrtille: A native HTML4/5 Remote Desktop Protocol client. + + Copyright(c) 2014-2018 Cedric Coste + Copyright(c) 2018 Paul Oliver + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +using System.Data.Entity; using System.Data.SqlServerCe; namespace Myrtille.Enterprise { public class MyrtilleEnterpriseDBContext : DbContext { - public MyrtilleEnterpriseDBContext() : base(new SqlCeConnection(@"Data Source=|DataDirectory|MyrtilleEnterprise.sdf;Persist Security Info=False;"), contextOwnsConnection: true) + public MyrtilleEnterpriseDBContext() : + base("name=enterpriseDBConnection") + //base(new SqlCeConnection(@"Data Source=|DataDirectory|MyrtilleEnterprise.sdf;Persist Security Info=False;"), contextOwnsConnection: true) { Database.SetInitializer(new MigrateDatabaseToLatestVersion()); } diff --git a/Myrtille.Enterprise/Data/Session.cs b/Myrtille.Enterprise/Data/Session.cs index e134788..d76701e 100644 --- a/Myrtille.Enterprise/Data/Session.cs +++ b/Myrtille.Enterprise/Data/Session.cs @@ -1,4 +1,22 @@ -using System; +/* + Myrtille: A native HTML4/5 Remote Desktop Protocol client. + + Copyright(c) 2014-2018 Cedric Coste + Copyright(c) 2018 Paul Oliver + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; @@ -11,7 +29,7 @@ public class Session [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] public long ID { get; set; } - [Index(IsClustered = true), StringLength(100)] + [Index(IsClustered = false), StringLength(100)] public string SessionID { get; set; } [Index, StringLength(250)] diff --git a/Myrtille.Enterprise/Data/SessionGroup.cs b/Myrtille.Enterprise/Data/SessionGroup.cs index ee4f442..a1a38b4 100644 --- a/Myrtille.Enterprise/Data/SessionGroup.cs +++ b/Myrtille.Enterprise/Data/SessionGroup.cs @@ -1,4 +1,22 @@ -using System.ComponentModel.DataAnnotations; +/* + Myrtille: A native HTML4/5 Remote Desktop Protocol client. + + Copyright(c) 2014-2018 Cedric Coste + Copyright(c) 2018 Paul Oliver + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace Myrtille.Enterprise diff --git a/Myrtille.Enterprise/Helpers/DirectoryExceptionHelper.cs b/Myrtille.Enterprise/Helpers/DirectoryExceptionHelper.cs new file mode 100644 index 0000000..e6917e4 --- /dev/null +++ b/Myrtille.Enterprise/Helpers/DirectoryExceptionHelper.cs @@ -0,0 +1,75 @@ +/* + Myrtille: A native HTML4/5 Remote Desktop Protocol client. + + Copyright(c) 2014-2018 Cedric Coste + Copyright(c) 2018 Paul Oliver + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.DirectoryServices; +using Myrtille.Services.Contracts; + +namespace Myrtille.Enterprise +{ + public class DirectoryExceptionHelper + { + public EnterpriseAuthenticationErrorCode ErrorCode { get; private set; } + + public DirectoryExceptionHelper(EnterpriseAuthenticationErrorCode e) + { + ErrorCode = e; + + } + + public static implicit operator DirectoryExceptionHelper(DirectoryServicesCOMException e) + { + var errorDict = e.ExtendedErrorMessage + .Split(',') + .Select(x => x.Trim()) + .ToDictionary(s => s.Split(new[] { ' ' }, 2)[0], s => s); + + var errorCode = errorDict["data"].Split(new[] { ' ' }, 2)[1]; + + switch (errorCode) + { + case "525": + return new DirectoryExceptionHelper(EnterpriseAuthenticationErrorCode.USER_NOT_FOUND); + case "52e": + return new DirectoryExceptionHelper(EnterpriseAuthenticationErrorCode.INVALID_LOGIN_CREDENTIALS); + case "530": + return new DirectoryExceptionHelper(EnterpriseAuthenticationErrorCode.LOGIN_NOT_PERMITTED_AT_THIS_TIME); + case "531": + return new DirectoryExceptionHelper(EnterpriseAuthenticationErrorCode.LOGIN_NOT_PERMITTED_AT_THIS_WORKSTATION); + case "532": + return new DirectoryExceptionHelper(EnterpriseAuthenticationErrorCode.PASSWORD_EXPIRED); + case "533": + return new DirectoryExceptionHelper(EnterpriseAuthenticationErrorCode.ACCOUNT_DISABLED); + case "534": + return new DirectoryExceptionHelper(EnterpriseAuthenticationErrorCode.USER_NOT_GRANTED_LOGIN_AT_THIS_MACHINE); + case "701": + return new DirectoryExceptionHelper(EnterpriseAuthenticationErrorCode.ACCOUNT_EXPIRED); + case "773": + return new DirectoryExceptionHelper(EnterpriseAuthenticationErrorCode.USER_MUST_RESET_PASSWORD); + case "775": + return new DirectoryExceptionHelper(EnterpriseAuthenticationErrorCode.USER_ACCOUNT_LOCKED); + default: + return new DirectoryExceptionHelper(EnterpriseAuthenticationErrorCode.UNKNOWN_ERROR); + } + } + } +} diff --git a/Myrtille.Enterprise/Myrtille.Enterprise.csproj b/Myrtille.Enterprise/Myrtille.Enterprise.csproj index fa7dd52..1c407a8 100644 --- a/Myrtille.Enterprise/Myrtille.Enterprise.csproj +++ b/Myrtille.Enterprise/Myrtille.Enterprise.csproj @@ -44,6 +44,7 @@ + ..\packages\Microsoft.SqlServer.Compact.4.0.8876.1\lib\net40\System.Data.SqlServerCe.dll @@ -51,6 +52,7 @@ + @@ -66,6 +68,7 @@ + @@ -82,7 +85,6 @@ Myrtille.Services.Contracts - diff --git a/Myrtille.Services.Contracts/Adapters/IEnterpriseAdapter.cs b/Myrtille.Services.Contracts/Adapters/IEnterpriseAdapter.cs index e744fb5..f52bb6c 100644 --- a/Myrtille.Services.Contracts/Adapters/IEnterpriseAdapter.cs +++ b/Myrtille.Services.Contracts/Adapters/IEnterpriseAdapter.cs @@ -42,5 +42,7 @@ public interface IEnterpriseAdapter EnterpriseConnectionDetails GetSessionConnectionDetails(string sessionID, long hostID, string sessionKey); string CreateUserSession(string sessionID, long hostID, string username, string password); + + bool ChangeUserPassword(string username, string oldPassword, string newPassword, string domain); } } \ No newline at end of file diff --git a/Myrtille.Services.Contracts/IEnterpriseService.cs b/Myrtille.Services.Contracts/IEnterpriseService.cs index e5f1469..86b836f 100644 --- a/Myrtille.Services.Contracts/IEnterpriseService.cs +++ b/Myrtille.Services.Contracts/IEnterpriseService.cs @@ -1,4 +1,22 @@ -using System.Collections.Generic; +/* + Myrtille: A native HTML4/5 Remote Desktop Protocol client. + + Copyright(c) 2014-2018 Cedric Coste + Copyright(c) 2014-2018 Paul Oliver + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +using System.Collections.Generic; using System.ServiceModel; namespace Myrtille.Services.Contracts @@ -35,5 +53,8 @@ public interface IEnterpriseService [OperationContract] string CreateUserSession(string sessionID, long hostID, string username, string password); + + [OperationContract] + bool ChangeUserPassword(string username, string oldPassword, string newPassword); } } \ No newline at end of file diff --git a/Myrtille.Services.Contracts/IMFAAuthentication.cs b/Myrtille.Services.Contracts/IMFAAuthentication.cs index 57da2b7..fad8abb 100644 --- a/Myrtille.Services.Contracts/IMFAAuthentication.cs +++ b/Myrtille.Services.Contracts/IMFAAuthentication.cs @@ -1,4 +1,22 @@ -using System.ServiceModel; +/* + Myrtille: A native HTML4/5 Remote Desktop Protocol client. + + Copyright(c) 2014-2018 Cedric Coste + Copyright(c) 2014-2018 Paul Oliver + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +using System.ServiceModel; namespace Myrtille.Services.Contracts { diff --git a/Myrtille.Services.Contracts/Models/EnterpriseAuthenticationErrorHelper.cs b/Myrtille.Services.Contracts/Models/EnterpriseAuthenticationErrorHelper.cs new file mode 100644 index 0000000..ae09958 --- /dev/null +++ b/Myrtille.Services.Contracts/Models/EnterpriseAuthenticationErrorHelper.cs @@ -0,0 +1,75 @@ +/* + Myrtille: A native HTML4/5 Remote Desktop Protocol client. + + Copyright(c) 2014-2018 Cedric Coste + Copyright(c) 2014-2018 Paul Oliver + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Myrtille.Services.Contracts +{ + public static class EnterpriseAuthenticationErrorHelper + { + public static string GetErrorDescription(EnterpriseAuthenticationErrorCode errorCode) + { + switch (errorCode) + { + case EnterpriseAuthenticationErrorCode.USER_NOT_FOUND: + return "User not found"; + case EnterpriseAuthenticationErrorCode.INVALID_LOGIN_CREDENTIALS: + return "Invalid credentials"; + case EnterpriseAuthenticationErrorCode.LOGIN_NOT_PERMITTED_AT_THIS_TIME: + return "Not permitted to login at this time"; + case EnterpriseAuthenticationErrorCode.LOGIN_NOT_PERMITTED_AT_THIS_WORKSTATION: + return "Not permitted to login at this workstation"; + case EnterpriseAuthenticationErrorCode.PASSWORD_EXPIRED: + return "Password expired"; + case EnterpriseAuthenticationErrorCode.ACCOUNT_DISABLED: + return "Account disabled"; + case EnterpriseAuthenticationErrorCode.USER_NOT_GRANTED_LOGIN_AT_THIS_MACHINE: + return "The user has not been granted the requested logon type at this machine"; + case EnterpriseAuthenticationErrorCode.ACCOUNT_EXPIRED: + return "Account expired"; + case EnterpriseAuthenticationErrorCode.USER_MUST_RESET_PASSWORD: + return "User must reset password but it cannot be done remotely"; + case EnterpriseAuthenticationErrorCode.USER_ACCOUNT_LOCKED: + return "User account locked"; + case EnterpriseAuthenticationErrorCode.UNKNOWN_ERROR: + default: + return "Unknown error occured"; + } + } + } + + public enum EnterpriseAuthenticationErrorCode + { + NONE, + USER_NOT_FOUND, + INVALID_LOGIN_CREDENTIALS, + LOGIN_NOT_PERMITTED_AT_THIS_TIME, + LOGIN_NOT_PERMITTED_AT_THIS_WORKSTATION, + PASSWORD_EXPIRED, + ACCOUNT_DISABLED, + USER_NOT_GRANTED_LOGIN_AT_THIS_MACHINE, + ACCOUNT_EXPIRED, + USER_MUST_RESET_PASSWORD, + USER_ACCOUNT_LOCKED, + UNKNOWN_ERROR + } +} diff --git a/Myrtille.Services.Contracts/Models/EnterpriseConnectionDetails.cs b/Myrtille.Services.Contracts/Models/EnterpriseConnectionDetails.cs index 49a7854..5063d93 100644 --- a/Myrtille.Services.Contracts/Models/EnterpriseConnectionDetails.cs +++ b/Myrtille.Services.Contracts/Models/EnterpriseConnectionDetails.cs @@ -1,4 +1,23 @@ -namespace Myrtille.Services.Contracts +/* + Myrtille: A native HTML4/5 Remote Desktop Protocol client. + + Copyright(c) 2014-2018 Cedric Coste + Copyright(c) 2014-2018 Paul Oliver + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +namespace Myrtille.Services.Contracts { public class EnterpriseConnectionDetails : EnterpriseHost { diff --git a/Myrtille.Services.Contracts/Models/EnterpriseHost.cs b/Myrtille.Services.Contracts/Models/EnterpriseHost.cs index 5df0af0..deff9a8 100644 --- a/Myrtille.Services.Contracts/Models/EnterpriseHost.cs +++ b/Myrtille.Services.Contracts/Models/EnterpriseHost.cs @@ -1,4 +1,22 @@ -namespace Myrtille.Services.Contracts +/* + Myrtille: A native HTML4/5 Remote Desktop Protocol client. + + Copyright(c) 2014-2018 Cedric Coste + Copyright(c) 2014-2018 Paul Oliver + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +namespace Myrtille.Services.Contracts { public class EnterpriseHost { diff --git a/Myrtille.Services.Contracts/Models/EnterpriseHostEdit.cs b/Myrtille.Services.Contracts/Models/EnterpriseHostEdit.cs index 7f4c920..79a7c16 100644 --- a/Myrtille.Services.Contracts/Models/EnterpriseHostEdit.cs +++ b/Myrtille.Services.Contracts/Models/EnterpriseHostEdit.cs @@ -1,4 +1,23 @@ -namespace Myrtille.Services.Contracts +/* + Myrtille: A native HTML4/5 Remote Desktop Protocol client. + + Copyright(c) 2014-2018 Cedric Coste + Copyright(c) 2014-2018 Paul Oliver + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +namespace Myrtille.Services.Contracts { public class EnterpriseHostEdit { diff --git a/Myrtille.Services.Contracts/Models/EnterpriseSession.cs b/Myrtille.Services.Contracts/Models/EnterpriseSession.cs index d795db1..9619f56 100644 --- a/Myrtille.Services.Contracts/Models/EnterpriseSession.cs +++ b/Myrtille.Services.Contracts/Models/EnterpriseSession.cs @@ -1,9 +1,29 @@ -namespace Myrtille.Services.Contracts +/* + Myrtille: A native HTML4/5 Remote Desktop Protocol client. + + Copyright(c) 2014-2018 Cedric Coste + Copyright(c) 2014-2018 Paul Oliver + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +using System.Runtime.Serialization; +namespace Myrtille.Services.Contracts { public class EnterpriseSession { public bool IsAdmin { get; set; } public string SessionID { get; set; } public string SessionKey { get; set; } + public EnterpriseAuthenticationErrorCode AuthenticationErrorCode { get; set; } } } \ No newline at end of file diff --git a/Myrtille.Services.Contracts/Models/SecurityProtocolEnum.cs b/Myrtille.Services.Contracts/Models/SecurityProtocolEnum.cs index 0ba4f33..d1c704b 100644 --- a/Myrtille.Services.Contracts/Models/SecurityProtocolEnum.cs +++ b/Myrtille.Services.Contracts/Models/SecurityProtocolEnum.cs @@ -1,4 +1,22 @@ -namespace Myrtille.Services.Contracts +/* + Myrtille: A native HTML4/5 Remote Desktop Protocol client. + + Copyright(c) 2014-2018 Cedric Coste + Copyright(c) 2014-2018 Paul Oliver + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +namespace Myrtille.Services.Contracts { public enum SecurityProtocolEnum { diff --git a/Myrtille.Services.Contracts/Myrtille.Services.Contracts.csproj b/Myrtille.Services.Contracts/Myrtille.Services.Contracts.csproj index e1cc9b1..6306ac8 100644 --- a/Myrtille.Services.Contracts/Myrtille.Services.Contracts.csproj +++ b/Myrtille.Services.Contracts/Myrtille.Services.Contracts.csproj @@ -58,6 +58,7 @@ + @@ -72,6 +73,7 @@ + diff --git a/Myrtille.Services/EnterpriseService.cs b/Myrtille.Services/EnterpriseService.cs index f4639fb..8f541d5 100644 --- a/Myrtille.Services/EnterpriseService.cs +++ b/Myrtille.Services/EnterpriseService.cs @@ -1,4 +1,22 @@ -using System; +/* + Myrtille: A native HTML4/5 Remote Desktop Protocol client. + + Copyright(c) 2014-2018 Cedric Coste + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +using System; using System.Collections.Generic; using System.Diagnostics; using Myrtille.Services.Contracts; @@ -127,5 +145,19 @@ public string CreateUserSession(string sessionID, long hostID, string username, return null; } } + + public bool ChangeUserPassword(string username, string oldPassword, string newPassword) + { + try + { + Trace.TraceInformation("Change password for user {0}", username); + return Program._enterpriseAdapter.ChangeUserPassword(username, oldPassword, newPassword, Program._enterpriseDomain); + } + catch (Exception ex) + { + Trace.TraceError("Failed to change password for user {0}, ({1})", username, ex); + return false; + } + } } } \ No newline at end of file diff --git a/Myrtille.Services/MFAAuthentication.cs b/Myrtille.Services/MFAAuthentication.cs index 62c4ffb..ef1cc5d 100644 --- a/Myrtille.Services/MFAAuthentication.cs +++ b/Myrtille.Services/MFAAuthentication.cs @@ -1,4 +1,22 @@ -using Myrtille.Services.Contracts; +/* + Myrtille: A native HTML4/5 Remote Desktop Protocol client. + + Copyright(c) 2014-2018 Cedric Coste + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +using Myrtille.Services.Contracts; namespace Myrtille.Services { diff --git a/Myrtille.Services/RemoteSessionProcess.cs b/Myrtille.Services/RemoteSessionProcess.cs index daf85b0..ce81059 100644 --- a/Myrtille.Services/RemoteSessionProcess.cs +++ b/Myrtille.Services/RemoteSessionProcess.cs @@ -88,7 +88,8 @@ public void StartProcess( // log remote session events into a file (located into \log) var remoteSessionLog = false; - if (bool.TryParse(ConfigurationManager.AppSettings["RemoteSessionLog"], out bool bResult)) + bool bResult = false; + if (bool.TryParse(ConfigurationManager.AppSettings["RemoteSessionLog"], out bResult)) { remoteSessionLog = bResult; } @@ -97,7 +98,8 @@ public void StartProcess( // color depth var bpp = 16; - if (int.TryParse(ConfigurationManager.AppSettings["FreeRDPBpp"], out int iResult)) + int iResult = 16; + if (int.TryParse(ConfigurationManager.AppSettings["FreeRDPBpp"], out iResult)) { bpp = iResult; } diff --git a/Myrtille.Services/app.config b/Myrtille.Services/app.config index 5df90fa..7047afc 100644 --- a/Myrtille.Services/app.config +++ b/Myrtille.Services/app.config @@ -6,7 +6,18 @@
- + + + + + diff --git a/Myrtille.Web/Default.aspx.cs b/Myrtille.Web/Default.aspx.cs index 5d52f7d..82a7f46 100644 --- a/Myrtille.Web/Default.aspx.cs +++ b/Myrtille.Web/Default.aspx.cs @@ -220,7 +220,7 @@ private void SessionFixationHandler() private void UpdateControls() { // hosts list - if (_enterpriseSession != null && (RemoteSession == null || RemoteSession.State == RemoteSessionState.Disconnecting || RemoteSession.State == RemoteSessionState.Disconnected)) + if (_enterpriseSession != null && _enterpriseSession.AuthenticationErrorCode == EnterpriseAuthenticationErrorCode.NONE && (RemoteSession == null || RemoteSession.State == RemoteSessionState.Disconnecting || RemoteSession.State == RemoteSessionState.Disconnected)) { toolbar.Style["visibility"] = "hidden"; toolbar.Style["display"] = "none"; @@ -302,6 +302,7 @@ protected void ConnectButtonClick( { connectError.InnerText = "MFA Authentication failed!"; UpdateControls(); + return; } } @@ -309,6 +310,7 @@ protected void ConnectButtonClick( // enterprise mode from login if (_enterpriseSession == null && _enterpriseClient.GetState()) { + CreateEnterpriseSessionFromLogin(); } // connection from: @@ -387,7 +389,8 @@ private bool ConnectRemoteServer() if (_enterpriseSession != null && Request["SD"] != null) { long hostId = 0; - if (long.TryParse(Request["SD"], out long lResult)) + long lResult = 0; + if (long.TryParse(Request["SD"], out lResult)) { hostId = lResult; } @@ -417,7 +420,8 @@ private bool ConnectRemoteServer() // remote clipboard access var allowRemoteClipboard = true; - if (bool.TryParse(ConfigurationManager.AppSettings["allowRemoteClipboard"], out bool bResult)) + bool bResult = false; + if (bool.TryParse(ConfigurationManager.AppSettings["allowRemoteClipboard"], out bResult)) { allowRemoteClipboard = bResult; } @@ -583,9 +587,19 @@ private void CreateEnterpriseSessionFromLogin() { // authenticate the user against the enterprise active directory _enterpriseSession = _enterpriseClient.Authenticate(user.Value, password.Value); - if (_enterpriseSession == null) + if (_enterpriseSession.AuthenticationErrorCode != EnterpriseAuthenticationErrorCode.NONE) { - connectError.InnerText = "Active Directory Authentication failed!"; + + if (_enterpriseSession.AuthenticationErrorCode == EnterpriseAuthenticationErrorCode.PASSWORD_EXPIRED) + { + Page.ClientScript.RegisterClientScriptBlock(this.GetType(), Guid.NewGuid().ToString(), string.Format("openPopup('changePasswordPopup', 'EnterpriseChangePassword.aspx?userId={0}');", user.Value),true); + } + else + { + connectError.InnerText = EnterpriseAuthenticationErrorHelper + .GetErrorDescription(_enterpriseSession.AuthenticationErrorCode); + + } UpdateControls(); return; } @@ -629,7 +643,7 @@ protected void hostsList_ItemDataBound( hostLink.Attributes["class"] = "hostLink"; var hostName = e.Item.FindControl("hostName") as HtmlGenericControl; - hostName.InnerText = host.HostName; + hostName.InnerText = (_enterpriseSession.IsAdmin ? "Edit " : "") + host.HostName; if (_enterpriseSession.IsAdmin) { hostName.Attributes["class"] = "hostName"; diff --git a/Myrtille.Web/Myrtille.Web.csproj b/Myrtille.Web/Myrtille.Web.csproj index db11135..bad8ba1 100644 --- a/Myrtille.Web/Myrtille.Web.csproj +++ b/Myrtille.Web/Myrtille.Web.csproj @@ -98,6 +98,13 @@ EditHost.aspx + + EnterpriseChangePassword.aspx + ASPXCodeBehind + + + EnterpriseChangePassword.aspx + FileStorage.aspx ASPXCodeBehind @@ -196,6 +203,7 @@ + diff --git a/Myrtille.Web/Web.config b/Myrtille.Web/Web.config new file mode 100644 index 0000000..7fd0881 --- /dev/null +++ b/Myrtille.Web/Web.config @@ -0,0 +1,117 @@ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Myrtille.Web/css/Default.css b/Myrtille.Web/css/Default.css index 94d14f8..200a864 100644 --- a/Myrtille.Web/css/Default.css +++ b/Myrtille.Web/css/Default.css @@ -360,6 +360,45 @@ label, width: 370px; } + +/* change password popup */ + +#changePasswordPopup, +#changePasswordPopupInner +{ + width: 400px; + height: 330px; +} + +#changePasswordPopupInner +{ + color: #000; + background: #fff; +} + +#changePasswordPopupTitle +{ + padding-top: 20px; + padding-left: 10px; +} + +.changePasswordMessage{ + padding-left: 10px; +} + +.changePasswordPopupInput +{ + padding-left: 10px; +} + +#changeError { + padding-left: 10px; + font-size: 10pt; + color: red; + width:380px; +} + + /* remote session display */ #displayDiv diff --git a/Myrtille.Web/popups/EditHost.aspx.cs b/Myrtille.Web/popups/EditHost.aspx.cs index e09462e..cf109e9 100644 --- a/Myrtille.Web/popups/EditHost.aspx.cs +++ b/Myrtille.Web/popups/EditHost.aspx.cs @@ -67,7 +67,8 @@ protected void Page_Load( // retrieve the host if (Request["hostId"] != null) { - if (long.TryParse(Request["hostId"], out long lResult)) + long lResult = 0; + if (long.TryParse(Request["hostId"], out lResult)) { _hostId = lResult; } diff --git a/Myrtille.Web/popups/EditHostSession.aspx.cs b/Myrtille.Web/popups/EditHostSession.aspx.cs index 32fdd19..6263e8b 100644 --- a/Myrtille.Web/popups/EditHostSession.aspx.cs +++ b/Myrtille.Web/popups/EditHostSession.aspx.cs @@ -66,7 +66,8 @@ protected void Page_Load( // retrieve the host if (Request["hostId"] != null) { - if (long.TryParse(Request["hostId"], out long lResult)) + long lResult = 0; + if (long.TryParse(Request["hostId"], out lResult)) { _hostId = lResult; } @@ -103,7 +104,7 @@ protected void CreateSessionUrlButtonClick( var url = _enterpriseClient.CreateUserSession(_enterpriseSession.SessionID, _hostId.Value, userName.Value, userPassword.Value); if (!string.IsNullOrEmpty(url)) { - sessionUrl.Value = Request.Url.Scheme + "://" + Request.Url.Host + (Request.Url.Port != 80 && Request.Url.Port != 443 ? ":" + Request.Url.Port : "") + "/" + Request.Url.Segments[1] + url + "&__EVENTTARGET=&__EVENTARGUMENT=&connect=Connect%21"; + sessionUrl.Value = Request.Url.Scheme + "://" + Request.Url.Host + (Request.Url.Port != 80 && Request.Url.Port != 443 ? ":" + Request.Url.Port : "") + Request.ApplicationPath + "/" + url + "&__EVENTTARGET=&__EVENTARGUMENT=&connect=Connect%21"; } } catch (Exception exc) diff --git a/Myrtille.Web/popups/EnterpriseChangePassword.aspx b/Myrtille.Web/popups/EnterpriseChangePassword.aspx new file mode 100644 index 0000000..64b976f --- /dev/null +++ b/Myrtille.Web/popups/EnterpriseChangePassword.aspx @@ -0,0 +1,86 @@ +<%-- + Myrtille: A native HTML4/5 Remote Desktop Protocol client. + + Copyright(c) 2014-2018 Cedric Coste + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--%> + +<%@ Page Language="C#" Inherits="Myrtille.Web.EnterpriseChangePassword" Codebehind="EnterpriseChangePassword.aspx.cs" AutoEventWireup="true" Culture="auto" UICulture="auto" %> +<%@ OutputCache Location="None" %> + + + + + + + Myrtille + + + + + +
+ +
+ + Change Password + +
+

Your password has expired and must be changed

+ +
+
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+ +
+
+
+ + +
+
+ +
+ + + + + + \ No newline at end of file diff --git a/Myrtille.Web/popups/EnterpriseChangePassword.aspx.cs b/Myrtille.Web/popups/EnterpriseChangePassword.aspx.cs new file mode 100644 index 0000000..4027e46 --- /dev/null +++ b/Myrtille.Web/popups/EnterpriseChangePassword.aspx.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.UI; +using System.Web.UI.WebControls; + +namespace Myrtille.Web +{ + public partial class EnterpriseChangePassword : System.Web.UI.Page + { + private EnterpriseServiceClient _enterpriseClient; + private string _userName = null; + /// + /// page init + /// + /// + /// + protected void Page_Init( + object sender, + EventArgs e) + { + _enterpriseClient = new EnterpriseServiceClient(); + } + + /// + /// page load (postback data is now available) + /// + /// + /// + protected void Page_Load( + object sender, + EventArgs e) + { + // retrieve the host + if (Request["userId"] != null) + { + userName.Value = Request["userId"]; + _userName = Request["userId"]; + + if (!IsPostBack && Request["edit"] == null) + { + //try + //{ + // var host = _enterpriseClient.GetHost(_hostId.Value, _enterpriseSession.SessionID); + // if (host != null) + // { + // hostName.Value = host.HostName; + // hostAddress.Value = host.HostAddress; + // groupsAccess.Value = host.DirectoryGroups; + // securityProtocol.SelectedIndex = (int)host.Protocol; + // } + //} + //catch (Exception exc) + //{ + // System.Diagnostics.Trace.TraceError("Failed to retrieve host {0}, ({1})", _hostId, exc); + //} + } + } + else + { + changePassword.Disabled = true; + } + } + + /// + /// change a user password + /// + /// + /// + protected void ChangePasswordButtonClick( + object sender, + EventArgs e) + { + if (_enterpriseClient == null && !string.IsNullOrEmpty(_userName)) + return; + + try + { + if(string.IsNullOrEmpty(oldPassword.Value)) + { + changeError.InnerText = "Old password must be specified"; + }else + if (!string.Equals(newPassword.Value, confirmPassword.Value)) + { + changeError.InnerText = "New and confirmed passwords do not match"; + } + else + { + bool bResult = _enterpriseClient.ChangeUserPassword(_userName, oldPassword.Value, newPassword.Value); + + if (bResult) + { + Response.Redirect(Request.RawUrl + (Request.RawUrl.Contains("?") ? "&" : "?") + "change=success"); + } + else + { + changeError.InnerText = "Password change failed"; + } + } + } + catch (Exception exc) + { + System.Diagnostics.Trace.TraceError("Failed to change user password {0} ({1})", _userName, exc); + changeError.InnerText = "Password change failed"; + } + } + } +} \ No newline at end of file diff --git a/Myrtille.Web/popups/EnterpriseChangePassword.aspx.designer.cs b/Myrtille.Web/popups/EnterpriseChangePassword.aspx.designer.cs new file mode 100644 index 0000000..1e86aee --- /dev/null +++ b/Myrtille.Web/popups/EnterpriseChangePassword.aspx.designer.cs @@ -0,0 +1,69 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Myrtille.Web { + + + public partial class EnterpriseChangePassword { + + /// + /// userName control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlInputText userName; + + /// + /// oldPassword control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlInputPassword oldPassword; + + /// + /// newPassword control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlInputPassword newPassword; + + /// + /// confirmPassword control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlInputPassword confirmPassword; + + /// + /// changeError control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlGenericControl changeError; + + /// + /// changePassword control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlInputButton changePassword; + } +} diff --git a/Myrtille.Web/src/EnterpriseServiceClient.cs b/Myrtille.Web/src/EnterpriseServiceClient.cs index 01f1a0c..b4d9840 100644 --- a/Myrtille.Web/src/EnterpriseServiceClient.cs +++ b/Myrtille.Web/src/EnterpriseServiceClient.cs @@ -137,5 +137,18 @@ public string CreateUserSession(string sessionID, long hostID, string username, throw; } } + + public bool ChangeUserPassword(string username, string oldPassword, string newPassword) + { + try + { + return Channel.ChangeUserPassword(username, oldPassword, newPassword); + } + catch (Exception exc) + { + Trace.TraceError("Failed to change user password ({0})", exc); + throw; + } + } } } \ No newline at end of file