CVE-2012-2654: Improper Input Validation (CWE-20)
value: The (1) EC2 and (2) OS APIs in OpenStack Compute (Nova) Folsom (2012.2), Essex (2012.1), and Diablo (2011.3) do not properly check the protocol when security groups are created and the network protocol is not specified entirely in lowercase, which allows remote attackers to bypass intended access restrictions.
CWE description: The product receives input or data, but it does
        not validate or incorrectly validates that the input has the
        properties that are required to process the data safely and
        correctly.
Published: 2012-06-21T15:55Z
Repository: https://github.com/openstack/nova
Language: Python
Files changed: nova/api/ec2/cloud.py, nova/api/openstack/compute/contrib/security_groups.py, nova/virt/firewall.py
Commit date: 2012-06-06 13:25:04 -0400
Commit message: Fix up protocol case handling for security groups.

Fix bug 985184.

When creating security group rules, any case for the protocol was
accepted as input, such as TCP, Tcp, tcp, etc., and was stored in the
database as specified.  However, unless specified as all lowercase, the
code to apply the rules would break and result in some rules not being
applied.

Change-Id: I6c723d371579eb37a94bd484d39beeb773668ed4

Diff: diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py
index 43686aa12a..723c7fca74 100644
--- a/nova/api/ec2/cloud.py
+++ b/nova/api/ec2/cloud.py
@@ -596,11 +596,11 @@ class CloudController(object):
                 to_port < -1 or to_port > 255)):
                 raise exception.InvalidPortRange(from_port=from_port,
                       to_port=to_port, msg="For ICMP, the"
                                            " type:code must be valid")
 
-            values['protocol'] = ip_protocol
+            values['protocol'] = ip_protocol.lower()
             values['from_port'] = from_port
             values['to_port'] = to_port
         else:
             # If cidr based filtering, protocol and ports are mandatory
             if 'cidr' in values:
diff --git a/nova/api/openstack/compute/contrib/security_groups.py b/nova/api/openstack/compute/contrib/security_groups.py
index 7e3f937521..4a69d392ea 100644
--- a/nova/api/openstack/compute/contrib/security_groups.py
+++ b/nova/api/openstack/compute/contrib/security_groups.py
@@ -522,11 +522,11 @@ class SecurityGroupRulesController(SecurityGroupControllerBase):
                 to_port < -1 or to_port > 255)):
                 raise exception.InvalidPortRange(from_port=from_port,
                       to_port=to_port, msg="For ICMP, the"
                                            " type:code must be valid")
 
-            values['protocol'] = ip_protocol
+            values['protocol'] = ip_protocol.lower()
             values['from_port'] = from_port
             values['to_port'] = to_port
         else:
             # If cidr based filtering, protocol and ports are mandatory
             if 'cidr' in values:
diff --git a/nova/virt/firewall.py b/nova/virt/firewall.py
index bca50d21f3..be6a0f7c97 100644
--- a/nova/virt/firewall.py
+++ b/nova/virt/firewall.py
@@ -329,12 +329,12 @@ class IptablesFirewallDriver(FirewallDriver):
                 if version == 4:
                     fw_rules = ipv4_rules
                 else:
                     fw_rules = ipv6_rules
 
-                protocol = rule.protocol
-                if version == 6 and rule.protocol == 'icmp':
+                protocol = rule.protocol.lower()
+                if version == 6 and protocol == 'icmp':
                     protocol = 'icmpv6'
 
                 args = ['-j ACCEPT']
                 if protocol:
                     args += ['-p', protocol]

Vulnerable code:             values['protocol'] = ip_protocol
            values['protocol'] = ip_protocol
                protocol = rule.protocol
                if version == 6 and rule.protocol == 'icmp':
Fixed code:             values['protocol'] = ip_protocol.lower()
            values['protocol'] = ip_protocol.lower()
                protocol = rule.protocol.lower()
                if version == 6 and protocol == 'icmp':