~ubuntu-branches/ubuntu/quantal/keystone/quantal-security

« back to all changes in this revision

Viewing changes to .pc/CVE-2013-1664+1665.patch/keystone/common/serializer.py

  • Committer: Package Import Robot
  • Author(s): Jamie Strandboge
  • Date: 2013-06-13 13:42:44 UTC
  • mfrom: (35.1.6 quantal-proposed)
  • Revision ID: package-import@ubuntu.com-20130613134244-mle4ueu39urzeknr
Tags: 2012.2.4-0ubuntu3.1
* SECURITY UPDATE: fix auth_token middleware neglects to check expiry of
  signed token when using PKI
  - debian/patches/CVE-2013-2104.patch: explicitly check the expiry on the
    tokens, and reject tokens that have expired. Also update test data
  - CVE-2013-2104
  - LP: #1179615
* debian/patches/fix-testsuite-for-2038-problem.patch: Adjust json example
  cert data to use 2037 instead of 2112 and regenerate the certs. Also
  adjust token expiry data to use 2037 instead of 2999.
* SECURITY UPDATE: fix authentication bypass when using LDAP backend
  - debian/patches/CVE-2013-2157.patch: identity/backends/ldap/core.py is
    adjusted to raise an assertion for invalid password when using LDAP and
    an empty password is submitted
  - CVE-2013-2157
  - LP: #1187305

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
 
 
3
 
# Copyright 2012 OpenStack LLC
4
 
#
5
 
# Licensed under the Apache License, Version 2.0 (the "License"); you may
6
 
# not use this file except in compliance with the License. You may obtain
7
 
# a copy of the License at
8
 
#
9
 
#      http://www.apache.org/licenses/LICENSE-2.0
10
 
#
11
 
# Unless required by applicable law or agreed to in writing, software
12
 
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
 
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
 
# License for the specific language governing permissions and limitations
15
 
# under the License.
16
 
 
17
 
"""
18
 
Dict <--> XML de/serializer.
19
 
 
20
 
The identity API prefers attributes over elements, so we serialize that way
21
 
by convention, with a few hardcoded exceptions.
22
 
 
23
 
"""
24
 
 
25
 
from lxml import etree
26
 
import re
27
 
 
28
 
 
29
 
DOCTYPE = '<?xml version="1.0" encoding="UTF-8"?>'
30
 
XMLNS = 'http://docs.openstack.org/identity/api/v2.0'
31
 
 
32
 
 
33
 
def from_xml(xml):
34
 
    """Deserialize XML to a dictionary."""
35
 
    if xml is None:
36
 
        return None
37
 
 
38
 
    deserializer = XmlDeserializer()
39
 
    return deserializer(xml)
40
 
 
41
 
 
42
 
def to_xml(d, xmlns=None):
43
 
    """Serialize a dictionary to XML."""
44
 
    if d is None:
45
 
        return None
46
 
 
47
 
    serialize = XmlSerializer()
48
 
    return serialize(d, xmlns)
49
 
 
50
 
 
51
 
class XmlDeserializer(object):
52
 
    def __call__(self, xml_str):
53
 
        """Returns a dictionary populated by decoding the given xml string."""
54
 
        dom = etree.fromstring(xml_str.strip())
55
 
        return self.walk_element(dom)
56
 
 
57
 
    @staticmethod
58
 
    def _tag_name(tag):
59
 
        """Remove the namespace from the tagname.
60
 
 
61
 
        TODO(dolph): We might care about the namespace at some point.
62
 
 
63
 
        >>> XmlDeserializer._tag_name('{xmlNamespace}tagName')
64
 
        'tagName'
65
 
 
66
 
        """
67
 
        m = re.search('[^}]+$', tag)
68
 
        return m.string[m.start():]
69
 
 
70
 
    def walk_element(self, element):
71
 
        """Populates a dictionary by walking an etree element."""
72
 
        values = {}
73
 
        for k, v in element.attrib.iteritems():
74
 
            # boolean-looking attributes become booleans in JSON
75
 
            if k in ['enabled']:
76
 
                if v in ['true']:
77
 
                    v = True
78
 
                elif v in ['false']:
79
 
                    v = False
80
 
 
81
 
            values[k] = v
82
 
 
83
 
        text = None
84
 
        if element.text is not None:
85
 
            text = element.text.strip()
86
 
 
87
 
        # current spec does not have attributes on an element with text
88
 
        values = values or text or {}
89
 
 
90
 
        for child in [self.walk_element(x) for x in element]:
91
 
            values = dict(values.items() + child.items())
92
 
 
93
 
        return {XmlDeserializer._tag_name(element.tag): values}
94
 
 
95
 
 
96
 
class XmlSerializer(object):
97
 
    def __call__(self, d, xmlns=None):
98
 
        """Returns an xml etree populated by the given dictionary.
99
 
 
100
 
        Optionally, namespace the etree by specifying an ``xmlns``.
101
 
 
102
 
        """
103
 
        # FIXME(dolph): skipping links for now
104
 
        for key in d.keys():
105
 
            if '_links' in key:
106
 
                d.pop(key)
107
 
 
108
 
        assert len(d.keys()) == 1, ('Cannot encode more than one root '
109
 
                                    'element: %s' % d.keys())
110
 
 
111
 
        # name the root dom element
112
 
        name = d.keys()[0]
113
 
 
114
 
        # only the root dom element gets an xlmns
115
 
        root = etree.Element(name, xmlns=(xmlns or XMLNS))
116
 
 
117
 
        self.populate_element(root, d[name])
118
 
 
119
 
        # TODO(dolph): you can get a doctype from lxml, using ElementTrees
120
 
        return '%s\n%s' % (DOCTYPE, etree.tostring(root, pretty_print=True))
121
 
 
122
 
    def _populate_list(self, element, k, v):
123
 
        """Populates an element with a key & list value."""
124
 
        # spec has a lot of inconsistency here!
125
 
        container = element
126
 
 
127
 
        if k == 'media-types':
128
 
            # xsd compliance: <media-types> contains <media-type>s
129
 
            # find an existing <media-types> element or make one
130
 
            container = element.find('media-types')
131
 
            if container is None:
132
 
                container = etree.Element(k)
133
 
                element.append(container)
134
 
            name = k[:-1]
135
 
        elif k == 'serviceCatalog':
136
 
            # xsd compliance: <serviceCatalog> contains <service>s
137
 
            container = etree.Element(k)
138
 
            element.append(container)
139
 
            name = 'service'
140
 
        elif k == 'values' and element.tag[-1] == 's':
141
 
            # OS convention is to contain lists in a 'values' element,
142
 
            # so the list itself can have attributes, which is
143
 
            # unnecessary in XML
144
 
            name = element.tag[:-1]
145
 
        elif k[-1] == 's':
146
 
            name = k[:-1]
147
 
        else:
148
 
            name = k
149
 
 
150
 
        for item in v:
151
 
            child = etree.Element(name)
152
 
            self.populate_element(child, item)
153
 
            container.append(child)
154
 
 
155
 
    def _populate_dict(self, element, k, v):
156
 
        """Populates an element with a key & dictionary value."""
157
 
        child = etree.Element(k)
158
 
        self.populate_element(child, v)
159
 
        element.append(child)
160
 
 
161
 
    def _populate_bool(self, element, k, v):
162
 
        """Populates an element with a key & boolean value."""
163
 
        # booleans are 'true' and 'false'
164
 
        element.set(k, unicode(v).lower())
165
 
 
166
 
    def _populate_str(self, element, k, v):
167
 
        """Populates an element with a key & string value."""
168
 
        if k in ['description']:
169
 
            # always becomes an element
170
 
            child = etree.Element(k)
171
 
            child.text = unicode(v)
172
 
            element.append(child)
173
 
        else:
174
 
            # add attributes to the current element
175
 
            element.set(k, unicode(v))
176
 
 
177
 
    def _populate_number(self, element, k, v):
178
 
        """Populates an element with a key & numeric value."""
179
 
        # numbers can be handled as strings
180
 
        self._populate_str(element, k, v)
181
 
 
182
 
    def populate_element(self, element, value):
183
 
        """Populates an etree with the given value."""
184
 
        if isinstance(value, list):
185
 
            self._populate_sequence(element, value)
186
 
        elif isinstance(value, dict):
187
 
            self._populate_tree(element, value)
188
 
 
189
 
    def _populate_sequence(self, element, l):
190
 
        """Populates an etree with a sequence of elements, given a list."""
191
 
        # xsd compliance: child elements are singular: <users> has <user>s
192
 
        name = element.tag
193
 
        if element.tag[-1] == 's':
194
 
            name = element.tag[:-1]
195
 
 
196
 
        for item in l:
197
 
            child = etree.Element(name)
198
 
            self.populate_element(child, item)
199
 
            element.append(child)
200
 
 
201
 
    def _populate_tree(self, element, d):
202
 
        """Populates an etree with attributes & elements, given a dict."""
203
 
        for k, v in d.iteritems():
204
 
            if isinstance(v, dict):
205
 
                self._populate_dict(element, k, v)
206
 
            elif isinstance(v, list):
207
 
                self._populate_list(element, k, v)
208
 
            elif isinstance(v, bool):
209
 
                self._populate_bool(element, k, v)
210
 
            elif isinstance(v, basestring):
211
 
                self._populate_str(element, k, v)
212
 
            elif type(v) in [int, float, long, complex]:
213
 
                self._populate_number(element, k, v)