1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 import sys
21 import hashlib
22 import time
23 import random
24 import socket
25 import string
26 try:
27
28 import xmlrpclib
29 except ImportError:
30
31 import xmlrpc.client as xmlrpclib
32
33 from spacewalk.common.rhnLog import log_debug, log_error
34 from spacewalk.common.rhnException import rhnFault
35 from spacewalk.common.stringutils import to_string
36 from server_lib import getServerSecret
37
38
40 """ Generate a secret """
41 seed = repr(time.time())
42 sum = hashlib.new('sha256', seed)
43
44 for k in range(1, random.randint(5, 15)):
45 sum.update(repr(random.random()))
46 sum.update(socket.gethostname())
47 ret = ""
48 for i in sum.digest()[:]:
49 ret = ret + "%02x" % ord(i)
50 del sum
51 return ret
52
53
55
56 """ Functions for handling system_id strings """
57
58 - def __init__(self, secret, *args, **kwargs):
59 algo = 'sha256'
60 if 'algo' in kwargs:
61 algo = kwargs['algo']
62 self.sum = hashlib.new(algo, secret)
63 if len(args) > 0:
64 self.feed(*args)
65
66 - def feed(self, arg):
67
68 if type(arg) == type(()) or type(arg) == type([]):
69 for s in arg:
70 self.sum.update(s)
71 else:
72 if type(arg) == type(0):
73 arg = str(arg)
74 self.sum.update(to_string(arg))
75
77 t = ""
78 for i in self.sum.digest()[:]:
79 t = t + "%02x" % ord(i)
80 return t
81 __str__ = __repr__
82
83
85
86 """ Main certificate class """
87 CheckSumFields = ["username", "os_release", "operating_system",
88 "architecture", "system_id", "type"]
89
91 """ init data
92 normally we include in the attrs:
93 username, os_release, os, arch, system_id and fields
94 """
95 self.attrs = {}
96 for k in Certificate.CheckSumFields:
97 self.attrs[k] = None
98 self.__fields = []
99 self.__secret = None
100 self.__checksum = None
101
103 """ function that make it look like a dictionary for easy access """
104 return self.attrs.get(key)
105
107 """ function that make it look like a dictionary for easy access
108 updates the values of the attributes list with new values
109 """
110 self.attrs[name] = value
111 if name in Certificate.CheckSumFields:
112 if name not in self.__fields:
113 self.__fields.append(name)
114 else:
115 if value is None:
116 self.attrs[name] = ""
117 return 0
118
120 """ string format """
121 return "<Certificate instance>: Attrs: %s, Fields: %s, Secret: %s, Checksum: %s" % (
122 self.attrs, self.__fields, self.__secret, self.__checksum)
123 __str__ = __repr__
124
126 """ convert to XML """
127 dump = self.attrs
128 dump["checksum"] = self.__checksum
129 dump["fields"] = self.__fields
130 try:
131 x = xmlrpclib.dumps((dump,))
132 except TypeError:
133 e = sys.exc_info()[1]
134 log_error("Could not marshall certificate for %s" % dump)
135 e.args = e.args + (dump,)
136 raise
137 return '<?xml version="1.0"?>\n%s' % x
138
140 """ Update the checksum """
141 log_debug(4, secret, self.attrs)
142 csum = Checksum(secret, algo=algo)
143 for f in self.__fields:
144 csum.feed(self.attrs[f])
145
146 csum.feed(self.__fields)
147 return str(csum)
148
150 """ set the secret of the entry and recompute the checksum """
151 log_debug(4, "secret", secret)
152 self.__secret = secret
153 self.__checksum = self.compute_checksum(secret)
154
156 """ load data from a text certificate passed on by a client """
157 log_debug(4)
158 text_id = string.strip(text)
159 if not text_id:
160 return -1
161
162 try:
163 sysid, junk = xmlrpclib.loads(to_string(text_id))
164 except:
165 return -1
166 else:
167 s = sysid[0]
168 del junk
169 if "system_id" not in s or not s.has_key("fields"):
170 log_error("Got certificate with missing entries: %s" % s)
171 return -1
172
173 for k in s["fields"]:
174 if k not in s:
175 log_error("Certificate lists unknown %s as a checksum field" % k,
176 "cert data: %s" % s)
177 return -1
178
179
180 self.__init__()
181
182
183
184 for k in s.keys():
185 if k == "fields":
186 self.__fields = s[k]
187 continue
188 if k == "checksum":
189 self.__checksum = s[k]
190 continue
191 self.attrs[k] = s[k]
192
193 return 0
194
196 """ compute the current checksum against a secret and check it against
197 the current checksum
198 """
199 if len(secret) == 64:
200 csum = self.compute_checksum(secret, algo='sha256')
201 elif len(secret) == 32:
202 csum = self.compute_checksum(secret, algo='md5')
203 if not csum == self.__checksum:
204
205 log_error("Checksum check failed: %s != %s" % (csum, self.__checksum),
206 "fields = %s" % str(self.__fields), "attrs = %s" % str(self.attrs))
207 return 0
208 return 1
209
211 log_debug(4)
212
213 if 'type' in self.attrs and self.attrs['type'] \
214 and string.upper(self.attrs['type']) == "ANONYMOUS":
215 raise rhnFault(28, """
216 You need to re-register your system with Red Hat Satellite.
217 Previously you have chosen to skip the creation of a system profile
218 with Red Hat Satellite and this trial feature is no longer available now.
219 """)
220
221 sid = self.attrs["system_id"]
222 secret = getServerSecret(sid)
223 if secret is None:
224
225 log_debug(1, "Server id %s not found in database" % sid)
226 return 0
227 return self.__validate_checksum(secret)
228