Revision 4e9dac14

b/lib/serializer.py
96 96
  return DumpJson(signed_dict)
97 97

  
98 98

  
99
def LoadSignedJson(txt, key, salt_verifier=None):
99
def LoadSignedJson(txt, key):
100 100
  """Verify that a given message was signed with the given key, and load it.
101 101

  
102 102
  @param txt: json-encoded hmac-signed message
103 103
  @param key: shared hmac key
104
  @param salt_verifier: function taking a salt as input and returning boolean
105 104
  @rtype: tuple of original data, string
106
  @return: original data
105
  @return: original data, salt
107 106
  @raises errors.SignatureError: if the message signature doesn't verify
108 107

  
109 108
  """
......
117 116
  except KeyError:
118 117
    raise errors.SignatureError('Invalid external message')
119 118

  
120
  if salt and not salt_verifier:
121
    raise errors.SignatureError('Salted message is not verified')
122
  elif salt_verifier is not None:
123
    if not salt_verifier(salt):
124
      raise errors.SignatureError('Invalid salt')
125

  
126 119
  if hmac.new(key, salt + msg, sha1).hexdigest() != hmac_sign:
127 120
    raise errors.SignatureError('Invalid Signature')
128
  return LoadJson(msg)
129

  
130

  
131
def SaltEqualTo(expected):
132
  """Helper salt verifier function that checks for equality.
133

  
134
  @type expected: string
135
  @param expected: expected salt
136
  @rtype: function
137
  @return: salt verifier that returns True if the target salt is "x"
138

  
139
  """
140
  return lambda salt: salt == expected
141

  
142

  
143
def SaltIn(expected):
144
  """Helper salt verifier function that checks for membership.
145

  
146
  @type expected: collection
147
  @param expected: collection of possible valid salts
148
  @rtype: function
149
  @return: salt verifier that returns True if the salt is in the collection
150

  
151
  """
152
  return lambda salt: salt in expected
153

  
154

  
155
def SaltInRange(min, max):
156
  """Helper salt verifier function that checks for integer range.
157

  
158
  @type min: integer
159
  @param min: minimum salt value
160
  @type max: integer
161
  @param max: maximum salt value
162
  @rtype: function
163
  @return: salt verifier that returns True if the salt is in the min,max range
164

  
165
  """
166
  def _CheckSaltInRange(salt):
167
    try:
168
      i_salt = int(salt)
169
    except (TypeError, ValueError), err:
170
      return False
171

  
172
    return i_salt > min and i_salt < max
173 121

  
174
  return _CheckSaltInRange
122
  return LoadJson(msg), salt
175 123

  
176 124

  
177 125
Dump = DumpJson
b/test/ganeti.serializer_unittest.py
63 63
  def testSignedMessage(self):
64 64
    LoadSigned = serializer.LoadSigned
65 65
    DumpSigned = serializer.DumpSigned
66
    SaltEqualTo = serializer.SaltEqualTo
67
    SaltIn = serializer.SaltIn
68
    SaltInRange = serializer.SaltInRange
69 66

  
70 67
    for data in self._TESTDATA:
71
      self.assertEqual(LoadSigned(DumpSigned(data, "mykey"), "mykey"), data)
68
      self.assertEqual(LoadSigned(DumpSigned(data, "mykey"), "mykey"),
69
                       (data, ''))
72 70
      self.assertEqual(LoadSigned(
73 71
                         DumpSigned(data, "myprivatekey", "mysalt"),
74
                         "myprivatekey", SaltEqualTo("mysalt")), data)
75
      self.assertEqual(LoadSigned(
76
                         DumpSigned(data, "myprivatekey", "mysalt"),
77
                         "myprivatekey", SaltIn(["notmysalt", "mysalt"])), data)
78
      self.assertEqual(LoadSigned(
79
                         DumpSigned(data, "myprivatekey", "12345"),
80
                         "myprivatekey", SaltInRange(12340, 12346)), data)
72
                         "myprivatekey"), (data, "mysalt"))
81 73
    self.assertRaises(errors.SignatureError, serializer.LoadSigned,
82 74
                      serializer.DumpSigned("test", "myprivatekey"),
83 75
                      "myotherkey")
84
    self.assertRaises(errors.SignatureError, serializer.LoadSigned,
85
                      serializer.DumpSigned("test", "myprivatekey", "salt"),
86
                      "myprivatekey")
87
    self.assertRaises(errors.SignatureError, serializer.LoadSigned,
88
                      serializer.DumpSigned("test", "myprivatekey", "salt"),
89
                      "myprivatekey", SaltIn(["notmysalt", "morenotmysalt"]))
90
    self.assertRaises(errors.SignatureError, serializer.LoadSigned,
91
                      serializer.DumpSigned("test", "myprivatekey", "salt"),
92
                      "myprivatekey", SaltInRange(1, 2))
93
    self.assertRaises(errors.SignatureError, serializer.LoadSigned,
94
                      serializer.DumpSigned("test", "myprivatekey", "12345"),
95
                      "myprivatekey", SaltInRange(1, 2))
96 76

  
97 77
  def _TestSerializer(self, dump_fn, load_fn):
98 78
    for data in self._TESTDATA:

Also available in: Unified diff