diff --git a/ClientServerLib/ClientServerLib/CServer.cs b/ClientServerLib/ClientServerLib/CServer.cs
index ab704a95..51a6d2b7 100644
--- a/ClientServerLib/ClientServerLib/CServer.cs
+++ b/ClientServerLib/ClientServerLib/CServer.cs
@@ -142,14 +142,14 @@ namespace ServerLib
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
smb.HttpGetEnabled = true;
host.Description.Behaviors.Add(smb);*/
- _RegisterUrlAndCert(_BaseAddress.Port);
+ _RegisterUrlAndCert(_BaseAddress.Port, false);
_Host.Open();
}
catch (CommunicationException e)
{
if (e is AddressAccessDeniedException || e is AddressAlreadyInUseException)
{
- _RegisterUrlAndCert(_BaseAddress.Port);
+ _RegisterUrlAndCert(_BaseAddress.Port, true);
try
{
_Host.Abort();
@@ -178,18 +178,18 @@ namespace ServerLib
}
}
- private void _RegisterUrlAndCert(int port)
+ private void _RegisterUrlAndCert(int port, bool reserve)
{
#if WIN
ProcessStartInfo info = new ProcessStartInfo
{
FileName = "VocaluxeServerConfig.exe",
- Arguments = port + " " + (_Encrypted ? "true" : "false"),
+ WorkingDirectory = Environment.CurrentDirectory,
+ Arguments = port + " " + (_Encrypted ? "true" : "false") + (reserve ? " reserve" : ""),
UseShellExecute = true,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
- Verb = "runas"
};
Process p = Process.Start(info);
p.WaitForExit();
diff --git a/Vocaluxe/Program.cs b/Vocaluxe/Program.cs
index 5d254c13..b59d4f9e 100644
--- a/Vocaluxe/Program.cs
+++ b/Vocaluxe/Program.cs
@@ -259,6 +259,7 @@ namespace Vocaluxe
Environment.Exit(Environment.ExitCode);
}
+#if !DEBUG
[HandleProcessCorruptedStateExceptions]
private static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs args)
{
@@ -273,6 +274,7 @@ namespace Vocaluxe
CLog.LogError("Unhandled exception: " + e.Message + stackTrace);
_CloseProgram();
}
+#endif
private static Assembly _AssemblyResolver(Object sender, ResolveEventArgs args)
{
diff --git a/WebserverInitalConfig/CConfigHttpApi.cs b/WebserverInitalConfig/CConfigHttpApi.cs
index 4bbd3ed9..fe184af4 100644
--- a/WebserverInitalConfig/CConfigHttpApi.cs
+++ b/WebserverInitalConfig/CConfigHttpApi.cs
@@ -15,6 +15,9 @@
// along with Vocaluxe. If not, see .
#endregion
+using System.Diagnostics;
+using System.Security.Authentication;
+using System.Security.Principal;
using Security.Cryptography;
using Security.Cryptography.X509Certificates;
using System;
@@ -26,34 +29,64 @@ using NetFwTypeLib;
namespace WebserverInitalConfig
{
- public static class CConfigHttpApi
+ public class CConfigHttpApi
{
// ReSharper disable InconsistentNaming
private const String CLSID_NetFwMgr = "{304CE942-6E39-40D8-943A-B913C40C9CD4}";
private const String CLSID_NetAuthApp = "{EC9846B3-2762-4A6B-A214-6ACB603462D2}";
private const String CLSID_NetOpenPort = "{0CA545C6-37AD-4A6C-BF92-9F7610067EF5}";
+ private const string _AppGUID = "{7baf41f1-48b7-42cb-b145-f815499cb48f}";
// ReSharper restore InconsistentNaming
- public static void ReserveUrl(string networkString)
+
+ private readonly string _RuleName;
+ private readonly string _ExePath;
+ private readonly string _IP;
+ private readonly int _Port;
+ private readonly bool _IsTCP;
+
+ public CConfigHttpApi(string ruleName, string exePath, string ip, int port, bool isTCP)
{
+ _ExePath = exePath;
+ _Port = port;
+ _IsTCP = isTCP;
+ _IP = ip;
+ _RuleName = ruleName;
+ }
+
+ private static void _ReserveUrl(string networkString)
+ {
+ if (!IsAdministrator())
+ throw new AuthenticationException();
HttpApi.ReserveURL(networkString, "D:(A;;GX;;;S-1-1-0)");
}
- public static void BindCert(string ip, int port, X509Certificate2 cert)
+ public void ReserveUrl()
{
- IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse(ip), port);
- if (HttpApi.QuerySslCertificateInfo(endpoint) != null)
- HttpApi.DeleteCertificateBinding(endpoint);
-
- HttpApi.BindCertificate(endpoint, cert.GetCertHash(), StoreName.My, new Guid("{7baf41f1-48b7-42cb-b145-f815499cb48f}"));
+ _ReserveUrl("https://+:" + _Port + "/");
}
- public static void AddCertToStore(X509Certificate2 cert)
+ private void _BindCert(X509Certificate cert)
+ {
+ IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse(_IP), _Port);
+ HttpApi.SslCertificateInfo certificateInfo = HttpApi.QuerySslCertificateInfo(endpoint);
+ if (certificateInfo != null && !certificateInfo.Hash.SequenceEqual(cert.GetCertHash()))
+ {
+ if (!IsAdministrator())
+ throw new AuthenticationException();
+ HttpApi.DeleteCertificateBinding(endpoint);
+
+ HttpApi.BindCertificate(endpoint, cert.GetCertHash(), StoreName.My, new Guid(_AppGUID));
+ }
+ }
+
+ private static void _AddCertToStore(X509Certificate2 cert)
{
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadWrite);
- X509Certificate2Collection oldCerts = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName,
- cert.SubjectName.Name, false);
+ // ReSharper disable AssignNullToNotNullAttribute
+ X509Certificate2Collection oldCerts = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName, cert.SubjectName.Name, false);
+ // ReSharper restore AssignNullToNotNullAttribute
foreach (X509Certificate2 oldCert in oldCerts)
store.Remove(oldCert);
@@ -62,7 +95,25 @@ namespace WebserverInitalConfig
store.Close();
}
- public static X509Certificate2 GetSelfSignedCert(string subjectName)
+ private static X509Certificate2 _GetCert(string name)
+ {
+ X509Certificate2 result = null;
+ X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
+ store.Open(OpenFlags.ReadOnly);
+
+ var name2 = new X500DistinguishedName(name);
+ // ReSharper disable AssignNullToNotNullAttribute
+ X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName, name2.Name, false);
+ // ReSharper restore AssignNullToNotNullAttribute
+ if (certs.Count > 0)
+ result = certs[0];
+
+ store.Close();
+
+ return result;
+ }
+
+ private X509Certificate2 _GetSelfSignedCert(string subjectName)
{
var keyParam = new CngKeyCreationParameters
{
@@ -91,58 +142,113 @@ namespace WebserverInitalConfig
byte[] rawData = key.CreateSelfSignedCertificate(param).Export(X509ContentType.Pfx, "");
var cert = new X509Certificate2(rawData, "", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet)
{
- FriendlyName = "Vocaluxe Server Certificate"
+ FriendlyName = _RuleName + " Server Certificate"
};
return cert;
}
- private static void _AddFirewallRuleForProfile(INetFwProfile profile, string exePath, int port, bool isTCP)
+ public void CreateAndAddCert(string hostName)
{
- bool isFirewallEnabled = profile.FirewallEnabled;
+ string certName = "CN=" + hostName + ", C=DE, O=" + _RuleName + ", OU=" + _RuleName + " Server";
- if (!isFirewallEnabled)
- return;
- INetFwAuthorizedApplications applications = profile.AuthorizedApplications;
- if (!(from INetFwAuthorizedApplication a in applications
- where a.ProcessImageFileName == exePath
- select a).Any())
+ X509Certificate2 cert = _GetCert(certName);
+ if (cert == null)
{
- INetFwAuthorizedApplication application = (INetFwAuthorizedApplication)Activator.CreateInstance(
- Type.GetTypeFromCLSID(new Guid(CLSID_NetAuthApp)));
-
- application.Name = "Vocaluxe";
- application.ProcessImageFileName = exePath;
- application.Enabled = true;
- application.Scope = NET_FW_SCOPE_.NET_FW_SCOPE_ALL;
- applications.Add(application);
- }
- INetFwOpenPorts openPorts = profile.GloballyOpenPorts;
- NET_FW_IP_PROTOCOL_ protocol = isTCP ? NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP : NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_UDP;
- if (!(from INetFwOpenPort p in openPorts
- where (p.Port == port &&
- (p.Protocol == protocol))
- select p).Any())
- {
- INetFwOpenPort openPort = (INetFwOpenPort)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid(CLSID_NetOpenPort)));
- openPort.Enabled = true;
- openPort.Port = port;
- openPort.Protocol = protocol;
- openPort.Name = "Vocaluxe(" + port + ")";
- openPort.Scope = NET_FW_SCOPE_.NET_FW_SCOPE_ALL;
-
- openPorts.Add(openPort);
+ if (!IsAdministrator())
+ throw new AuthenticationException();
+ cert = _GetSelfSignedCert(certName);
+ _AddCertToStore(cert);
}
+ _BindCert(cert);
}
- public static void AddFirewallRule(string exePath, int port, bool isTCP)
+ private bool _IsAppAuthorized(INetFwProfile profile)
+ {
+ if (!profile.FirewallEnabled)
+ return true;
+ foreach (INetFwAuthorizedApplication a in profile.AuthorizedApplications)
+ {
+ if (a.ProcessImageFileName == _ExePath)
+ return true;
+ }
+ return false;
+ }
+
+ private bool _IsPortOpen(INetFwProfile profile)
+ {
+ NET_FW_IP_PROTOCOL_ protocol = _GetProtocol();
+
+ if (!profile.FirewallEnabled)
+ return true;
+ foreach (INetFwOpenPort p in profile.GloballyOpenPorts)
+ {
+ if (p.Protocol == protocol && p.Port == _Port)
+ return true;
+ }
+ return false;
+ }
+
+ private NET_FW_IP_PROTOCOL_ _GetProtocol()
+ {
+ return _IsTCP ? NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP : NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_UDP;
+ }
+
+ private void _AddFirewallRuleForProfile(INetFwProfile profile)
+ {
+ bool isAppAuthorized = _IsAppAuthorized(profile);
+ bool isPortOpen = _IsPortOpen(profile);
+
+ if ((!isAppAuthorized || !isPortOpen) && !IsAdministrator())
+ throw new AuthenticationException();
+ if (!isAppAuthorized)
+ _AddAppToFirewall(profile);
+
+ if (!isPortOpen)
+ _AddPortToFirewall(profile);
+ }
+
+ private void _AddPortToFirewall(INetFwProfile profile)
+ {
+ INetFwOpenPort openPort = (INetFwOpenPort)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid(CLSID_NetOpenPort)));
+ openPort.Enabled = true;
+ openPort.Port = _Port;
+ openPort.Protocol = _GetProtocol();
+ openPort.Name = _RuleName + "(" + _Port + ")";
+ openPort.Scope = NET_FW_SCOPE_.NET_FW_SCOPE_ALL;
+
+ profile.GloballyOpenPorts.Add(openPort);
+ }
+
+ private void _AddAppToFirewall(INetFwProfile profile)
+ {
+ INetFwAuthorizedApplication application = (INetFwAuthorizedApplication)Activator.CreateInstance(
+ Type.GetTypeFromCLSID(new Guid(CLSID_NetAuthApp)));
+
+ application.Name = _RuleName;
+ application.ProcessImageFileName = _ExePath;
+ application.Enabled = true;
+ application.Scope = NET_FW_SCOPE_.NET_FW_SCOPE_ALL;
+ profile.AuthorizedApplications.Add(application);
+ }
+
+ public static bool IsAdministrator()
+ {
+ WindowsIdentity identity = WindowsIdentity.GetCurrent();
+ // ReSharper disable AssignNullToNotNullAttribute
+ WindowsPrincipal principal = new WindowsPrincipal(identity);
+ // ReSharper restore AssignNullToNotNullAttribute
+ return principal.IsInRole(WindowsBuiltInRole.Administrator);
+ }
+
+ public void AddFirewallRule()
{
INetFwMgr manage = (INetFwMgr)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid(CLSID_NetFwMgr)));
- //AddFirewallRuleForProfile(manage.LocalPolicy.CurrentProfile, exePath, port, isTCP);
+ //_AddFirewallRuleForProfile(manage.LocalPolicy.CurrentProfile);
//if (manage.CurrentProfileType != NET_FW_PROFILE_TYPE_.NET_FW_PROFILE_STANDARD)
//Add to Home/Work(Private) and current net
//TODO: This somewhow adds 2 entries each instead of only one that is activated for Home/Work and public nets
- _AddFirewallRuleForProfile(manage.LocalPolicy.GetProfileByType(NET_FW_PROFILE_TYPE_.NET_FW_PROFILE_STANDARD), exePath, port, isTCP);
- _AddFirewallRuleForProfile(manage.LocalPolicy.GetProfileByType(NET_FW_PROFILE_TYPE_.NET_FW_PROFILE_CURRENT), exePath, port, isTCP);
+ _AddFirewallRuleForProfile(manage.LocalPolicy.GetProfileByType(NET_FW_PROFILE_TYPE_.NET_FW_PROFILE_STANDARD));
+ _AddFirewallRuleForProfile(manage.LocalPolicy.GetProfileByType(NET_FW_PROFILE_TYPE_.NET_FW_PROFILE_CURRENT));
}
/*public static X509Certificate2 getCert(string subject)
diff --git a/WebserverInitalConfig/Program.cs b/WebserverInitalConfig/Program.cs
index 4b7ce630..a4f3a315 100644
--- a/WebserverInitalConfig/Program.cs
+++ b/WebserverInitalConfig/Program.cs
@@ -16,34 +16,64 @@
#endregion
using System;
+using System.Diagnostics;
using System.IO;
using System.Net;
+using System.Net.Mime;
+using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
namespace WebserverInitalConfig
{
- class Program
+ static class CProgram
{
+ // ReSharper disable InconsistentNaming
private static void Main(string[] args)
+ // ReSharper restore InconsistentNaming
{
- if (args.Length != 2)
+ int port;
+ if (args.Length < 2 || !int.TryParse(args[0], out port))
{
Console.WriteLine("Usage: VocaluxeServerConfig port isHttps");
Environment.Exit(-1);
}
-
- CConfigHttpApi.AddFirewallRule(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Vocaluxe.exe"), Int32.Parse(args[0]), true);
-
- if (args[1].ToLower() == "true")
- {
- string hostname = Dns.GetHostName();
- X509Certificate2 cert = CConfigHttpApi.GetSelfSignedCert("CN=" + hostname + " C=DE O=Vocaluxe OU=Vocaluxe Server");
- CConfigHttpApi.AddCertToStore(cert);
- CConfigHttpApi.BindCert("0.0.0.0", Int32.Parse(args[0]), cert);
- CConfigHttpApi.ReserveUrl("https://+:" + args[0] + "/");
- }
else
- CConfigHttpApi.ReserveUrl("http://+:" + args[0] + "/");
+ {
+ CConfigHttpApi config = new CConfigHttpApi("Vocaluxe", Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Vocaluxe.exe"), "0.0.0.0", port, true);
+ try
+ {
+ config.AddFirewallRule();
+ if (args[1].ToLower() == "true")
+ config.CreateAndAddCert(Dns.GetHostName());
+
+ if ((args.Length >= 3 && args[2] == "reserve") || CConfigHttpApi.IsAdministrator())
+ config.ReserveUrl();
+ }
+ catch (AuthenticationException)
+ {
+ ProcessStartInfo proc = new ProcessStartInfo
+ {
+ UseShellExecute = true,
+ WorkingDirectory = Environment.CurrentDirectory,
+ FileName = Process.GetCurrentProcess().MainModule.FileName,
+ Arguments = args[0] + " " + args[1],
+ Verb = "runas",
+ CreateNoWindow = true,
+ WindowStyle = ProcessWindowStyle.Hidden,
+ };
+
+ try
+ {
+ Process.Start(proc);
+ }
+ catch
+ {
+ // The user refused the elevation.
+ // Do nothing and return directly ...
+ Environment.Exit(-1);
+ }
+ }
+ }
}
}
}
\ No newline at end of file
diff --git a/WebserverInitalConfig/WebserverInitalConfig.csproj b/WebserverInitalConfig/WebserverInitalConfig.csproj
index 7544f7a3..2f48f927 100644
--- a/WebserverInitalConfig/WebserverInitalConfig.csproj
+++ b/WebserverInitalConfig/WebserverInitalConfig.csproj
@@ -32,9 +32,6 @@
prompt
4
-
- app.manifest
-
Vocaluxe.ico