using XFEEliteDangerous.Client; using System.Net; using System.Security.AccessControl; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Security.Principal; using System.Text.Json; using XFEEliteDangerous.Core; namespace XFEEliteDangerous.Server; public sealed record OnlineServerOptions(string BindAddress="0.0.0.0",int Port=48081,bool Enabled=true) { public void Validate(){if(Port is <1024 or >65535||!IPAddress.TryParse(BindAddress,out var ip)||ip.AddressFamily!=System.Net.Sockets.AddressFamily.InterNetwork)throw new InvalidDataException(AppText.Get("OnlineServerOptions.Text456"));} public X509Certificate2 OpenCertificate(string dataRoot) { Validate();var file=Path.Combine(dataRoot,"game-server.pfx"); if(!File.Exists(file)) { using var key=RSA.Create(3072);var request=new CertificateRequest("CN=XFEEliteDangerous private server",key,HashAlgorithmName.SHA256,RSASignaturePadding.Pkcs1); request.CertificateExtensions.Add(new X509BasicConstraintsExtension(false,false,0,true)); request.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature|X509KeyUsageFlags.KeyEncipherment,true)); var san=new SubjectAlternativeNameBuilder();san.AddDnsName("localhost");san.AddIpAddress(IPAddress.Loopback);request.CertificateExtensions.Add(san.Build()); using var created=request.CreateSelfSigned(DateTimeOffset.UtcNow.AddMinutes(-5),DateTimeOffset.UtcNow.AddYears(5)); using var output=new FileStream(file,FileMode.CreateNew,FileAccess.Write,FileShare.None);output.Write(created.Export(X509ContentType.Pkcs12));output.Flush(true); } if(OperatingSystem.IsWindows()) { var security=new FileSecurity();security.SetAccessRuleProtection(true,false); foreach(var sid in new[]{WindowsIdentity.GetCurrent().User!,new SecurityIdentifier(WellKnownSidType.LocalSystemSid,null)})security.AddAccessRule(new FileSystemAccessRule(sid,FileSystemRights.FullControl,AccessControlType.Allow)); new FileInfo(file).SetAccessControl(security); } else File.SetUnixFileMode(file,UnixFileMode.UserRead|UnixFileMode.UserWrite); var certificate=X509CertificateLoader.LoadPkcs12FromFile(file,null,OperatingSystem.IsWindows()?X509KeyStorageFlags.UserKeySet:X509KeyStorageFlags.EphemeralKeySet); var host=BindAddress=="0.0.0.0"?"localhost":BindAddress; var profile=new OnlineServerProfile($"https://{host}:{Port}/game/",Convert.ToHexStringLower(SHA256.HashData(certificate.RawData))); File.WriteAllText(Path.Combine(dataRoot,"game-client.json"),JsonSerializer.Serialize(profile,GameLinkJson.Default.OnlineServerProfile)); return certificate; } }