/*
Myrtille: A native HTML4/5 Remote Desktop Protocol client.
Copyright(c) 2014-2021 Cedric Coste
Copyright(c) 2018 Paul Oliver (Olive Innovations)
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.Configuration;
using System.Linq;
using Myrtille.Helpers;
using Myrtille.Services.Contracts;
namespace Myrtille.Enterprise
{
public class LocalAdmin : IEnterpriseAdapter
{
public void Initialize()
{
using (var db = new MyrtilleEnterpriseDBContext())
{
db.Session.RemoveRange(db.Session);
db.SaveChanges();
}
}
public EnterpriseSession Authenticate(string username, string password, string adminGroup, string domain, string netbiosDomain)
{
EnterpriseSession enterpriseSession = null;
try
{
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var localAdminUser = ((AppSettingsSection)config.GetSection("localAdmin")).Settings["LocalAdminUser"].Value;
var localAdminPassword = ((AppSettingsSection)config.GetSection("localAdmin")).Settings["localAdminPassword"].Value;
if (!username.Equals(localAdminUser))
{
enterpriseSession = new EnterpriseSession
{
AuthenticationErrorCode = EnterpriseAuthenticationErrorCode.USER_NOT_FOUND
};
}
else
{
if (!localAdminPassword.Equals("admin"))
{
localAdminPassword = CryptoHelper.AES_Decrypt(localAdminPassword, localAdminUser);
}
if (!password.Equals(localAdminPassword))
{
enterpriseSession = new EnterpriseSession
{
AuthenticationErrorCode = EnterpriseAuthenticationErrorCode.INVALID_LOGIN_CREDENTIALS
};
}
else
{
if (password.Equals("admin"))
{
enterpriseSession = new EnterpriseSession
{
AuthenticationErrorCode = EnterpriseAuthenticationErrorCode.PASSWORD_EXPIRED
};
}
else
{
using (var db = new MyrtilleEnterpriseDBContext())
{
var session = db.Session.FirstOrDefault(m => m.Username == username);
if (session != null)
{
db.Session.Remove(session);
db.SaveChanges();
}
string sessionID = Guid.NewGuid().ToString();
string sessionKey = Guid.NewGuid().ToString("n");
session = new Session
{
Domain = netbiosDomain,
Username = username,
Password = CryptoHelper.AES_Encrypt(CryptoHelper.RDP_Encrypt(password), sessionKey),
SessionID = sessionID,
IsAdmin = true
};
db.Session.Add(session);
db.SaveChanges();
enterpriseSession = new EnterpriseSession
{
Domain = netbiosDomain,
UserName = username,
SessionID = sessionID,
SessionKey = sessionKey,
IsAdmin = true,
SingleUseConnection = false
};
}
}
}
}
}
catch (Exception)
{
enterpriseSession = new EnterpriseSession
{
AuthenticationErrorCode = EnterpriseAuthenticationErrorCode.UNKNOWN_ERROR
};
}
return enterpriseSession;
}
public void Logout(string sessionID)
{
using (var db = new MyrtilleEnterpriseDBContext())
{
var session = db.Session.FirstOrDefault(m => m.SessionID == sessionID);
if (session != null)
{
db.Session.Remove(session);
db.SaveChanges();
}
}
}
public long? AddHost(EnterpriseHostEdit editHost, string sessionID)
{
long? hostId = null;
using (var db = new MyrtilleEnterpriseDBContext())
{
if (db.Session.Any(m => m.SessionID == sessionID && m.IsAdmin && m.Expire > DateTime.Now) &&
!db.Host.Any(m => m.HostName.Equals(editHost.HostName, StringComparison.InvariantCultureIgnoreCase)))
{
var host = new Host
{
HostName = editHost.HostName,
HostAddress = editHost.HostAddress,
VMGuid = editHost.VMGuid,
VMEnhancedMode = editHost.VMEnhancedMode,
Protocol = editHost.Protocol,
HostType = editHost.HostType,
StartRemoteProgram = editHost.StartRemoteProgram,
PromptForCredentials = editHost.PromptForCredentials
};
db.Host.Add(host);
db.SaveChanges();
hostId = host.ID;
}
}
return hostId;
}
public EnterpriseHostEdit GetHost(long hostID, string sessionID)
{
EnterpriseHostEdit hostEdit = null;
using (var db = new MyrtilleEnterpriseDBContext())
{
if (db.Session.Any(m => m.SessionID == sessionID && m.IsAdmin && m.Expire > DateTime.Now))
{
var host = db.Host.FirstOrDefault(m => m.ID == hostID);
if (host != null)
{
hostEdit = new EnterpriseHostEdit
{
HostID = host.ID,
HostName = host.HostName,
HostAddress = host.HostAddress,
VMGuid = host.VMGuid,
VMEnhancedMode = host.VMEnhancedMode,
Protocol = host.Protocol,
HostType = host.HostType,
StartRemoteProgram = host.StartRemoteProgram,
PromptForCredentials = host.PromptForCredentials
};
}
}
}
return hostEdit;
}
public bool UpdateHost(EnterpriseHostEdit editHost, string sessionID)
{
var success = false;
using (var db = new MyrtilleEnterpriseDBContext())
{
if (db.Session.Any(m => m.SessionID == sessionID && m.IsAdmin && m.Expire > DateTime.Now))
{
var host = db.Host.FirstOrDefault(m => m.ID == editHost.HostID);
if (host != null)
{
host.HostName = editHost.HostName;
host.HostAddress = editHost.HostAddress;
host.VMGuid = editHost.VMGuid;
host.VMEnhancedMode = editHost.VMEnhancedMode;
host.Protocol = editHost.Protocol;
host.StartRemoteProgram = editHost.StartRemoteProgram;
host.PromptForCredentials = editHost.PromptForCredentials;
db.SaveChanges();
success = true;
}
}
}
return success;
}
public bool DeleteHost(long hostID, string sessionID)
{
var success = false;
using (var db = new MyrtilleEnterpriseDBContext())
{
if (db.Session.Any(m => m.SessionID == sessionID && m.IsAdmin && m.Expire > DateTime.Now))
{
var host = db.Host.FirstOrDefault(m => m.ID == hostID);
if (host != null)
{
db.Host.Remove(host);
db.SaveChanges();
success = true;
}
}
}
return success;
}
public List SessionHosts(string sessionID)
{
var hosts = new List();
using (var db = new MyrtilleEnterpriseDBContext())
{
var sessionInfo = db.Session
.Where(m => m.SessionID == sessionID && m.Expire > DateTime.Now)
.Select(m => new
{
SessionID = m.SessionID,
IsAdmin = m.IsAdmin
})
.FirstOrDefault();
if (sessionInfo != null && sessionInfo.IsAdmin)
{
hosts = (from s in db.Session
from h in db.Host
where s.SessionID == sessionID
&& s.Expire > DateTime.Now
select new EnterpriseHost
{
HostID = h.ID,
HostName = h.HostName,
HostAddress = h.HostAddress,
VMGuid = h.VMGuid,
VMEnhancedMode = h.VMEnhancedMode,
HostType = h.HostType,
StartRemoteProgram = h.StartRemoteProgram,
PromptForCredentials = h.PromptForCredentials
})
.Distinct()
.OrderBy(m => m.HostName)
.ToList();
}
}
return hosts;
}
public EnterpriseConnectionDetails GetSessionConnectionDetails(string sessionID, long hostID, string sessionKey)
{
EnterpriseConnectionDetails connection = null;
using (var db = new MyrtilleEnterpriseDBContext())
{
var sessionInfo = db.Session
.Where(m => m.SessionID == sessionID && m.Expire > DateTime.Now)
.Select(m => new
{
SessionID = m.SessionID,
OneTime = m.OneTime,
IsAdmin = m.IsAdmin
})
.FirstOrDefault();
if (sessionInfo != null)
{
if (sessionInfo.OneTime)
{
connection = (from s in db.Session
from h in db.Host
where s.SessionID == sessionID
&& h.ID == hostID
&& s.Expire > DateTime.Now
select new EnterpriseConnectionDetails
{
HostID = h.ID,
HostName = h.HostName,
HostAddress = h.HostAddress,
VMGuid = h.VMGuid,
VMEnhancedMode = h.VMEnhancedMode,
HostType = h.HostType,
Domain = s.Domain,
Username = s.Username,
Password = s.Password,
Protocol = h.Protocol,
StartRemoteProgram = h.StartRemoteProgram
})
.FirstOrDefault();
}
else if (sessionInfo.IsAdmin)
{
connection = (from s in db.Session
from h in db.Host
join sc in db.SessionHostCredentials on new { x1 = s.ID, x2 = h.ID } equals new { x1 = sc.SessionID, x2 = sc.HostID } into scl
from sc in scl.DefaultIfEmpty()
where s.SessionID == sessionID
&& h.ID == hostID
&& s.Expire > DateTime.Now
select new EnterpriseConnectionDetails
{
HostID = h.ID,
HostName = h.HostName,
HostAddress = h.HostAddress,
VMGuid = h.VMGuid,
VMEnhancedMode = h.VMEnhancedMode,
HostType = h.HostType,
Domain = sc.Domain,
Username = sc.Username,
Password = sc.Password,
Protocol = h.Protocol,
StartRemoteProgram = h.StartRemoteProgram
})
.FirstOrDefault();
}
if (connection != null)
{
connection.Password = CryptoHelper.AES_Decrypt(connection.Password, sessionKey);
}
// when connected from the login page, the session logout is based on expiration or user action
// when connected from a one time url, the logout is done immediately
if (sessionInfo.OneTime)
{
Logout(sessionID);
}
}
}
return connection;
}
public string CreateUserSession(string sessionID, long hostID, string username, string password, string domain)
{
string sessionUrl = null;
using (var db = new MyrtilleEnterpriseDBContext())
{
if (db.Session.Any(m => m.SessionID == sessionID && m.IsAdmin && m.Expire > DateTime.Now) &&
db.Host.Any(m => m.ID == hostID))
{
string newSessionID = Guid.NewGuid().ToString();
string sessionKey = Guid.NewGuid().ToString("n");
var session = new Session
{
Domain = domain,
Username = username,
Password = CryptoHelper.AES_Encrypt(CryptoHelper.RDP_Encrypt(password), sessionKey),
SessionID = newSessionID,
IsAdmin = false,
Expire = DateTime.Now.AddHours(1),
OneTime = true
};
db.Session.Add(session);
db.SaveChanges();
sessionUrl = string.Format("?SI={0}&SD={1}&SK={2}", newSessionID, hostID, sessionKey);
}
}
return sessionUrl;
}
public bool ChangeUserPassword(string username, string oldPassword, string newPassword, string domain)
{
var success = false;
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var localAdminUser = ((AppSettingsSection)config.GetSection("localAdmin")).Settings["LocalAdminUser"].Value;
var localAdminPassword = ((AppSettingsSection)config.GetSection("localAdmin")).Settings["localAdminPassword"].Value;
if (username.Equals(localAdminUser))
{
if (!localAdminPassword.Equals("admin"))
{
localAdminPassword = CryptoHelper.AES_Decrypt(localAdminPassword, localAdminUser);
}
if (oldPassword.Equals(localAdminPassword))
{
((AppSettingsSection)config.GetSection("localAdmin")).Settings["localAdminPassword"].Value = CryptoHelper.AES_Encrypt(newPassword, localAdminUser);
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("localAdmin");
success = true;
}
}
return success;
}
public bool AddSessionHostCredentials(EnterpriseHostSessionCredentials credentials)
{
var success = false;
using (var db = new MyrtilleEnterpriseDBContext())
{
var session = db.Session.FirstOrDefault(m => m.SessionID == credentials.SessionID);
if (session != null && db.Host.Any(m => m.ID == credentials.HostID))
{
var sessionHost = db.SessionHostCredentials.FirstOrDefault(m =>
m.SessionID == session.ID &&
m.HostID == credentials.HostID);
if (sessionHost != null)
{
db.SessionHostCredentials.Remove(sessionHost);
}
sessionHost = new SessionHostCredential
{
SessionID = session.ID,
HostID = credentials.HostID,
Domain = credentials.Domain,
Username = credentials.Username,
Password = CryptoHelper.AES_Encrypt(CryptoHelper.RDP_Encrypt(credentials.Password), credentials.SessionKey)
};
db.SessionHostCredentials.Add(sessionHost);
db.SaveChanges();
success = true;
}
}
return success;
}
}
}