Statistics
| Branch: | Tag: | Revision:

root / lib / serializer.py @ 2419060d

History | View | Annotate | Download (3.1 kB)

1 8d14b30d Iustin Pop
#
2 8d14b30d Iustin Pop
#
3 8d14b30d Iustin Pop
4 8d14b30d Iustin Pop
# Copyright (C) 2007, 2008 Google Inc.
5 8d14b30d Iustin Pop
#
6 8d14b30d Iustin Pop
# This program is free software; you can redistribute it and/or modify
7 8d14b30d Iustin Pop
# it under the terms of the GNU General Public License as published by
8 8d14b30d Iustin Pop
# the Free Software Foundation; either version 2 of the License, or
9 8d14b30d Iustin Pop
# (at your option) any later version.
10 8d14b30d Iustin Pop
#
11 8d14b30d Iustin Pop
# This program is distributed in the hope that it will be useful, but
12 8d14b30d Iustin Pop
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 8d14b30d Iustin Pop
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 8d14b30d Iustin Pop
# General Public License for more details.
15 8d14b30d Iustin Pop
#
16 8d14b30d Iustin Pop
# You should have received a copy of the GNU General Public License
17 8d14b30d Iustin Pop
# along with this program; if not, write to the Free Software
18 8d14b30d Iustin Pop
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 8d14b30d Iustin Pop
# 02110-1301, USA.
20 8d14b30d Iustin Pop
21 8d14b30d Iustin Pop
"""Serializer abstraction module
22 8d14b30d Iustin Pop

23 8d14b30d Iustin Pop
This module introduces a simple abstraction over the serialization
24 8d14b30d Iustin Pop
backend (currently json).
25 8d14b30d Iustin Pop

26 8d14b30d Iustin Pop
"""
27 8d14b30d Iustin Pop
28 8d14b30d Iustin Pop
import simplejson
29 8d14b30d Iustin Pop
import re
30 f4a2f532 Guido Trotter
import hmac
31 f4a2f532 Guido Trotter
32 f4a2f532 Guido Trotter
from ganeti import errors
33 8d14b30d Iustin Pop
34 541822e0 Guido Trotter
try:
35 541822e0 Guido Trotter
  from hashlib import sha1
36 541822e0 Guido Trotter
except ImportError:
37 541822e0 Guido Trotter
  import sha as sha1
38 071448fb Michael Hanselmann
39 8d14b30d Iustin Pop
# Check whether the simplejson module supports indentation
40 8d14b30d Iustin Pop
_JSON_INDENT = 2
41 8d14b30d Iustin Pop
try:
42 8d14b30d Iustin Pop
  simplejson.dumps(1, indent=_JSON_INDENT)
43 8d14b30d Iustin Pop
except TypeError:
44 8d14b30d Iustin Pop
  _JSON_INDENT = None
45 8d14b30d Iustin Pop
46 e91ffe49 Michael Hanselmann
_RE_EOLSP = re.compile('[ \t]+$', re.MULTILINE)
47 8d14b30d Iustin Pop
48 8d14b30d Iustin Pop
49 071448fb Michael Hanselmann
def DumpJson(data, indent=True):
50 8d14b30d Iustin Pop
  """Serialize a given object.
51 8d14b30d Iustin Pop

52 c41eea6e Iustin Pop
  @param data: the data to serialize
53 c41eea6e Iustin Pop
  @param indent: whether to indent output (depends on simplejson version)
54 c41eea6e Iustin Pop

55 c41eea6e Iustin Pop
  @return: the string representation of data
56 071448fb Michael Hanselmann

57 8d14b30d Iustin Pop
  """
58 071448fb Michael Hanselmann
  if not indent or _JSON_INDENT is None:
59 8d14b30d Iustin Pop
    txt = simplejson.dumps(data)
60 8d14b30d Iustin Pop
  else:
61 8d14b30d Iustin Pop
    txt = simplejson.dumps(data, indent=_JSON_INDENT)
62 071448fb Michael Hanselmann
63 e91ffe49 Michael Hanselmann
  txt = _RE_EOLSP.sub("", txt)
64 8d14b30d Iustin Pop
  if not txt.endswith('\n'):
65 8d14b30d Iustin Pop
    txt += '\n'
66 8d14b30d Iustin Pop
  return txt
67 8d14b30d Iustin Pop
68 8d14b30d Iustin Pop
69 228538cf Michael Hanselmann
def LoadJson(txt):
70 8d14b30d Iustin Pop
  """Unserialize data from a string.
71 8d14b30d Iustin Pop

72 c41eea6e Iustin Pop
  @param txt: the json-encoded form
73 c41eea6e Iustin Pop

74 c41eea6e Iustin Pop
  @return: the original data
75 c41eea6e Iustin Pop

76 8d14b30d Iustin Pop
  """
77 8d14b30d Iustin Pop
  return simplejson.loads(txt)
78 228538cf Michael Hanselmann
79 228538cf Michael Hanselmann
80 f4a2f532 Guido Trotter
def DumpSignedJson(data, key, salt=None):
81 f4a2f532 Guido Trotter
  """Serialize a given object and authenticate it.
82 f4a2f532 Guido Trotter

83 f4a2f532 Guido Trotter
  @param data: the data to serialize
84 f4a2f532 Guido Trotter
  @param key: shared hmac key
85 f4a2f532 Guido Trotter
  @return: the string representation of data signed by the hmac key
86 f4a2f532 Guido Trotter

87 f4a2f532 Guido Trotter
  """
88 f4a2f532 Guido Trotter
  txt = DumpJson(data, indent=False)
89 f4a2f532 Guido Trotter
  if salt is None:
90 f4a2f532 Guido Trotter
    salt = ''
91 f4a2f532 Guido Trotter
  signed_dict = {
92 f4a2f532 Guido Trotter
    'msg': txt,
93 f4a2f532 Guido Trotter
    'salt': salt,
94 541822e0 Guido Trotter
    'hmac': hmac.new(key, salt + txt, sha1).hexdigest(),
95 f4a2f532 Guido Trotter
  }
96 40765aa0 Guido Trotter
  return DumpJson(signed_dict, indent=False)
97 f4a2f532 Guido Trotter
98 f4a2f532 Guido Trotter
99 4e9dac14 Guido Trotter
def LoadSignedJson(txt, key):
100 f4a2f532 Guido Trotter
  """Verify that a given message was signed with the given key, and load it.
101 f4a2f532 Guido Trotter

102 f4a2f532 Guido Trotter
  @param txt: json-encoded hmac-signed message
103 f4a2f532 Guido Trotter
  @param key: shared hmac key
104 f4a2f532 Guido Trotter
  @rtype: tuple of original data, string
105 4e9dac14 Guido Trotter
  @return: original data, salt
106 f4a2f532 Guido Trotter
  @raises errors.SignatureError: if the message signature doesn't verify
107 f4a2f532 Guido Trotter

108 f4a2f532 Guido Trotter
  """
109 f4a2f532 Guido Trotter
  signed_dict = LoadJson(txt)
110 f4a2f532 Guido Trotter
  if not isinstance(signed_dict, dict):
111 f4a2f532 Guido Trotter
    raise errors.SignatureError('Invalid external message')
112 f4a2f532 Guido Trotter
  try:
113 f4a2f532 Guido Trotter
    msg = signed_dict['msg']
114 f4a2f532 Guido Trotter
    salt = signed_dict['salt']
115 f4a2f532 Guido Trotter
    hmac_sign = signed_dict['hmac']
116 f4a2f532 Guido Trotter
  except KeyError:
117 f4a2f532 Guido Trotter
    raise errors.SignatureError('Invalid external message')
118 f4a2f532 Guido Trotter
119 541822e0 Guido Trotter
  if hmac.new(key, salt + msg, sha1).hexdigest() != hmac_sign:
120 f4a2f532 Guido Trotter
    raise errors.SignatureError('Invalid Signature')
121 f4a2f532 Guido Trotter
122 4e9dac14 Guido Trotter
  return LoadJson(msg), salt
123 f4a2f532 Guido Trotter
124 f4a2f532 Guido Trotter
125 228538cf Michael Hanselmann
Dump = DumpJson
126 228538cf Michael Hanselmann
Load = LoadJson
127 f4a2f532 Guido Trotter
DumpSigned = DumpSignedJson
128 f4a2f532 Guido Trotter
LoadSigned = LoadSignedJson