def _serverCommo(self): """ Handler part 2 Server (or next proxy) communication. """ log_debug(1) # Copy the method from the original request, and use the # handler for this server # We add path_info to the put (GET, CONNECT, HEAD, PUT, POST) request. log_debug(2, self.req.method, self.uri) self.responseContext.getConnection().putrequest( self.req.method, self.uri) # Send the headers, the body and expect a response try: status, headers, bodyFd = self._proxy2server() self.responseContext.setHeaders(headers) self.responseContext.setBodyFd(bodyFd) except IOError: # Raised by HTTP*Connection.getresponse # Server closed connection on us, no need to mail out # XXX: why are we not mailing this out??? Traceback("SharedHandler._serverCommo", self.req, mail=0) raise_with_tb( rhnFault( 1000, _("SUSE Manager Proxy error: connection with the SUSE Manager server failed" )), sys.exc_info()[2]) except socket.error: # maybe self.req.read() failed? Traceback("SharedHandler._serverCommo", self.req) raise_with_tb( rhnFault( 1000, _("SUSE Manager Proxy error: connection with the SUSE Manager server failed" )), sys.exc_info()[2]) log_debug(2, "HTTP status code (200 means all is well): %s" % status) # Now we need to decide how to deal with the server's response. We'll # defer to subclass-specific implementation here. The handler will # return apache.OK if the request was a success. return self._handleServerResponse(status)
def _wrapper(self, req, function_name): #log_debug(1, "_wrapper", req, function_name) if not hasattr(self.server, function_name): log_error("%s doesn't have a %s function" % (self.server, function_name)) return apache.HTTP_NOT_FOUND function = getattr(self.server, function_name) try: log_debug(5, "Calling", function) ret = function(req) except rhnFault: e = sys.exc_info()[1] log_debug(4, "rhnFault caught: %s" % (e, )) error_string = self._exception_to_text(e) error_code = e.code self._error_to_headers(req.err_headers_out, error_code, error_string) ret = rhnFlags.get("apache-return-code") if not ret: ret = apache.HTTP_INTERNAL_SERVER_ERROR req.status = ret log_debug( 4, "_wrapper %s exited with apache code %s" % (function_name, ret)) except rhnSession.ExpiredSessionError: e = sys.exc_info()[1] # if session expires we catch here and return a forbidden # abd make it re-authenticate log_debug(4, "Expire Session Error Caught: %s" % (e, )) return 403 except: Traceback("server.apacheUploadServer._wrapper", req=req) log_error("Unhandled exception") return apache.HTTP_INTERNAL_SERVER_ERROR return ret
def _connectToParent(self): """ Handler part 1 Should not return an error code -- simply connects. """ scheme, host, port, self.uri = self._parse_url(self.rhnParent) self.responseContext.setConnection(self._create_connection()) if not self.uri: self.uri = '/' log_debug(3, 'Scheme:', scheme) log_debug(3, 'Host:', host) log_debug(3, 'Port:', port) log_debug(3, 'URI:', self.uri) log_debug(3, 'HTTP proxy:', self.httpProxy) log_debug(3, 'HTTP proxy username:'******'HTTP proxy password:'******'CA cert:', self.caChain) try: self.responseContext.getConnection().connect() except socket.error, e: log_error("Error opening connection", self.rhnParent, e) Traceback(mail=0) raise rhnFault(1000, _("Spacewalk Proxy could not successfully connect its RHN parent. " "Please contact your system administrator.")), None, sys.exc_info()[2]
def __getV2(self, action, dry_run=0): """ Fetches queued actions for the clients version 2+. """ log_debug(3, self.server_id) # Get the root dir of this install try: method = getMethod.getMethod(action['method'], 'server.action') except getMethod.GetMethodException: Traceback("queue.get V2") raise_with_tb(EmptyAction("Could not get a valid method for %s" % ( action['method'],)), sys.exc_info()[2]) # Call the method result = method(self.server_id, action['id'], dry_run) if result is None: # None are mapped to the empty list result = () elif not isinstance(result, TupleType): # Everything other than a tuple is wrapped in a tuple result = (result, ) xmlblob = xmlrpclib.dumps(result, methodname=action['method']) log_debug(5, "returning xmlblob for action", xmlblob) return { 'id': action['id'], 'action': xmlblob, 'version': action['version'], }
def response(self, response): # Send the xml-rpc response back log_debug(3, type(response)) needs_xmlrpc_encoding = not rhnFlags.test("XMLRPC-Encoded-Response") compress_response = rhnFlags.test("compress_response") # Init an output object; we'll use it for sending data in various # formats if isinstance(response, transports.File): if not hasattr(response.file_obj, 'fileno') and compress_response: # This is a StringIO that has to be compressed, so read it in # memory; mark that we don't have to do any xmlrpc encoding response = response.file_obj.read() needs_xmlrpc_encoding = 0 else: # Just treat is as a file return self.response_file(response) output = transports.Output() # First, use the same encoding/transfer that the client used output.set_transport_flags( transfer=transports.lookupTransfer(self.input.transfer), encoding=transports.lookupEncoding(self.input.encoding)) if isinstance(response, xmlrpclib.Fault): log_debug(4, "Return FAULT", response.faultCode, response.faultString) # No compression for faults because we'd like them to pop # up in clear text on the other side just in case output.set_transport_flags(output.TRANSFER_NONE, output.ENCODE_NONE) elif compress_response: # check if we have to compress this result log_debug(4, "Compression on for client version", self.client) if self.client > 0: output.set_transport_flags(output.TRANSFER_BINARY, output.ENCODE_ZLIB) else: # original clients had the binary transport support broken output.set_transport_flags(output.TRANSFER_BASE64, output.ENCODE_ZLIB) # We simply add the transport options to the output headers output.headers.update(rhnFlags.get('outputTransportOptions').dict()) if needs_xmlrpc_encoding: # Normalize the response response = self.normalize(response) try: response = xmlrpclib.dumps(response, methodresponse=1) except TypeError, e: log_debug( 4, "Error \"%s\" encoding response = %s" % (e, response)) Traceback("apacheHandler.response", self.req, extra="Error \"%s\" encoding response = %s" % (e, response), severity="notification") return apache.HTTP_INTERNAL_SERVER_ERROR except:
def add_hardware(self, hardware): """ add new hardware """ log_debug(4, hardware) if not hardware: return -1 if type(hardware) == type({}): hardware = UserDictCase(hardware) if not isinstance(hardware, UserDictCase): log_error("argument type is not hash: %s" % hardware) raise TypeError, "This function requires a hash as an argument" # validation is important hw_class = hardware.get("class") if hw_class is None: return -1 hw_class = string.lower(hw_class) class_type = None if hw_class in [ "video", "audio", "audio_hd", "usb", "other", "hd", "floppy", "mouse", "modem", "network", "cdrom", "scsi", "unspec", "scanner", "tape", "capture", "raid", "socket", "keyboard", "printer", "firewire", "ide" ]: class_type = HardwareDevice elif hw_class == "cpu": class_type = CPUDevice elif hw_class == "netinfo": class_type = NetworkInformation elif hw_class == "memory": class_type = MemoryInformation elif hw_class == "dmi": class_type = DMIInformation elif hw_class == "installinfo": class_type = InstallInformation elif hw_class == "netinterfaces": class_type = NetIfaceInformation else: log_error("UNKNOWN CLASS TYPE `%s'" % hw_class) # Same trick: try-except and raise the exception so that Traceback # can send the e-mail try: raise KeyError, "Unknwon class type `%s' for hardware '%s'" % ( hw_class, hardware) except: Traceback(mail=1) return # create the new device new_dev = class_type(hardware) if self.__hardware.has_key(class_type): _l = self.__hardware[class_type] else: _l = self.__hardware[class_type] = [] _l.append(new_dev) self.__changed = 1 return 0
def _connectToParent(self): """ Handler part 1 Should not return an error code -- simply connects. """ scheme, host, port, self.uri, query = self._parse_url(self.rhnParent) self.responseContext.setConnection(self._create_connection()) if not self.uri: self.uri = '/' # if this request is for an upstream server, use the original query string. # Otherwise, if it is for the local Squid instance, strip it so that # Squid will not keep multiple cached copies of the same resource if self.httpProxy not in ['127.0.0.1:8080', 'localhost:8080']: if 'X-Suse-Auth-Token' in self.req.headers_in: self.uri += '?%s' % self.req.headers_in['X-Suse-Auth-Token'] elif query: self.uri += '?%s' % query log_debug(3, 'Scheme:', scheme) log_debug(3, 'Host:', host) log_debug(3, 'Port:', port) log_debug(3, 'URI:', self.uri) log_debug(3, 'HTTP proxy:', self.httpProxy) log_debug(3, 'HTTP proxy username:'******'HTTP proxy password:'******'CA cert:', self.caChain) try: self.responseContext.getConnection().connect() except socket.error as e: log_error("Error opening connection", self.rhnParent, e) Traceback(mail=0) raise_with_tb( rhnFault( 1000, _("SUSE Manager Proxy could not successfully connect its SUSE Manager parent. " "Please contact your system administrator.")), sys.exc_info()[2]) # At this point the server should be okay log_debug(3, "Connected to parent: %s " % self.rhnParent) if self.httpProxy: if self.httpProxyUsername: log_debug( 3, "HTTP proxy info: %s %s/<password>" % (self.httpProxy, self.httpProxyUsername)) else: log_debug(3, "HTTP proxy info: %s" % self.httpProxy) else: log_debug(3, "HTTP proxy info: not using an HTTP proxy") peer = self.responseContext.getConnection().sock.getpeername() log_debug( 4, "Other connection info: %s:%s%s" % (peer[0], peer[1], self.uri))
def __init__(self, fields, dict=None, mapping=None): GenericDevice.__init__(self) x = {} for k in fields: x[k] = None self.data = UserDictCase(x) if not dict: return # make sure we get a UserDictCase to work with if type(dict) == type({}): dict = UserDictCase(dict) if mapping is None or type(mapping) == type({}): mapping = UserDictCase(mapping) if not isinstance(dict, UserDictCase) or \ not isinstance(mapping, UserDictCase): log_error("Argument passed is not a dictionary", dict, mapping) raise TypeError("Argument passed is not a dictionary", dict, mapping) # make sure we have a platform for k in list(dict.keys()): if dict[k] == '': dict[k] = None if self.data.has_key(k): self.data[k] = dict[k] continue if mapping.has_key(k): # the mapping dict might tell us to lose some fields if mapping[k] is not None: self.data[mapping[k]] = dict[k] else: log_error("Unknown HW key =`%s'" % k, dict.dict(), mapping.dict()) # The try-except is added just so that we can send e-mails try: raise KeyError("Don't know how to parse key `%s''" % k, dict.dict()) except: Traceback(mail=1) # Ignore this key continue # clean up this data try: for k in list(self.data.keys()): if type(self.data[k]) == type("") and len(self.data[k]): self.data[k] = self.data[k].strip() if not len(self.data[k]): continue if self.data[k][0] == '"' and self.data[k][-1] == '"': self.data[k] = self.data[k][1:-1] except IndexError: raise_with_tb( IndexError("Can not process data = %s, key = %s" % (repr(self.data), k)), sys.exc_info()[2])
def process(self, stream=None): log_debug(6) if stream is not None: self.setStream(stream) try: self.__parser.parse(self.__stream) except (KeyboardInterrupt, SystemExit): raise except Exception: Traceback(ostream=sys.stderr, with_locals=1) if stream is not None: stream.close() sys.exit(1)
def call_function(self, method, params): # short-circuit everything if sending a system-wide message. if CFG.SEND_MESSAGE_TO_ALL: # Make sure the applet doesn't see the message if method == 'applet.poll_status': return self.response({ 'checkin_interval': 3600, 'server_status': 'normal' }) if method == 'applet.poll_packages': return self.response({'use_cached_copy': 1}) # Fetch global message being sent to clients if applicable. msg = open(CFG.MESSAGE_TO_ALL).read() log_debug(3, "Sending message to all clients: %s" % msg) # Send the message as a fault. response = xmlrpclib.Fault( -1, _("IMPORTANT MESSAGE FOLLOWS:\n%s") % msg) # and now send everything back ret = self.response(response) log_debug(4, "Leave with return value", ret) return ret # req: where the response is sent to log_debug(2, method) # Now we have the reference, call away force_rollback = 1 try: rhnSQL.clear_log_id() # now get the function reference and call it func = self.method_ref(method) response = func(*params) except (TypeError, ValueError, KeyError, IndexError, UnknownXML): # report exception back to server fault = 1 if sys.exc_type == UnknownXML: fault = -1 e_type, e_value = sys.exc_info()[:2] response = xmlrpclib.Fault( fault, _("While running '%s': caught\n%s : %s\n") % (method, e_type, e_value)) Traceback(method, self.req, extra="Response sent back to the caller:\n%s\n" % (response.faultString, ), severity="notification") except rhnNotFound, e: return apache.HTTP_NOT_FOUND
def _wrapper(self, req, function): try: ret = function(req) except rhnFault: e = sys.exc_info()[1] return self._send_xmlrpc(req, e) except ClosedConnectionError: # The error code most likely doesn't matter, the client won't see # it anyway return apache.HTTP_NOT_ACCEPTABLE except Exception: # pylint: disable=E0012, W0703 Traceback("satexport._wrapper", req=req) return apache.HTTP_INTERNAL_SERVER_ERROR return ret
class GetHandler(apacheRequest): # we require our own init since we depend on a channel def __init__(self, client_version, req): apacheRequest.__init__(self, client_version, req) self.channel = None def _setup_servers(self): # Nothing to do here pass # get a function reference for the GET request def method_ref(self, method): log_debug(3, self.server, method) # Init the repository server_id = rhnFlags.get("AUTH_SESSION_TOKEN")['X-RHN-Server-Id'] username = rhnFlags.get("AUTH_SESSION_TOKEN")['X-RHN-Auth-User-Id'] repository = rhnRepository.Repository(self.channel, server_id, username) repository.set_qos() f = repository.get_function(method) if f is None: raise UnknownXML("function '%s' invalid; path_info is %s" % (method, self.req.path_info)) return f # handle the GET requests def process(self): log_debug(3) # Query repository; only after a clients signature has been # authenticated. try: method, params = self._get_method_params() except rhnFault, f: log_debug(2, "Fault caught") response = f.getxml() self.response(response) return apache.HTTP_NOT_FOUND except Exception, e: rhnSQL.rollback() # otherwise we do a full stop Traceback(method, self.req, severity="unhandled") return apache.HTTP_INTERNAL_SERVER_ERROR
def _clientCommo(self, status=apache.OK): """ Handler part 3 Forward server's response to the client. """ log_debug(1) try: self._forwardServer2Client() except IOError: # Raised by HTTP*connection.getresponse # Client closed connection on us, no need to mail out a traceback Traceback("SharedHandler._clientCommo", self.req, mail=0) return apache.HTTP_SERVICE_UNAVAILABLE # Close all open response contexts. self.responseContext.clear() return status
def process_extra_data(self, server_id, action_id, data={}, action_type=None): log_debug(4, server_id, action_id, action_type) if not action_type: # Shouldn't happen return try: method = getMethod.getMethod(action_type, 'server.action_extra_data') except getMethod.GetMethodException: Traceback("queue.get V2") raise_with_tb(EmptyAction("Could not get a valid method for %s" % action_type), sys.exc_info()[2]) # Call the method result = method(self.server_id, action_id, data=data) return result
def __request(self, methodname, params): # pylint: disable=R0915 log_debug(6, methodname, params) # Init the socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: sock.connect(self.serverAddr) except socket.error, e: sock.close() methodname = None log_error("Error connecting to the auth cache: %s" % str(e)) Traceback("Shelf.__request", extra=""" Error connecting to the the authentication cache daemon. Make sure it is started on %s""" % str(self.serverAddr)) # FIXME: PROBLEM: this rhnFault will never reach the client raise rhnFault(1000, _("Spacewalk Proxy error (issues connecting to auth cache). " "Please contact your system administrator")), None, sys.exc_info()[2]
def _handler(self, req): log_debug(3, "Method", req.method) # Read all the request data = req.read() log_debug(7, "Received", data) # Decode the data try: params, methodname = xmlrpclib.loads(data) except: raise log_debug(5, params, methodname) try: f = self.get_function(methodname, req) except FunctionRetrievalError, e: Traceback(methodname, req) return self._send_xmlrpc(req, rhnFault(3008, str(e), explain=0))
def set_cached_token(self, token): """ Caches current token in the auth cache. """ log_debug(3) # Try to connect to the token-cache. shelf = get_auth_shelf() # Cache the token. try: shelf[self.__cache_proxy_key()] = token except: text = _("""\ Caching of authentication token for proxy id %s failed! Either the authentication caching daemon is experiencing problems, isn't running, or the token is somehow corrupt. """) % self.__serverid Traceback("ProxyAuth.set_cached_token", extra=text) raise rhnFault(1000, _("Spacewalk Proxy error (auth caching issue). " "Please contact your system administrator.")), None, sys.exc_info()[2] log_debug(4, "successfully returning") return token
def process(self): log_debug(3) # Query repository; only after a clients signature has been # authenticated. try: method, params = self._get_method_params() except rhnFault: f = sys.exc_info()[1] log_debug(2, "Fault caught") response = f.getxml() self.response(response) return apache.HTTP_NOT_FOUND except Exception: e = sys.exc_info()[1] rhnSQL.rollback() # otherwise we do a full stop Traceback(method, self.req, severity="unhandled") return apache.HTTP_INTERNAL_SERVER_ERROR # make the actual function call and return the result return self.call_function(method, params)
def __call__(self, req): # NOTE: all imports done here due to required initialization of # of the configuration module before all others. # Initialization is dependent on RHNComponentType in the # req object. if self.__init: from apacheHandler import getComponentType # We cannot trust the config files to tell us if we are in the # broker or in the redirect because we try to always pass # upstream all requests componentType = getComponentType(req) initCFG(componentType) initLOG(CFG.LOG_FILE, CFG.DEBUG) log_debug(1, 'New request, component %s' % (componentType, )) # Instantiate the handlers if HandlerWrap.svrHandlers is None: HandlerWrap.svrHandlers = self.get_handler_factory(req)() if self.__init: # Set the component type HandlerWrap.svrHandlers.set_component(componentType) try: log_setreq(req) if hasattr(HandlerWrap.svrHandlers, self.__name): f = getattr(HandlerWrap.svrHandlers, self.__name) ret = f(req) else: raise Exception("Class has no attribute %s" % self.__name) # pylint: disable=W0702 except: Traceback(self.__name, req, extra="Unhandled exception type", severity="unhandled") return apache.HTTP_INTERNAL_SERVER_ERROR else: return ret
def _handler(self, req): log_debug(3, "Method", req.method) # Read all the request data = req.read() log_debug(7, "Received", data) # Decode the data try: params, methodname = xmlrpclib.loads(data) except: raise log_debug(5, params, methodname) try: f = self.get_function(methodname, req) except FunctionRetrievalError: e = sys.exc_info()[1] Traceback(methodname, req) return self._send_xmlrpc(req, rhnFault(3008, str(e), explain=0)) if len(params) < 2: params = [] else: params = params[1:] result = f(*params) if result: # Error of some sort return self._send_xmlrpc(req, rhnFault(3009)) # Presumably the function did all the sending log_debug(4, "Exiting OK") return apache.OK
def response(self, req, response): """ send the response (common code) """ # Send the xml-rpc response back log_debug(5, "Response type", type(response)) needs_xmlrpc_encoding = rhnFlags.test("NeedEncoding") compress_response = rhnFlags.test("compress_response") # Init an output object; we'll use it for sending data in various # formats if isinstance(response, rpclib.transports.File): if not hasattr(response.file_obj, 'fileno') and compress_response: # This is a StringIO that has to be compressed, so read it in # memory; mark that we don't have to do any xmlrpc encoding response = response.file_obj.read() needs_xmlrpc_encoding = 0 else: # Just treat is as a file return self.response_file(req, response) is_fault = 0 if isinstance(response, rhnFault): if req.method == 'GET': return self._response_fault_get(req, response.getxml()) # Need to encode the response as xmlrpc response = response.getxml() is_fault = 1 # No compression compress_response = 0 # This is an xmlrpc Fault, so we have to encode it needs_xmlrpc_encoding = 1 output = rpclib.transports.Output() if not is_fault: # First, use the same encoding/transfer that the client used output.set_transport_flags( transfer=rpclib.transports.lookupTransfer(self.input.transfer), encoding=rpclib.transports.lookupEncoding(self.input.encoding)) if compress_response: # check if we have to compress this result log_debug(4, "Compression on for client version", self.clientVersion) if self.clientVersion > 0: output.set_transport_flags(output.TRANSFER_BINARY, output.ENCODE_ZLIB) else: # original clients had the binary transport support broken output.set_transport_flags(output.TRANSFER_BASE64, output.ENCODE_ZLIB) # We simply add the transport options to the output headers output.headers.update(rhnFlags.get('outputTransportOptions').dict()) if needs_xmlrpc_encoding: # Normalize the response response = self.normalize(response) try: response = rpclib.xmlrpclib.dumps(response, methodresponse=1) except TypeError, e: log_debug( -1, "Error \"%s\" encoding response = %s" % (e, response)) Traceback("apacheHandler.response", req, extra="Error \"%s\" encoding response = %s" % (e, response), severity="notification") return apache.HTTP_INTERNAL_SERVER_ERROR except Exception: # pylint: disable=E0012, W0703 # Uncaught exception; signal the error Traceback("apacheHandler.response", req, severity="unhandled") return apache.HTTP_INTERNAL_SERVER_ERROR
class Shelf: """ Client authenication temp. db. Main class that the client side (client to the caching daemon) has to instantiate to expose the proper API. Basically, the API is a dictionary. """ # pylint: disable=R0903 def __init__(self, server_addr): log_debug(6, server_addr) self.serverAddr = server_addr def __request(self, methodname, params): # pylint: disable=R0915 log_debug(6, methodname, params) # Init the socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: sock.connect(self.serverAddr) except socket.error, e: sock.close() methodname = None log_error("Error connecting to the auth cache: %s" % str(e)) Traceback("Shelf.__request", extra=""" Error connecting to the the authentication cache daemon. Make sure it is started on %s""" % str(self.serverAddr)) # FIXME: PROBLEM: this rhnFault will never reach the client raise rhnFault( 1000, _("Spacewalk Proxy error (issues connecting to auth cache). " "Please contact your system administrator") ), None, sys.exc_info()[2] wfile = sock.makefile("w") try: send(wfile, methodname, None, *params) except CommunicationError: wfile.close() sock.close() Traceback("Shelf.__request", extra="Encountered a CommunicationError") raise except socket.error: wfile.close() sock.close() log_error("Error communicating to the auth cache: %s" % str(e)) Traceback("Shelf.__request", extra="""\ Error sending to the authentication cache daemon. Make sure the authentication cache daemon is started""") # FIXME: PROBLEM: this rhnFault will never reach the client raise rhnFault( 1000, _("Spacewalk Proxy error (issues connecting to auth cache). " "Please contact your system administrator") ), None, sys.exc_info()[2] wfile.close() rfile = sock.makefile("r") try: params, methodname = recv(rfile) except CommunicationError, e: log_error(e.faultString) rfile.close() sock.close() log_error("Error communicating to the auth cache: %s" % str(e)) Traceback("Shelf.__request", extra="""\ Error receiving from the authentication cache daemon. Make sure the authentication cache daemon is started""") # FIXME: PROBLEM: this rhnFault will never reach the client raise rhnFault( 1000, _("Spacewalk Proxy error (issues communicating to auth cache). " "Please contact your system administrator") ), None, sys.exc_info()[2]
def __redirectToNextLocationNoRetry(self, loopProtection=False): """ This function will perform a redirection to the next location, as specified in the last response's "Location" header. This function will return an actual HTTP response status code. If successful, it will return apache.HTTP_OK, not apache.OK. If unsuccessful, this function will simply return; no retries will be performed. The following error codes can be returned: HTTP_OK,HTTP_PARTIAL_CONTENT - Redirect successful. HTTP_MOVED_TEMPORARILY - Redirect was redirected again by 3rd party. HTTP_MOVED_PERMANENTLY - Redirect was redirected again by 3rd party. HTTP_INTERNAL_SERVER_ERROR - Error extracting redirect information HTTP_SERVICE_UNAVAILABLE - Could not connect to 3rd party server, connection was reset, or a read error occurred during communication. HTTP_* - Any other HTTP status code may also be returned. Upon successful completion of this function, a new responseContext will be created and pushed onto the stack. """ # Obtain the redirect location first before we replace the current # response context. It's contained in the Location header of the # previous response. redirectLocation = self._get_header(rhnConstants.HEADER_LOCATION) # We are about to redirect to a new location so now we'll push a new # response context before we return any errors. self.responseContext.add() # There should always be a redirect URL passed back to us. If not, # there's an error. if not redirectLocation: log_error(" No redirect location specified!") Traceback(mail=0) return apache.HTTP_INTERNAL_SERVER_ERROR # The _get_header function returns the value as a list. There should # always be exactly one location specified. redirectLocation = redirectLocation[0] log_debug(1, " Redirecting to: ", redirectLocation) # Tear apart the redirect URL. We need the scheme, the host, the # port (if not the default), and the URI. _scheme, host, port, uri, query = self._parse_url(redirectLocation) # Add back the query string if query: uri += '?' + query # Now create a new connection. We'll use SSL if configured to do # so. params = { 'host': host, 'port': port, } if CFG.has_key('timeout'): params['timeout'] = CFG.TIMEOUT if CFG.USE_SSL: log_debug(1, " Redirecting with SSL. Cert= ", self.caChain) params['trusted_certs'] = [self.caChain] connection = connections.HTTPSConnection(**params) else: log_debug(1, " Redirecting withOUT SSL.") connection = connections.HTTPConnection(**params) # Put the connection into the current response context. self.responseContext.setConnection(connection) # Now open the connection to the 3rd party server. log_debug(4, "Attempting to connect to 3rd party server...") try: connection.connect() except socket.error as e: log_error("Error opening redirect connection", redirectLocation, e) Traceback(mail=0) return apache.HTTP_SERVICE_UNAVAILABLE log_debug(4, "Connected to 3rd party server:", connection.sock.getpeername()) # Put the request out on the wire. response = None try: # We'll redirect to the URI made in the original request, but with # the new server instead. log_debug(4, "Making request: ", self.req.method, uri) connection.putrequest(self.req.method, uri) # Add some custom headers. if loopProtection: connection.putheader(rhnConstants.HEADER_RHN_REDIRECT, '0') log_debug(4, " Adding original URL header: ", self.rhnParent) connection.putheader(rhnConstants.HEADER_RHN_ORIG_LOC, self.rhnParent) # Add all the other headers in the original request in case we # need to re-authenticate with Hosted. for hdr in list(self.req.headers_in.keys()): if hdr.lower().startswith("x-rhn"): connection.putheader(hdr, self.req.headers_in[hdr]) log_debug(4, "Passing request header: ", hdr, self.req.headers_in[hdr]) connection.endheaders() response = connection.getresponse() except IOError as ioe: # Raised by getresponse() if server closes connection on us. log_error("Redirect connection reset by peer.", redirectLocation, ioe) Traceback(mail=0) # The connection is saved in the current response context, and # will be closed when the caller pops the context. return apache.HTTP_SERVICE_UNAVAILABLE except socket.error as se: # Some socket error occurred. Possibly a read error. log_error("Redirect request failed.", redirectLocation, se) Traceback(mail=0) # The connection is saved in the current response context, and # will be closed when the caller pops the context. return apache.HTTP_SERVICE_UNAVAILABLE # Save the response headers and body FD in the current communication # context. self.responseContext.setBodyFd(response) self.responseContext.setHeaders(response.msg) log_debug(4, "Response headers: ", list(self.responseContext.getHeaders().items())) log_debug(4, "Got redirect response. Status=", response.status) # Return the HTTP status to the caller. return response.status
def response(self, response): # Send the xml-rpc response back log_debug(3, type(response)) needs_xmlrpc_encoding = not rhnFlags.test("XMLRPC-Encoded-Response") compress_response = rhnFlags.test("compress_response") # Init an output object; we'll use it for sending data in various # formats if isinstance(response, transports.File): if not hasattr(response.file_obj, 'fileno') and compress_response: # This is a StringIO that has to be compressed, so read it in # memory; mark that we don't have to do any xmlrpc encoding response = response.file_obj.read() needs_xmlrpc_encoding = 0 else: # Just treat is as a file return self.response_file(response) output = transports.Output() # First, use the same encoding/transfer that the client used output.set_transport_flags( transfer=transports.lookupTransfer(self.input.transfer), encoding=transports.lookupEncoding(self.input.encoding)) if isinstance(response, xmlrpclib.Fault): log_debug(4, "Return FAULT", response.faultCode, response.faultString) # No compression for faults because we'd like them to pop # up in clear text on the other side just in case output.set_transport_flags(output.TRANSFER_NONE, output.ENCODE_NONE) elif compress_response: # check if we have to compress this result log_debug(4, "Compression on for client version", self.client) if self.client > 0: output.set_transport_flags(output.TRANSFER_BINARY, output.ENCODE_ZLIB) else: # original clients had the binary transport support broken output.set_transport_flags(output.TRANSFER_BASE64, output.ENCODE_ZLIB) # We simply add the transport options to the output headers output.headers.update(rhnFlags.get('outputTransportOptions').dict()) if needs_xmlrpc_encoding: # Normalize the response response = self.normalize(response) try: response = xmlrpclib.dumps(response, methodresponse=1) except TypeError: e = sys.exc_info()[1] log_debug(4, "Error \"%s\" encoding response = %s" % (e, response)) Traceback("apacheHandler.response", self.req, extra="Error \"%s\" encoding response = %s" % (e, response), severity="notification") return apache.HTTP_INTERNAL_SERVER_ERROR except: # Uncaught exception; signal the error Traceback("apacheHandler.response", self.req, severity="unhandled") return apache.HTTP_INTERNAL_SERVER_ERROR # we're about done here, patch up the headers output.process(response) # Copy the rest of the fields for k, v in output.headers.items(): if string.lower(k) == 'content-type': # Content-type self.req.content_type = v else: setHeaderValue(self.req.headers_out, k, v) if 5 <= CFG.DEBUG < 10: log_debug(5, "The response: %s[...SNIP (for sanity) SNIP...]%s" % (response[:100], response[-100:])) elif CFG.DEBUG >= 10: # if you absolutely must have that whole response in the log file log_debug(10, "The response: %s" % response) # send the headers self.req.send_http_header() try: # XXX: in case data is really large maybe we should split # it in smaller chunks instead of blasting everything at # once. Not yet a problem... self.req.write(output.data) except IOError: # send_http_header is already sent, so it doesn't make a lot of # sense to return a non-200 error; but there is no better solution return apache.HTTP_BAD_REQUEST del output return apache.OK
def call_function(self, method, params): # short-circuit everything if sending a system-wide message. if CFG.SEND_MESSAGE_TO_ALL: # Make sure the applet doesn't see the message if method == 'applet.poll_status': return self.response({ 'checkin_interval': 3600, 'server_status': 'normal' }) if method == 'applet.poll_packages': return self.response({'use_cached_copy': 1}) # Fetch global message being sent to clients if applicable. msg = open(CFG.MESSAGE_TO_ALL).read() log_debug(3, "Sending message to all clients: %s" % msg) # Send the message as a fault. response = xmlrpclib.Fault( -1, _("IMPORTANT MESSAGE FOLLOWS:\n%s") % msg) # and now send everything back ret = self.response(response) log_debug(4, "Leave with return value", ret) return ret # req: where the response is sent to log_debug(2, method) # Now we have the reference, call away force_rollback = 1 try: rhnSQL.clear_log_id() # now get the function reference and call it func = self.method_ref(method) response = func(*params) except (TypeError, ValueError, KeyError, IndexError, UnknownXML): # report exception back to server fault = 1 if sys.version_info[0] == 3: exctype = sys.exc_info()[0] else: exctype = sys.exc_type if exctype == UnknownXML: fault = -1 e_type, e_value = sys.exc_info()[:2] response = xmlrpclib.Fault(fault, _( "While running '%s': caught\n%s : %s\n") % ( method, e_type, e_value)) Traceback(method, self.req, extra="Response sent back to the caller:\n%s\n" % ( response.faultString,), severity="notification") except rhnNotFound: e = sys.exc_info()[1] return apache.HTTP_NOT_FOUND # pkilambi:catch exception if redirect except redirectException: re = sys.exc_info()[1] log_debug(3, "redirect exception caught", re.path) response = re.path except rhnFault: f = sys.exc_info()[1] response = f.getxml() except rhnSQL.SQLSchemaError: e = sys.exc_info()[1] f = None if e.errno == 20200: log_debug(2, "User Group Membership EXCEEDED") f = rhnFault(43, e.errmsg) if not f: log_error("rhnSQL.SQLSchemaError caught", e) rhnSQL.rollback() # generate the traceback report Traceback(method, self.req, extra="SQL Error generated: %s" % e, severity="schema") return apache.HTTP_INTERNAL_SERVER_ERROR response = f.getxml() except rhnSQL.SQLError: e = sys.exc_info()[1] log_error("rhnSQL.SQLError caught", e) rhnSQL.rollback() Traceback(method, self.req, extra="SQL Error generated: %s" % e, severity="schema") return apache.HTTP_INTERNAL_SERVER_ERROR except Exception: e = sys.exc_info()[1] log_error("Unhandled exception", e) rhnSQL.rollback() # otherwise we do a full stop Traceback(method, self.req, severity="unhandled") return apache.HTTP_INTERNAL_SERVER_ERROR else: # if no exception, we don't need to rollback force_rollback = 0 if force_rollback: rhnSQL.rollback() rhnSQL.clear_log_id() # and now send everything back ret = self.response(response) log_debug(4, "Leave with return value", ret) return ret
response = connection.getresponse() except IOError, ioe: # Raised by getresponse() if server closes connection on us. log_error("Redirect connection reset by peer.", redirectLocation, ioe) Traceback(mail=0) # The connection is saved in the current response context, and # will be closed when the caller pops the context. return apache.HTTP_SERVICE_UNAVAILABLE except socket.error, se: # Some socket error occurred. Possibly a read error. log_error("Redirect request failed.", redirectLocation, se) Traceback(mail=0) # The connection is saved in the current response context, and # will be closed when the caller pops the context. return apache.HTTP_SERVICE_UNAVAILABLE # Save the response headers and body FD in the current communication # context. self.responseContext.setBodyFd(response) self.responseContext.setHeaders(response.msg) log_debug(4, "Response headers: ", self.responseContext.getHeaders().items()) log_debug(4, "Got redirect response. Status=", response.status)
def __redirectToNextLocationNoRetry(self, loopProtection=False): """ This function will perform a redirection to the next location, as specified in the last response's "Location" header. This function will return an actual HTTP response status code. If successful, it will return apache.HTTP_OK, not apache.OK. If unsuccessful, this function will simply return; no retries will be performed. The following error codes can be returned: HTTP_OK,HTTP_PARTIAL_CONTENT - Redirect successful. HTTP_MOVED_TEMPORARILY - Redirect was redirected again by 3rd party. HTTP_MOVED_PERMANENTLY - Redirect was redirected again by 3rd party. HTTP_INTERNAL_SERVER_ERROR - Error extracting redirect information HTTP_SERVICE_UNAVAILABLE - Could not connect to 3rd party server, connection was reset, or a read error occurred during communication. HTTP_* - Any other HTTP status code may also be returned. Upon successful completion of this function, a new responseContext will be created and pushed onto the stack. """ # Obtain the redirect location first before we replace the current # response context. It's contained in the Location header of the # previous response. redirectLocation = self._get_header(rhnConstants.HEADER_LOCATION) # We are about to redirect to a new location so now we'll push a new # response context before we return any errors. self.responseContext.add() # There should always be a redirect URL passed back to us. If not, # there's an error. if not redirectLocation or len(redirectLocation) == 0: log_error(" No redirect location specified!") Traceback(mail=0) return apache.HTTP_INTERNAL_SERVER_ERROR # The _get_header function returns the value as a list. There should # always be exactly one location specified. redirectLocation = redirectLocation[0] log_debug(1, " Redirecting to: ", redirectLocation) # Tear apart the redirect URL. We need the scheme, the host, the # port (if not the default), and the URI. _scheme, host, port, uri = self._parse_url(redirectLocation) # Add any params onto the URI since _parse_url doesn't include them. if redirectLocation.find('?') > -1: uri += redirectLocation[redirectLocation.index('?'):] # Now create a new connection. We'll use SSL if configured to do # so. params = { 'host': host, 'port': port, } if CFG.has_key('timeout'): params['timeout'] = CFG.TIMEOUT if CFG.USE_SSL: log_debug(1, " Redirecting with SSL. Cert= ", self.caChain) params['trusted_certs'] = [self.caChain] connection = connections.HTTPSConnection(**params) else: log_debug(1, " Redirecting withOUT SSL.") connection = connections.HTTPConnection(**params) # Put the connection into the current response context. self.responseContext.setConnection(connection) # Now open the connection to the 3rd party server. log_debug(4, "Attempting to connect to 3rd party server...") try: connection.connect() except socket.error, e: log_error("Error opening redirect connection", redirectLocation, e) Traceback(mail=0) return apache.HTTP_SERVICE_UNAVAILABLE
# rather big problem: http proxy not running. log_error("*** ERROR ***: %s" % error[1]) Traceback(mail=0) except socket.sslerror, e: error = ['socket.sslerror', '(%s) %s' % (CFG.HTTP_PROXY, e)] # rather big problem: http proxy not running. log_error("*** ERROR ***: %s" % error[1]) Traceback(mail=0) else: error = ['socket', str(e)] log_error(error) Traceback(mail=0) else: log_error("Socket error", e) Traceback(mail=0) Traceback(mail=1) token = None time.sleep(.25) continue except SSL.SSL.Error, e: token = None error = ['rhn.SSL.SSL.Error', repr(e), str(e)] log_error(error) Traceback(mail=0) time.sleep(.25) continue except xmlrpclib.ProtocolError, e: token = None log_error('xmlrpclib.ProtocolError', e) time.sleep(.25)
class RedirectHandler(SharedHandler): """ Spacewalk Proxy SSL Redirect specific handler code called by rhnApache. Workflow is: Client -> Apache:Broker -> Squid -> Apache:Redirect -> Satellite Redirect handler get all request for localhost:80 and they come from Broker handler through Squid, which hadle caching. Redirect module transform destination url to parent or http proxy. Depend on what we have in CFG. """ def __init__(self, req): SharedHandler.__init__(self, req) self.componentType = 'proxy.redirect' self._initConnectionVariables(req) self.rhnParentXMLRPC = None def _initConnectionVariables(self, _req): """ set connection variables NOTE: self.{caChain,rhnParent,httpProxy*} are initialized in SharedHandler """ effectiveURI = self._getEffectiveURI() effectiveURI_parts = urlparse(effectiveURI) scheme = 'http' if CFG.USE_SSL: scheme = 'https' else: self.caChain = '' self.rhnParentXMLRPC = urlunparse( (scheme, self.rhnParent, '/XMLRPC', '', '', '')) self.rhnParent = urlunparse((scheme, self.rhnParent) + effectiveURI_parts[2:]) log_debug(3, 'remapped self.rhnParent: %s' % self.rhnParent) log_debug(3, 'remapped self.rhnParentXMLRPC: %s' % self.rhnParentXMLRPC) def handler(self): """ Main handler for all requests pumped through this server. """ log_debug(4, 'In redirect handler') self._prepHandler() # Rebuild the X-Forwarded-For header so that it reflects the actual # path of the request. We must do this because squid is unable to # determine the "real" client, and will make each entry in the chain # 127.0.0.1. _oto = rhnFlags.get('outputTransportOptions') _oto['X-Forwarded-For'] = _oto['X-RHN-IP-Path'] self.rhnParent = self.rhnParent or '' # paranoid log_debug(4, 'Connecting to parent...') self._connectToParent() # part 1 log_debug(4, 'Initiating communication with server...') status = self._serverCommo() # part 2 if (status != apache.OK) and (status != apache.HTTP_PARTIAL_CONTENT): log_debug(3, "Leaving handler with status code %s" % status) return status log_debug(4, 'Initiating communication with client...') # If we got this far, it has to be a good response return self._clientCommo(status) def _handleServerResponse(self, status): """ Here, we'll override the default behavior for handling server responses so that we can adequately handle 302's. We will follow redirects unless it is redirect to (re)login page. In which case we change protocol to https and return redirect to user. """ # In case of a 302, redirect the original request to the location # specified in the response. if status == apache.HTTP_MOVED_TEMPORARILY or \ status == apache.HTTP_MOVED_PERMANENTLY: log_debug(1, "Received redirect response: ", status) # if we redirected to ssl version of login page, send redirect directly to user headers = self.responseContext.getHeaders() if headers is not None: for headerKey in headers.keys(): if headerKey == 'location': location = self._get_header(headerKey) relogin = re.compile( r'https?://.*(/rhn/(Re)?Login.do\?.*)') m = relogin.match(location[0]) if m: # pull server name out of "t:o:k:e:n:hostname1,t:o:k:e:n:hostname2,..." proxy_auth = self.req.headers_in[ 'X-RHN-Proxy-Auth'] last_auth = proxy_auth.split(',')[-1] server_name = last_auth.split(':')[-1] log_debug( 1, "Redirecting to SSL version of login page") rhnLib.setHeaderValue( self.req.headers_out, 'Location', "https://%s%s" % (server_name, m.group(1))) return apache.HTTP_MOVED_PERMANENTLY redirectStatus = self.__redirectToNextLocation() # At this point, we've either: # # (a) successfully redirected to the 3rd party # (b) been told to redirect somewhere else from the 3rd party # (c) run out of retry attempts # # We'll keep redirecting until we've received HTTP_OK or an error. while redirectStatus == apache.HTTP_MOVED_PERMANENTLY or \ redirectStatus == apache.HTTP_MOVED_TEMPORARILY: # We've been told to redirect again. We'll pass a special # argument to ensure that if we end up back at the server, we # won't be redirected again. log_debug(1, "Redirected again! Code=", redirectStatus) redirectStatus = self.__redirectToNextLocation(True) if (redirectStatus != apache.HTTP_OK) and ( redirectStatus != apache.HTTP_PARTIAL_CONTENT): # We must have run out of retry attempts. Fail over to Hosted # to perform the request. log_debug(1, "Redirection failed; retries exhausted. " \ "Failing over. Code=", \ redirectStatus) redirectStatus = self.__redirectFailover() return SharedHandler._handleServerResponse(self, redirectStatus) else: # Otherwise, revert to default behavior. return SharedHandler._handleServerResponse(self, status) def __redirectToNextLocation(self, loopProtection=False): """ This function will perform a redirection to the next location, as specified in the last response's "Location" header. This function will return an actual HTTP response status code. If successful, it will return apache.HTTP_OK, not apache.OK. If unsuccessful, this function will retry a configurable number of times, as defined in CFG.NETWORK_RETRIES. The following codes define "success". HTTP_OK HTTP_PARTIAL_CONTENT HTTP_MOVED_TEMPORARILY HTTP_MOVED_PERMANENTLY Upon successful completion of this function, the responseContext should be populated with the response. Arguments: loopProtection - If True, this function will insert a special header into the new request that tells the RHN server not to issue another redirect to us, in case that's where we end up being redirected. Return: This function may return any valid HTTP_* response code. See __redirectToNextLocationNoRetry for more info. """ retriesLeft = CFG.NETWORK_RETRIES # We'll now try to redirect to the 3rd party. We will keep # retrying until we exhaust the number of allowed attempts. # Valid response codes are: # HTTP_OK # HTTP_PARTIAL_CONTENT # HTTP_MOVED_PERMANENTLY # HTTP_MOVED_TEMPORARILY redirectStatus = self.__redirectToNextLocationNoRetry(loopProtection) while redirectStatus != apache.HTTP_OK and \ redirectStatus != apache.HTTP_PARTIAL_CONTENT and \ redirectStatus != apache.HTTP_MOVED_PERMANENTLY and \ redirectStatus != apache.HTTP_MOVED_TEMPORARILY and \ retriesLeft > 0: retriesLeft = retriesLeft - 1 log_debug(1, "Redirection failed; trying again. " \ "Retries left=", \ retriesLeft, \ "Code=", \ redirectStatus) # Pop the current response context and restore the state to # the last successful response. The acts of remove the current # context will cause all of its open connections to be closed. self.responseContext.remove() # XXX: Possibly sleep here for a second? redirectStatus = \ self.__redirectToNextLocationNoRetry(loopProtection) return redirectStatus def __redirectToNextLocationNoRetry(self, loopProtection=False): """ This function will perform a redirection to the next location, as specified in the last response's "Location" header. This function will return an actual HTTP response status code. If successful, it will return apache.HTTP_OK, not apache.OK. If unsuccessful, this function will simply return; no retries will be performed. The following error codes can be returned: HTTP_OK,HTTP_PARTIAL_CONTENT - Redirect successful. HTTP_MOVED_TEMPORARILY - Redirect was redirected again by 3rd party. HTTP_MOVED_PERMANENTLY - Redirect was redirected again by 3rd party. HTTP_INTERNAL_SERVER_ERROR - Error extracting redirect information HTTP_SERVICE_UNAVAILABLE - Could not connect to 3rd party server, connection was reset, or a read error occurred during communication. HTTP_* - Any other HTTP status code may also be returned. Upon successful completion of this function, a new responseContext will be created and pushed onto the stack. """ # Obtain the redirect location first before we replace the current # response context. It's contained in the Location header of the # previous response. redirectLocation = self._get_header(rhnConstants.HEADER_LOCATION) # We are about to redirect to a new location so now we'll push a new # response context before we return any errors. self.responseContext.add() # There should always be a redirect URL passed back to us. If not, # there's an error. if not redirectLocation or len(redirectLocation) == 0: log_error(" No redirect location specified!") Traceback(mail=0) return apache.HTTP_INTERNAL_SERVER_ERROR # The _get_header function returns the value as a list. There should # always be exactly one location specified. redirectLocation = redirectLocation[0] log_debug(1, " Redirecting to: ", redirectLocation) # Tear apart the redirect URL. We need the scheme, the host, the # port (if not the default), and the URI. _scheme, host, port, uri = self._parse_url(redirectLocation) # Add any params onto the URI since _parse_url doesn't include them. if redirectLocation.find('?') > -1: uri += redirectLocation[redirectLocation.index('?'):] # Now create a new connection. We'll use SSL if configured to do # so. params = { 'host': host, 'port': port, } if CFG.has_key('timeout'): params['timeout'] = CFG.TIMEOUT if CFG.USE_SSL: log_debug(1, " Redirecting with SSL. Cert= ", self.caChain) params['trusted_certs'] = [self.caChain] connection = connections.HTTPSConnection(**params) else: log_debug(1, " Redirecting withOUT SSL.") connection = connections.HTTPConnection(**params) # Put the connection into the current response context. self.responseContext.setConnection(connection) # Now open the connection to the 3rd party server. log_debug(4, "Attempting to connect to 3rd party server...") try: connection.connect() except socket.error, e: log_error("Error opening redirect connection", redirectLocation, e) Traceback(mail=0) return apache.HTTP_SERVICE_UNAVAILABLE log_debug(4, "Connected to 3rd party server:", connection.sock.getpeername()) # Put the request out on the wire. response = None try: # We'll redirect to the URI made in the original request, but with # the new server instead. log_debug(4, "Making request: ", self.req.method, uri) connection.putrequest(self.req.method, uri) # Add some custom headers. if loopProtection: connection.putheader(rhnConstants.HEADER_RHN_REDIRECT, '0') log_debug(4, " Adding original URL header: ", self.rhnParent) connection.putheader(rhnConstants.HEADER_RHN_ORIG_LOC, self.rhnParent) # Add all the other headers in the original request in case we # need to re-authenticate with Hosted. for hdr in self.req.headers_in.keys(): if hdr.lower().startswith("x-rhn"): connection.putheader(hdr, self.req.headers_in[hdr]) log_debug(4, "Passing request header: ", hdr, self.req.headers_in[hdr]) connection.endheaders() response = connection.getresponse() except IOError, ioe: # Raised by getresponse() if server closes connection on us. log_error("Redirect connection reset by peer.", redirectLocation, ioe) Traceback(mail=0) # The connection is saved in the current response context, and # will be closed when the caller pops the context. return apache.HTTP_SERVICE_UNAVAILABLE
def login(self): """ Login and fetch new token (proxy token). How it works in a nutshell. Only the broker component uses this. We perform a xmlrpc request to rhn_parent. This occurs outside of the http process we are currently working on. So, we do this all on our own; do all of our own SSL decisionmaking etc. We use CFG.RHN_PARENT as we always bypass the SSL redirect. DESIGN NOTES: what is the proxy auth token? ------------------------------------------- An Spacewalk Proxy auth token is a token fetched upon login from Red Hat Satellite or hosted. It has this format: 'S:U:ST:EO:SIG' Where: S = server ID U = username ST = server time EO = expiration offset SIG = signature H = hostname (important later) Within this function within the Spacewalk Proxy Broker we also tag on the hostname to the end of the token. The token as described above is enough for authentication purposes, but we need a to identify the exact hostname (as the Spacewalk Proxy sees it). So now the token becomes (token:hostname): 'S:U:ST:EO:SIG:H' DESIGN NOTES: what is X-RHN-Proxy-Auth? ------------------------------------------- This is where we use the auth token beyond Spacewalk Proxy login purposes. This a header used to track request routes through a hierarchy of RHN Proxies. X-RHN-Proxy-Auth is a header that passes proxy authentication information around in the form of an ordered list of tokens. This list is used to gain information as to how a client request is routed throughout an RHN topology. Format: 'S1:U1:ST1:EO1:SIG1:H1,S2:U2:ST2:EO2:SIG2:H2,...' |_________1_________| |_________2_________| |__... token token where token is really: token:hostname leftmost token was the first token hit by a client request. rightmost token was the last token hit by a client request. """ # pylint: disable=R0915 log_debug(3) server = self.__getXmlrpcServer() error = None token = None # update the systemid/serverid if need be. self.__processSystemid() # Makes three attempts to login for _i in range(self.__nRetries): try: token = server.proxy.login(self.__systemid) except (socket.error, socket.sslerror), e: if CFG.HTTP_PROXY: # socket error, check to see if your HTTP proxy is running... s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) httpProxy, httpProxyPort = CFG.HTTP_PROXY.split(':') try: s.connect((httpProxy, int(httpProxyPort))) except socket.error, e: error = ['socket.error', 'HTTP Proxy not running? ' '(%s) %s' % (CFG.HTTP_PROXY, e)] # rather big problem: http proxy not running. log_error("*** ERROR ***: %s" % error[1]) Traceback(mail=0) except socket.sslerror, e: error = ['socket.sslerror', '(%s) %s' % (CFG.HTTP_PROXY, e)] # rather big problem: http proxy not running. log_error("*** ERROR ***: %s" % error[1]) Traceback(mail=0) else: error = ['socket', str(e)] log_error(error) Traceback(mail=0)