Пример #1
0
        /// <summary>
        /// Parses a RemoteAddress element
        /// </summary>
        /// <param name="element">The element to parse.</param>
        private void ParseRemoteAddressElement(Intermediate intermediate, IntermediateSection section, XElement element, ref string remoteAddresses)
        {
            SourceLineNumber sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);

            // no attributes
            foreach (XAttribute attrib in element.Attributes())
            {
                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
                {
                    this.ParseHelper.UnexpectedAttribute(element, attrib);
                }
                else
                {
                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
                }
            }

            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);

            string address = this.ParseHelper.GetTrimmedInnerText(element);

            if (String.IsNullOrEmpty(address))
            {
                this.Messaging.Write(FirewallErrors.IllegalEmptyRemoteAddress(sourceLineNumbers));
            }
            else
            {
                if (String.IsNullOrEmpty(remoteAddresses))
                {
                    remoteAddresses = address;
                }
                else
                {
                    remoteAddresses = String.Concat(remoteAddresses, ",", address);
                }
            }
        }
        /// <summary>
        /// Parses a FirewallException element.
        /// </summary>
        /// <param name="element">The element to parse.</param>
        /// <param name="componentId">Identifier of the component that owns this firewall exception.</param>
        /// <param name="fileId">The file identifier of the parent element (null if nested under Component).</param>
        private void ParseFirewallExceptionElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string fileId)
        {
            var        sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
            Identifier id              = null;
            string     name            = null;
            int        attributes      = 0;
            string     file            = null;
            string     program         = null;
            string     port            = null;
            int?       protocol        = null;
            int?       profile         = null;
            string     scope           = null;
            string     remoteAddresses = null;
            string     description     = null;
            int?       direction       = null;

            foreach (var attrib in element.Attributes())
            {
                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
                {
                    switch (attrib.Name.LocalName)
                    {
                    case "Id":
                        id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
                        break;

                    case "Name":
                        name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
                        break;

                    case "File":
                        if (null != fileId)
                        {
                            this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, "File", "File"));
                        }
                        else
                        {
                            file = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                        }
                        break;

                    case "IgnoreFailure":
                        if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                        {
                            attributes |= 0x1;     // feaIgnoreFailures
                        }
                        break;

                    case "Program":
                        if (null != fileId)
                        {
                            this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, "Program", "File"));
                        }
                        else
                        {
                            program = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
                        }
                        break;

                    case "Port":
                        port = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
                        break;

                    case "Protocol":
                        var protocolValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
                        switch (protocolValue)
                        {
                        case "tcp":
                            protocol = FirewallConstants.NET_FW_IP_PROTOCOL_TCP;
                            break;

                        case "udp":
                            protocol = FirewallConstants.NET_FW_IP_PROTOCOL_UDP;
                            break;

                        default:
                            this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Protocol", protocolValue, "tcp", "udp"));
                            break;
                        }
                        break;

                    case "Scope":
                        scope = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
                        switch (scope)
                        {
                        case "any":
                            remoteAddresses = "*";
                            break;

                        case "localSubnet":
                            remoteAddresses = "LocalSubnet";
                            break;

                        default:
                            this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Scope", scope, "any", "localSubnet"));
                            break;
                        }
                        break;

                    case "Profile":
                        var profileValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
                        switch (profileValue)
                        {
                        case "domain":
                            profile = FirewallConstants.NET_FW_PROFILE2_DOMAIN;
                            break;

                        case "private":
                            profile = FirewallConstants.NET_FW_PROFILE2_PRIVATE;
                            break;

                        case "public":
                            profile = FirewallConstants.NET_FW_PROFILE2_PUBLIC;
                            break;

                        case "all":
                            profile = FirewallConstants.NET_FW_PROFILE2_ALL;
                            break;

                        default:
                            this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Profile", profileValue, "domain", "private", "public", "all"));
                            break;
                        }
                        break;

                    case "Description":
                        description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
                        break;

                    case "Outbound":
                        direction = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib) == YesNoType.Yes
                                ? FirewallConstants.NET_FW_RULE_DIR_OUT
                                : FirewallConstants.NET_FW_RULE_DIR_IN;
                        break;

                    default:
                        this.ParseHelper.UnexpectedAttribute(element, attrib);
                        break;
                    }
                }
                else
                {
                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
                }
            }

            // parse RemoteAddress children
            foreach (var child in element.Elements())
            {
                if (this.Namespace == child.Name.Namespace)
                {
                    switch (child.Name.LocalName)
                    {
                    case "RemoteAddress":
                        if (null != scope)
                        {
                            this.Messaging.Write(FirewallErrors.IllegalRemoteAddressWithScopeAttribute(sourceLineNumbers));
                        }
                        else
                        {
                            this.ParseRemoteAddressElement(intermediate, section, child, ref remoteAddresses);
                        }
                        break;

                    default:
                        this.ParseHelper.UnexpectedElement(element, child);
                        break;
                    }
                }
                else
                {
                    this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child);
                }
            }

            if (null == id)
            {
                id = this.ParseHelper.CreateIdentifier("fex", name, remoteAddresses, componentId);
            }

            // Name is required
            if (null == name)
            {
                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
            }

            // Scope or child RemoteAddress(es) are required
            if (null == remoteAddresses)
            {
                this.Messaging.Write(ErrorMessages.ExpectedAttributeOrElement(sourceLineNumbers, element.Name.LocalName, "Scope", "RemoteAddress"));
            }

            // can't have both Program and File
            if (null != program && null != file)
            {
                this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "File", "Program"));
            }

            // must be nested under File, have File or Program attributes, or have Port attribute
            if (String.IsNullOrEmpty(fileId) && String.IsNullOrEmpty(file) && String.IsNullOrEmpty(program) && String.IsNullOrEmpty(port))
            {
                this.Messaging.Write(FirewallErrors.NoExceptionSpecified(sourceLineNumbers));
            }

            if (!this.Messaging.EncounteredError)
            {
                // at this point, File attribute and File parent element are treated the same
                if (null != file)
                {
                    fileId = file;
                }

                var symbol = section.AddSymbol(new WixFirewallExceptionSymbol(sourceLineNumbers, id)
                {
                    Name            = name,
                    RemoteAddresses = remoteAddresses,
                    Profile         = profile ?? FirewallConstants.NET_FW_PROFILE2_ALL,
                    ComponentRef    = componentId,
                    Description     = description,
                    Direction       = direction ?? FirewallConstants.NET_FW_RULE_DIR_IN,
                });

                if (!String.IsNullOrEmpty(port))
                {
                    symbol.Port = port;

                    if (!protocol.HasValue)
                    {
                        // default protocol is "TCP"
                        protocol = FirewallConstants.NET_FW_IP_PROTOCOL_TCP;
                    }
                }

                if (protocol.HasValue)
                {
                    symbol.Protocol = protocol.Value;
                }

                if (!String.IsNullOrEmpty(fileId))
                {
                    symbol.Program = $"[#{fileId}]";
                    this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.File, fileId);
                }
                else if (!String.IsNullOrEmpty(program))
                {
                    symbol.Program = program;
                }

                if (CompilerConstants.IntegerNotSet != attributes)
                {
                    symbol.Attributes = attributes;
                }

                this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedFirewallExceptionsInstall", this.Context.Platform, CustomActionPlatforms.ARM64 | CustomActionPlatforms.X64 | CustomActionPlatforms.X86);
                this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedFirewallExceptionsUninstall", this.Context.Platform, CustomActionPlatforms.ARM64 | CustomActionPlatforms.X64 | CustomActionPlatforms.X86);
            }
        }
Пример #3
0
        /// <summary>
        /// Parses a FirewallException element.
        /// </summary>
        /// <param name="element">The element to parse.</param>
        /// <param name="componentId">Identifier of the component that owns this firewall exception.</param>
        /// <param name="fileId">The file identifier of the parent element (null if nested under Component).</param>
        private void ParseFirewallExceptionElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string fileId)
        {
            SourceLineNumber sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
            Identifier       id    = null;
            string           name  = null;
            int    attributes      = 0;
            string file            = null;
            string program         = null;
            string port            = null;
            string protocolValue   = null;
            int?   protocol        = null;
            string profileValue    = null;
            int?   profile         = null;
            string scope           = null;
            string remoteAddresses = null;
            string description     = null;

            foreach (XAttribute attrib in element.Attributes())
            {
                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
                {
                    switch (attrib.Name.LocalName)
                    {
                    case "Id":
                        id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
                        break;

                    case "Name":
                        name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
                        break;

                    case "File":
                        if (null != fileId)
                        {
                            this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, "File", "File"));
                        }
                        else
                        {
                            file = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                        }
                        break;

                    case "IgnoreFailure":
                        if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                        {
                            attributes |= 0x1;     // feaIgnoreFailures
                        }
                        break;

                    case "Program":
                        if (null != fileId)
                        {
                            this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, "Program", "File"));
                        }
                        else
                        {
                            program = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
                        }
                        break;

                    case "Port":
                        port = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
                        break;

                    case "Protocol":
                        protocolValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
                        switch (protocolValue)
                        {
                        case "tcp":
                            protocol = FirewallConstants.NET_FW_IP_PROTOCOL_TCP;
                            break;

                        case "udp":
                            protocol = FirewallConstants.NET_FW_IP_PROTOCOL_UDP;
                            break;

                        default:
                            this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Protocol", protocolValue, "tcp", "udp"));
                            break;
                        }
                        break;

                    case "Scope":
                        scope = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
                        switch (scope)
                        {
                        case "any":
                            remoteAddresses = "*";
                            break;

                        case "localSubnet":
                            remoteAddresses = "LocalSubnet";
                            break;

                        default:
                            this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Scope", scope, "any", "localSubnet"));
                            break;
                        }
                        break;

                    case "Profile":
                        profileValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
                        switch (profileValue)
                        {
                        case "domain":
                            profile = FirewallConstants.NET_FW_PROFILE2_DOMAIN;
                            break;

                        case "private":
                            profile = FirewallConstants.NET_FW_PROFILE2_PRIVATE;
                            break;

                        case "public":
                            profile = FirewallConstants.NET_FW_PROFILE2_PUBLIC;
                            break;

                        case "all":
                            profile = FirewallConstants.NET_FW_PROFILE2_ALL;
                            break;

                        default:
                            this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Profile", profileValue, "domain", "private", "public", "all"));
                            break;
                        }
                        break;

                    case "Description":
                        description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
                        break;

                    default:
                        this.ParseHelper.UnexpectedAttribute(element, attrib);
                        break;
                    }
                }
                else
                {
                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
                }
            }

            // parse RemoteAddress children
            foreach (XElement child in element.Elements())
            {
                if (this.Namespace == child.Name.Namespace)
                {
                    SourceLineNumber childSourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(child);
                    switch (child.Name.LocalName)
                    {
                    case "RemoteAddress":
                        if (null != scope)
                        {
                            this.Messaging.Write(FirewallErrors.IllegalRemoteAddressWithScopeAttribute(sourceLineNumbers));
                        }
                        else
                        {
                            this.ParseRemoteAddressElement(intermediate, section, child, ref remoteAddresses);
                        }
                        break;

                    default:
                        this.ParseHelper.UnexpectedElement(element, child);
                        break;
                    }
                }
                else
                {
                    this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child);
                }
            }

            // Id and Name are required
            if (null == id)
            {
                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Id"));
            }

            if (null == name)
            {
                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
            }

            // Scope or child RemoteAddress(es) are required
            if (null == remoteAddresses)
            {
                this.Messaging.Write(ErrorMessages.ExpectedAttributeOrElement(sourceLineNumbers, element.Name.LocalName, "Scope", "RemoteAddress"));
            }

            // can't have both Program and File
            if (null != program && null != file)
            {
                this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "File", "Program"));
            }

            // must be nested under File, have File or Program attributes, or have Port attribute
            if (String.IsNullOrEmpty(fileId) && String.IsNullOrEmpty(file) && String.IsNullOrEmpty(program) && String.IsNullOrEmpty(port))
            {
                this.Messaging.Write(FirewallErrors.NoExceptionSpecified(sourceLineNumbers));
            }

            if (!this.Messaging.EncounteredError)
            {
                // at this point, File attribute and File parent element are treated the same
                if (null != file)
                {
                    fileId = file;
                }

                var row = this.ParseHelper.CreateRow(section, sourceLineNumbers, "WixFirewallException", id);
                row.Set(1, name);
                row.Set(2, remoteAddresses);

                if (!String.IsNullOrEmpty(port))
                {
                    row.Set(3, port);

                    if (!protocol.HasValue)
                    {
                        // default protocol is "TCP"
                        protocol = FirewallConstants.NET_FW_IP_PROTOCOL_TCP;
                    }
                }

                if (protocol.HasValue)
                {
                    row.Set(4, protocol);
                }

                if (!String.IsNullOrEmpty(fileId))
                {
                    row.Set(5, $"[#{fileId}]");
                    this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "File", fileId);
                }
                else if (!String.IsNullOrEmpty(program))
                {
                    row.Set(5, program);
                }

                if (CompilerConstants.IntegerNotSet != attributes)
                {
                    row.Set(6, attributes);
                }

                // Default is "all"
                row.Set(7, profile ?? FirewallConstants.NET_FW_PROFILE2_ALL);

                row.Set(8, componentId);

                row.Set(9, description);

                if (this.Context.Platform == Platform.ARM)
                {
                    // Ensure ARM version of the CA is referenced
                    this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "CustomAction", "WixSchedFirewallExceptionsInstall_ARM");
                    this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "CustomAction", "WixSchedFirewallExceptionsUninstall_ARM");
                }
                else
                {
                    // All other supported platforms use x86
                    this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "CustomAction", "WixSchedFirewallExceptionsInstall");
                    this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "CustomAction", "WixSchedFirewallExceptionsUninstall");
                }
            }
        }