From 085ba380e7991013c6bb6dce48dc89f02eca4808 Mon Sep 17 00:00:00 2001 From: Bob Arnson Date: Mon, 17 Feb 2025 22:30:31 -0500 Subject: Support non-SNI SSL certificates in Http extension Implements https://github.com/wixtoolset/issues/issues/7622 --- src/ext/Http/wixext/HttpCompiler.cs | 31 +++++-- src/ext/Http/wixext/HttpTableDefinitions.cs | 13 +-- src/ext/Http/wixext/Symbols/CertificateType.cs | 13 +++ .../Http/wixext/Symbols/HttpCertificateSymbol.cs | 103 +++++++++++++++++++++ .../Http/wixext/Symbols/HttpSymbolDefinitions.cs | 6 +- .../Http/wixext/Symbols/WixHttpSniSslCertSymbol.cs | 95 ------------------- 6 files changed, 150 insertions(+), 111 deletions(-) create mode 100644 src/ext/Http/wixext/Symbols/CertificateType.cs create mode 100644 src/ext/Http/wixext/Symbols/HttpCertificateSymbol.cs delete mode 100644 src/ext/Http/wixext/Symbols/WixHttpSniSslCertSymbol.cs (limited to 'src/ext/Http/wixext') diff --git a/src/ext/Http/wixext/HttpCompiler.cs b/src/ext/Http/wixext/HttpCompiler.cs index 51fdfebc..27ddeb0e 100644 --- a/src/ext/Http/wixext/HttpCompiler.cs +++ b/src/ext/Http/wixext/HttpCompiler.cs @@ -49,7 +49,11 @@ namespace WixToolset.Http switch (element.Name.LocalName) { case "SniSslCertificate": - this.ParseSniSslCertificateElement(intermediate, section, element, componentId); + this.ParseCertificateElement(intermediate, section, element, componentId, CertificateType.SniSsl); + break; + + case "SslCertificate": + this.ParseCertificateElement(intermediate, section, element, componentId, CertificateType.IpSsl); break; case "UrlReservation": @@ -71,7 +75,7 @@ namespace WixToolset.Http /// /// The element to parse. /// Identifier of the component that owns this SNI SSL Certificate. - private void ParseSniSslCertificateElement(Intermediate intermediate, IntermediateSection section, XElement node, string componentId) + private void ParseCertificateElement(Intermediate intermediate, IntermediateSection section, XElement node, string componentId, CertificateType type) { var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(node); Identifier id = null; @@ -138,13 +142,25 @@ namespace WixToolset.Http // Need the element ID for child element processing, so generate now if not authored. if (null == id) { - id = this.ParseHelper.CreateIdentifier("ssl", componentId, host, port); + var prefix = type == CertificateType.IpSsl ? "ips" : "sni"; + + id = this.ParseHelper.CreateIdentifier(prefix, componentId, host, port); } // Required attributes. if (null == host) { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Host")); + if (type == CertificateType.SniSsl) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Host")); + } + } + else + { + if (type == CertificateType.IpSsl) + { + this.Messaging.Write(ErrorMessages.IllegalAttributeExceptOnElement(sourceLineNumbers, node.Name.LocalName, "Host", "SniSslCertificate")); + } } if (null == port) @@ -162,7 +178,7 @@ namespace WixToolset.Http if (!this.Messaging.EncounteredError) { - section.AddSymbol(new WixHttpSniSslCertSymbol(sourceLineNumbers, id) + section.AddSymbol(new HttpCertificateSymbol(sourceLineNumbers, id) { Host = host, Port = port, @@ -170,11 +186,12 @@ namespace WixToolset.Http AppId = appId, Store = store, HandleExisting = handleExisting, + CertificateType = type, ComponentRef = componentId, }); - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedHttpSniSslCertsInstall", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedHttpSniSslCertsUninstall", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix6SchedHttpCertificatesInstall", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix6SchedHttpCertificatesUninstall", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); } } diff --git a/src/ext/Http/wixext/HttpTableDefinitions.cs b/src/ext/Http/wixext/HttpTableDefinitions.cs index ea08337f..ac469b47 100644 --- a/src/ext/Http/wixext/HttpTableDefinitions.cs +++ b/src/ext/Http/wixext/HttpTableDefinitions.cs @@ -6,18 +6,19 @@ namespace WixToolset.Http public static class HttpTableDefinitions { - public static readonly TableDefinition WixHttpSniSslCert = new TableDefinition( - "Wix4HttpSniSslCert", - HttpSymbolDefinitions.WixHttpSniSslCert, + public static readonly TableDefinition HttpCertificate = new TableDefinition( + "Wix6HttpCertificate", + HttpSymbolDefinitions.HttpCertificate, new[] { - new ColumnDefinition("Wix4HttpSniSslCert", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "The non-localized primary key for the table.", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("Host", ColumnType.String, 0, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Host for the SNI SSL certificate.", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("HttpCertificate", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "The non-localized primary key for the table.", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Host", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Host for the SNI SSL certificate.", modularizeType: ColumnModularizeType.Property), new ColumnDefinition("Port", ColumnType.String, 0, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Port for the SNI SSL certificate.", modularizeType: ColumnModularizeType.Property), new ColumnDefinition("Thumbprint", ColumnType.String, 0, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "humbprint of the SNI SSL certificate to find.", modularizeType: ColumnModularizeType.Property), new ColumnDefinition("AppId", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Optional application id for the SNI SSL certificate.", modularizeType: ColumnModularizeType.Property), new ColumnDefinition("Store", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Optional application id for the SNI SSL certificate.", modularizeType: ColumnModularizeType.Property), new ColumnDefinition("HandleExisting", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 2, description: "The behavior when trying to install a SNI SSL certificate and it already exists."), + new ColumnDefinition("Type", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 1, description: "0: SNI; 1: non-SNI"), new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table referencing the component that controls the URL reservation.", modularizeType: ColumnModularizeType.Column), }, symbolIdIsPrimaryKey: true @@ -52,7 +53,7 @@ namespace WixToolset.Http public static readonly TableDefinition[] All = new[] { - WixHttpSniSslCert, + HttpCertificate, WixHttpUrlReservation, WixHttpUrlAce, }; diff --git a/src/ext/Http/wixext/Symbols/CertificateType.cs b/src/ext/Http/wixext/Symbols/CertificateType.cs new file mode 100644 index 00000000..1e57ff13 --- /dev/null +++ b/src/ext/Http/wixext/Symbols/CertificateType.cs @@ -0,0 +1,13 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Http.Symbols +{ + /// + /// Must match constants in httpcerts.cpp + /// + public enum CertificateType + { + SniSsl = 0, + IpSsl = 1, + } +} diff --git a/src/ext/Http/wixext/Symbols/HttpCertificateSymbol.cs b/src/ext/Http/wixext/Symbols/HttpCertificateSymbol.cs new file mode 100644 index 00000000..1e361b54 --- /dev/null +++ b/src/ext/Http/wixext/Symbols/HttpCertificateSymbol.cs @@ -0,0 +1,103 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Http +{ + using WixToolset.Data; + using WixToolset.Http.Symbols; + + public static partial class HttpSymbolDefinitions + { + public static readonly IntermediateSymbolDefinition HttpCertificate = new IntermediateSymbolDefinition( + HttpSymbolDefinitionType.HttpCertificate.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(HttpCertificateSymbolFields.Host), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(HttpCertificateSymbolFields.Port), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(HttpCertificateSymbolFields.Thumbprint), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(HttpCertificateSymbolFields.AppId), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(HttpCertificateSymbolFields.Store), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(HttpCertificateSymbolFields.HandleExisting), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(HttpCertificateSymbolFields.CertificateType), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(HttpCertificateSymbolFields.ComponentRef), IntermediateFieldType.String), + }, + typeof(HttpCertificateSymbol)); + } +} + +namespace WixToolset.Http.Symbols +{ + using WixToolset.Data; + + public enum HttpCertificateSymbolFields + { + Host, + Port, + Thumbprint, + AppId, + Store, + HandleExisting, + CertificateType, + ComponentRef, + } + + public class HttpCertificateSymbol : IntermediateSymbol + { + public HttpCertificateSymbol() : base(HttpSymbolDefinitions.HttpCertificate, null, null) + { + } + + public HttpCertificateSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(HttpSymbolDefinitions.HttpCertificate, sourceLineNumber, id) + { + } + + public IntermediateField this[HttpCertificateSymbolFields index] => this.Fields[(int)index]; + + public string Host + { + get => this.Fields[(int)HttpCertificateSymbolFields.Host].AsString(); + set => this.Set((int)HttpCertificateSymbolFields.Host, value); + } + + public string Port + { + get => this.Fields[(int)HttpCertificateSymbolFields.Port].AsString(); + set => this.Set((int)HttpCertificateSymbolFields.Port, value); + } + + public string Thumbprint + { + get => this.Fields[(int)HttpCertificateSymbolFields.Thumbprint].AsString(); + set => this.Set((int)HttpCertificateSymbolFields.Thumbprint, value); + } + + public string AppId + { + get => this.Fields[(int)HttpCertificateSymbolFields.AppId].AsString(); + set => this.Set((int)HttpCertificateSymbolFields.AppId, value); + } + + public string Store + { + get => this.Fields[(int)HttpCertificateSymbolFields.Store].AsString(); + set => this.Set((int)HttpCertificateSymbolFields.Store, value); + } + + public HandleExisting HandleExisting + { + get => (HandleExisting)this.Fields[(int)HttpCertificateSymbolFields.HandleExisting].AsNumber(); + set => this.Set((int)HttpCertificateSymbolFields.HandleExisting, (int)value); + } + + public CertificateType CertificateType + { + get => (CertificateType)this.Fields[(int)HttpCertificateSymbolFields.CertificateType].AsNumber(); + set => this.Set((int)HttpCertificateSymbolFields.CertificateType, (int)value); + } + + public string ComponentRef + { + get => this.Fields[(int)HttpCertificateSymbolFields.ComponentRef].AsString(); + set => this.Set((int)HttpCertificateSymbolFields.ComponentRef, value); + } + } +} diff --git a/src/ext/Http/wixext/Symbols/HttpSymbolDefinitions.cs b/src/ext/Http/wixext/Symbols/HttpSymbolDefinitions.cs index ff46ce3b..37a7abf0 100644 --- a/src/ext/Http/wixext/Symbols/HttpSymbolDefinitions.cs +++ b/src/ext/Http/wixext/Symbols/HttpSymbolDefinitions.cs @@ -7,7 +7,7 @@ namespace WixToolset.Http public enum HttpSymbolDefinitionType { - WixHttpSniSslCert, + HttpCertificate, WixHttpUrlAce, WixHttpUrlReservation, } @@ -28,8 +28,8 @@ namespace WixToolset.Http { switch (type) { - case HttpSymbolDefinitionType.WixHttpSniSslCert: - return HttpSymbolDefinitions.WixHttpSniSslCert; + case HttpSymbolDefinitionType.HttpCertificate: + return HttpSymbolDefinitions.HttpCertificate; case HttpSymbolDefinitionType.WixHttpUrlAce: return HttpSymbolDefinitions.WixHttpUrlAce; diff --git a/src/ext/Http/wixext/Symbols/WixHttpSniSslCertSymbol.cs b/src/ext/Http/wixext/Symbols/WixHttpSniSslCertSymbol.cs deleted file mode 100644 index ec67a089..00000000 --- a/src/ext/Http/wixext/Symbols/WixHttpSniSslCertSymbol.cs +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. - -namespace WixToolset.Http -{ - using WixToolset.Data; - using WixToolset.Http.Symbols; - - public static partial class HttpSymbolDefinitions - { - public static readonly IntermediateSymbolDefinition WixHttpSniSslCert = new IntermediateSymbolDefinition( - HttpSymbolDefinitionType.WixHttpSniSslCert.ToString(), - new[] - { - new IntermediateFieldDefinition(nameof(WixHttpSniSslCertSymbolFields.Host), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(WixHttpSniSslCertSymbolFields.Port), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(WixHttpSniSslCertSymbolFields.Thumbprint), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(WixHttpSniSslCertSymbolFields.AppId), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(WixHttpSniSslCertSymbolFields.Store), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(WixHttpSniSslCertSymbolFields.HandleExisting), IntermediateFieldType.Number), - new IntermediateFieldDefinition(nameof(WixHttpSniSslCertSymbolFields.ComponentRef), IntermediateFieldType.String), - }, - typeof(WixHttpSniSslCertSymbol)); - } -} - -namespace WixToolset.Http.Symbols -{ - using WixToolset.Data; - - public enum WixHttpSniSslCertSymbolFields - { - Host, - Port, - Thumbprint, - AppId, - Store, - HandleExisting, - ComponentRef, - } - - public class WixHttpSniSslCertSymbol : IntermediateSymbol - { - public WixHttpSniSslCertSymbol() : base(HttpSymbolDefinitions.WixHttpSniSslCert, null, null) - { - } - - public WixHttpSniSslCertSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(HttpSymbolDefinitions.WixHttpSniSslCert, sourceLineNumber, id) - { - } - - public IntermediateField this[WixHttpSniSslCertSymbolFields index] => this.Fields[(int)index]; - - public string Host - { - get => this.Fields[(int)WixHttpSniSslCertSymbolFields.Host].AsString(); - set => this.Set((int)WixHttpSniSslCertSymbolFields.Host, value); - } - - public string Port - { - get => this.Fields[(int)WixHttpSniSslCertSymbolFields.Port].AsString(); - set => this.Set((int)WixHttpSniSslCertSymbolFields.Port, value); - } - - public string Thumbprint - { - get => this.Fields[(int)WixHttpSniSslCertSymbolFields.Thumbprint].AsString(); - set => this.Set((int)WixHttpSniSslCertSymbolFields.Thumbprint, value); - } - - public string AppId - { - get => this.Fields[(int)WixHttpSniSslCertSymbolFields.AppId].AsString(); - set => this.Set((int)WixHttpSniSslCertSymbolFields.AppId, value); - } - - public string Store - { - get => this.Fields[(int)WixHttpSniSslCertSymbolFields.Store].AsString(); - set => this.Set((int)WixHttpSniSslCertSymbolFields.Store, value); - } - - public HandleExisting HandleExisting - { - get => (HandleExisting)this.Fields[(int)WixHttpSniSslCertSymbolFields.HandleExisting].AsNumber(); - set => this.Set((int)WixHttpSniSslCertSymbolFields.HandleExisting, (int)value); - } - - public string ComponentRef - { - get => this.Fields[(int)WixHttpSniSslCertSymbolFields.ComponentRef].AsString(); - set => this.Set((int)WixHttpSniSslCertSymbolFields.ComponentRef, value); - } - } -} -- cgit v1.2.3-55-g6feb