1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import os
20 import time
21 import socket
22 import xmlrpclib
23 import sys
24
25 from hashlib import sha1
26
27
28 from spacewalk.common.rhnLib import parseUrl
29 from spacewalk.common.rhnTB import Traceback
30 from spacewalk.common.rhnLog import log_debug, log_error
31 from spacewalk.common.rhnConfig import CFG
32 from spacewalk.common.rhnException import rhnFault
33 from spacewalk.common import rhnCache
34 from spacewalk.common.rhnTranslate import _
35
36
37 from rhn import rpclib
38 from rhn import SSL
39 import rhnAuthCacheClient
40
41
42 sys.path.append('/usr/share/rhn')
43 from up2date_client import config
44
45
46 __PROXY_AUTH = None
47 UP2DATE_CONFIG = config.Config('/etc/sysconfig/rhn/up2date')
57
60
61 __serverid = None
62 __systemid = None
63 __systemid_mtime = None
64 __systemid_filename = UP2DATE_CONFIG['systemIdPath']
65
66 __nRetries = 3
67
68 hostname = None
69
74
76 """ update the systemid/serverid but only if they stat differently.
77 returns 0=no updates made; or 1=updates were made
78 """
79 if not os.access(ProxyAuth.__systemid_filename, os.R_OK):
80 log_error("unable to access %s" % ProxyAuth.__systemid_filename)
81 raise rhnFault(1000,
82 _("Spacewalk Proxy error (Spacewalk Proxy systemid has wrong permissions?). "
83 "Please contact your system administrator."))
84
85 mtime = None
86 try:
87 mtime = os.stat(ProxyAuth.__systemid_filename)[-2]
88 except IOError, e:
89 log_error("unable to stat %s: %s" % (ProxyAuth.__systemid_filename, repr(e)))
90 raise rhnFault(1000,
91 _("Spacewalk Proxy error (Spacewalk Proxy systemid has wrong permissions?). "
92 "Please contact your system administrator.")), None, sys.exc_info()[2]
93
94 if not self.__systemid_mtime:
95 ProxyAuth.__systemid_mtime = mtime
96
97 if self.__systemid_mtime == mtime \
98 and self.__systemid and self.__serverid:
99
100 return 0
101
102
103 try:
104 ProxyAuth.__systemid = open(ProxyAuth.__systemid_filename, 'r').read()
105 except IOError, e:
106 log_error("unable to read %s" % ProxyAuth.__systemid_filename)
107 raise rhnFault(1000,
108 _("Spacewalk Proxy error (Spacewalk Proxy systemid has wrong permissions?). "
109 "Please contact your system administrator.")), None, sys.exc_info()[2]
110
111
112 sysid, _cruft = xmlrpclib.loads(ProxyAuth.__systemid)
113 ProxyAuth.__serverid = sysid[0]['system_id'][3:]
114
115 log_debug(7, 'SystemId: "%s[...snip snip...]%s"'
116 % (ProxyAuth.__systemid[:20], ProxyAuth.__systemid[-20:]))
117 log_debug(7, 'ServerId: %s' % ProxyAuth.__serverid)
118
119
120 return 1
121
126
138
150
152 """ Caches current token in the auth cache.
153 """
154 log_debug(3)
155
156 shelf = get_auth_shelf()
157
158 try:
159 shelf[self.__cache_proxy_key()] = token
160 except:
161 text = _("""\
162 Caching of authentication token for proxy id %s failed!
163 Either the authentication caching daemon is experiencing
164 problems, isn't running, or the token is somehow corrupt.
165 """) % self.__serverid
166 Traceback("ProxyAuth.set_cached_token", extra=text)
167 raise rhnFault(1000,
168 _("Spacewalk Proxy error (auth caching issue). "
169 "Please contact your system administrator.")), None, sys.exc_info()[2]
170 log_debug(4, "successfully returning")
171 return token
172
185
187 """ Login and fetch new token (proxy token).
188
189 How it works in a nutshell.
190 Only the broker component uses this. We perform a xmlrpc request
191 to rhn_parent. This occurs outside of the http process we are
192 currently working on. So, we do this all on our own; do all of
193 our own SSL decisionmaking etc. We use CFG.RHN_PARENT as we always
194 bypass the SSL redirect.
195
196 DESIGN NOTES: what is the proxy auth token?
197 -------------------------------------------
198 An Spacewalk Proxy auth token is a token fetched upon login from
199 Red Hat Satellite or hosted.
200
201 It has this format:
202 'S:U:ST:EO:SIG'
203 Where:
204 S = server ID
205 U = username
206 ST = server time
207 EO = expiration offset
208 SIG = signature
209 H = hostname (important later)
210
211 Within this function within the Spacewalk Proxy Broker we also tag on
212 the hostname to the end of the token. The token as described above
213 is enough for authentication purposes, but we need a to identify
214 the exact hostname (as the Spacewalk Proxy sees it). So now the token
215 becomes (token:hostname):
216 'S:U:ST:EO:SIG:H'
217
218 DESIGN NOTES: what is X-RHN-Proxy-Auth?
219 -------------------------------------------
220 This is where we use the auth token beyond Spacewalk Proxy login
221 purposes. This a header used to track request routes through
222 a hierarchy of RHN Proxies.
223
224 X-RHN-Proxy-Auth is a header that passes proxy authentication
225 information around in the form of an ordered list of tokens. This
226 list is used to gain information as to how a client request is
227 routed throughout an RHN topology.
228
229 Format: 'S1:U1:ST1:EO1:SIG1:H1,S2:U2:ST2:EO2:SIG2:H2,...'
230 |_________1_________| |_________2_________| |__...
231 token token
232 where token is really: token:hostname
233
234 leftmost token was the first token hit by a client request.
235 rightmost token was the last token hit by a client request.
236
237 """
238
239
240 log_debug(3)
241 server = self.__getXmlrpcServer()
242 error = None
243 token = None
244
245 self.__processSystemid()
246
247 for _i in range(self.__nRetries):
248 try:
249 token = server.proxy.login(self.__systemid)
250 except (socket.error, socket.sslerror), e:
251 if CFG.HTTP_PROXY:
252
253 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
254 httpProxy, httpProxyPort = CFG.HTTP_PROXY.split(':')
255 try:
256 s.connect((httpProxy, int(httpProxyPort)))
257 except socket.error, e:
258 error = ['socket.error', 'HTTP Proxy not running? '
259 '(%s) %s' % (CFG.HTTP_PROXY, e)]
260
261 log_error("*** ERROR ***: %s" % error[1])
262 Traceback(mail=0)
263 except socket.sslerror, e:
264 error = ['socket.sslerror',
265 '(%s) %s' % (CFG.HTTP_PROXY, e)]
266
267 log_error("*** ERROR ***: %s" % error[1])
268 Traceback(mail=0)
269 else:
270 error = ['socket', str(e)]
271 log_error(error)
272 Traceback(mail=0)
273 else:
274 log_error("Socket error", e)
275 Traceback(mail=0)
276 Traceback(mail=1)
277 token = None
278 time.sleep(.25)
279 continue
280 except SSL.SSL.Error, e:
281 token = None
282 error = ['rhn.SSL.SSL.Error', repr(e), str(e)]
283 log_error(error)
284 Traceback(mail=0)
285 time.sleep(.25)
286 continue
287 except xmlrpclib.ProtocolError, e:
288 token = None
289 log_error('xmlrpclib.ProtocolError', e)
290 time.sleep(.25)
291 continue
292 except xmlrpclib.Fault, e:
293
294
295
296
297
298
299 log_error("%s" % e)
300 if e.faultCode == 10000:
301
302
303 raise rhnFault(e.faultCode, e.faultString), None, sys.exc_info()[2]
304
305 Traceback("ProxyAuth.login (Fault) - Spacewalk Proxy not "
306 "able to log in.")
307
308
309 raise rhnFault(1000,
310 _("Spacewalk Proxy error (during proxy login). "
311 "Please contact your system administrator.")), None, sys.exc_info()[2]
312 except Exception, e:
313 token = None
314 log_error("Unhandled exception", e)
315 Traceback(mail=0)
316 time.sleep(.25)
317 continue
318 else:
319 break
320
321 if not token:
322 if error:
323 if error[0] in ('xmlrpclib.ProtocolError', 'socket.error', 'socket'):
324 raise rhnFault(1000,
325 _("Spacewalk Proxy error (error: %s). "
326 "Please contact your system administrator.") % error[0])
327 if error[0] in ('rhn.SSL.SSL.Error', 'socket.sslerror'):
328 raise rhnFault(1000,
329 _("Spacewalk Proxy error (SSL issues? Error: %s). "
330 "Please contact your system administrator.") % error[0])
331 else:
332 raise rhnFault(1002, err_text='%s' % e)
333 else:
334 raise rhnFault(1001)
335 if self.hostname:
336 token = token + ':' + self.hostname
337 log_debug(6, "New proxy token: %s" % token)
338 return token
339
340 @staticmethod
346
347 @staticmethod
351
353
354
355
356
357 dumbToken = {}
358 satInfo = None
359 for key in ('X-RHN-Server-Id', 'X-RHN-Auth-User-Id', 'X-RHN-Auth',
360 'X-RHN-Auth-Server-Time', 'X-RHN-Auth-Expire-Offset'):
361 if token.has_key(key):
362 dumbToken[key] = token[key]
363 try:
364 s = self.__getXmlrpcServer()
365 satInfo = s.proxy.checkTokenValidity(
366 dumbToken, self.get_system_id())
367 except Exception:
368 pass
369
370
371
372
373
374
375 if satInfo:
376 clockSkew = time.time() - float(satInfo['X-RHN-Auth-Server-Time'])
377 dumbToken['X-RHN-Auth-Proxy-Clock-Skew'] = clockSkew
378 dumbToken['X-RHN-Auth-Channels'] = satInfo['X-RHN-Auth-Channels']
379
380 self.set_client_token(clientid, dumbToken)
381 return dumbToken
382 return None
383
384
385
386 @staticmethod
421
424
427
435
467
468
469