Пример #1
0
    def getPackage(self, pkgFilename, *args):
        """ Get rpm package. """
        log_debug(3, pkgFilename)
        if args:
            pkg_spec = [pkgFilename] + list(args)
        else:
            pkg_spec = pkgFilename

        redirectsSupported = 0

        # If we are talking to a proxy, determine whether it's a version that
        # supports redirects.
        proxyVersionString = rhnFlags.get('x-rhn-proxy-version')
        if proxyVersionString:
            redirectsSupported = 1
        else:
            # Must be a client.  We'll determine the redirect capability via
            # the x-rhn-transport-capability header instead.
            transport_cap = rhnFlags.get('x-rhn-transport-capability')
            if transport_cap:
                transport_cap_list = transport_cap.split('=')
                redirectsSupported = transport_cap_list[0] == 'follow-redirects' and transport_cap_list[1] >= 2

        if redirectsSupported:
            log_debug(3, "Client supports redirects.")
            filePath = self.getPackagePath(pkg_spec, 1)
        else:
            # older clients just return the hosted url and download the package
            filePath = self.getPackagePath(pkg_spec)

        return self._getFile(filePath)
Пример #2
0
def auth_proxy():
    """ Authenticates a proxy carrying a clients request. For a valid or
        unsigned request, this function returns 1 (OK), otherwise it raises
        rhnFault

        NOTE: X-RHN-Proxy-Auth described in proxy/broker/rhnProxyAuth.py
    """

    log_debug(3)
    headers = rhnFlags.get('outputTransportOptions')
    if not rhnFlags.test('X-RHN-Proxy-Auth'):
        # No auth information; decline any action
        log_debug(4, "declined proxy authentication")
        headers['X-RHN-Proxy-Auth-Error'] = '%s:%s' % (
            1003, _("declined proxy authentication"))
        raise rhnFault(1003)  # Invalid session key

    # NOTE:
    #   - < v3.1 RHN proxies send only 1 token in this header
    #   - > v3.1: we send the route of the requests via multiple tokens
    #     "token1:hostname1,token2:hostname2" the first tuple is the first
    #     proxy hit.

    tokens = string.split(rhnFlags.get('X-RHN-Proxy-Auth'), ',')
    tokens = filter(lambda token: token, tokens)

    for auth_token in tokens:
        _verifyProxyAuthToken(auth_token)

    # if no rhnFault was raised then the tokens all passed
    return 1
Пример #3
0
def auth_proxy():
    """ Authenticates a proxy carrying a clients request. For a valid or
        unsigned request, this function returns 1 (OK), otherwise it raises
        rhnFault

        NOTE: X-RHN-Proxy-Auth described in proxy/broker/rhnProxyAuth.py
    """

    log_debug(3)
    headers = rhnFlags.get('outputTransportOptions')
    if not rhnFlags.test('X-RHN-Proxy-Auth'):
        # No auth information; decline any action
        log_debug(4, "declined proxy authentication")
        headers['X-RHN-Proxy-Auth-Error'] = '%s:%s' % (
            1003, _("declined proxy authentication"))
        raise rhnFault(1003)  # Invalid session key

    # NOTE:
    #   - < v3.1 RHN proxies send only 1 token in this header
    #   - > v3.1: we send the route of the requests via multiple tokens
    #     "token1:hostname1,token2:hostname2" the first tuple is the first
    #     proxy hit.

    tokens = string.split(rhnFlags.get('X-RHN-Proxy-Auth'), ',')
    tokens = [token for token in tokens if token]

    for auth_token in tokens:
        _verifyProxyAuthToken(auth_token)

    # if no rhnFault was raised then the tokens all passed
    return 1
Пример #4
0
    def getPackage(self, pkgFilename, *args):
        """ Get rpm package. """
        log_debug(3, pkgFilename)
        if args:
            pkg_spec = [pkgFilename] + list(args)
        else:
            pkg_spec = pkgFilename

        redirectsSupported = 0

        # If we are talking to a proxy, determine whether it's a version that
        # supports redirects.
        proxyVersionString = rhnFlags.get('x-rhn-proxy-version')
        if proxyVersionString:
            redirectsSupported = 1
        else:
            # Must be a client.  We'll determine the redirect capability via
            # the x-rhn-transport-capability header instead.
            transport_cap = rhnFlags.get('x-rhn-transport-capability')
            if transport_cap:
                transport_cap_list = transport_cap.split('=')
                redirectsSupported = transport_cap_list[
                    0] == 'follow-redirects' and transport_cap_list[1] >= 2

        if redirectsSupported:
            log_debug(3, "Client supports redirects.")
            filePath = self.getPackagePath(pkg_spec, 1)
        else:
            # older clients just return the hosted url and download the package
            filePath = self.getPackagePath(pkg_spec)

        return self._getFile(filePath)
Пример #5
0
    def response(self, response):
        log_debug(3)
        # pkilambi:if redirectException caught returns path(<str>)
        if isinstance(response, str):
            method, params = self._get_method_params()
            if method == "getPackage":
                return self.redirect(self.req, response)

        # GET requests resulting in a Fault receive special treatment
        # since we have to stick the error message in the HTTP header,
        # and to return an Apache error code

        if isinstance(response, xmlrpclib.Fault):
            log_debug(4, "Return FAULT", response.faultCode, response.faultString)
            retcode = apache.HTTP_NOT_FOUND
            if abs(response.faultCode) in (33, 34, 35, 37, 39, 41):
                retcode = apache.HTTP_UNAUTHORIZED

            self.req.headers_out["X-RHN-Fault-Code"] = str(response.faultCode)
            faultString = string.strip(base64.encodestring(response.faultString))
            # Split the faultString into multiple lines
            for line in string.split(faultString, "\n"):
                self.req.headers_out.add("X-RHN-Fault-String", string.strip(line))
            # And then send all the other things
            for k, v in rhnFlags.get("outputTransportOptions").items():
                setHeaderValue(self.req.headers_out, k, v)
            return retcode
        # Otherwise we're pretty much fine with the standard response
        # handler

        # Copy the fields from the transport options, if necessary
        for k, v in rhnFlags.get("outputTransportOptions").items():
            setHeaderValue(self.req.headers_out, k, v)
        # and jump into the base handler
        return apacheRequest.response(self, response)
Пример #6
0
    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
Пример #7
0
    def __callLocalRepository(self, channelName, funct, params):
        """ Contacts the local repository and retrieves files
        
            URI looks like:
              /$RHN/<channel>/<function>/<params>
        """

        log_debug(2, channelName, funct, params)

        # Find the channel version
        version = None
        for c in self.authChannels:
            ch, ver = c[:2]
            if ch == channelName:
                version = ver
                break

        # NOTE: X-RHN-Proxy-Auth described in broker/rhnProxyAuth.py
        if rhnFlags.get('outputTransportOptions').has_key('X-RHN-Proxy-Auth'):
            self.cachedClientInfo['X-RHN-Proxy-Auth'] = rhnFlags.get('outputTransportOptions')['X-RHN-Proxy-Auth']
        if rhnFlags.get('outputTransportOptions').has_key('Host'):
            self.cachedClientInfo['Host'] = rhnFlags.get('outputTransportOptions')['Host']

        # We already know he's subscribed to this channel
        # channel, so the version is non-null
        rep = rhnRepository.Repository(channelName, version,
                                       self.cachedClientInfo,
                                       rhnParent=self.rhnParent,
                                       rhnParentXMLRPC=self.rhnParentXMLRPC,
                                       httpProxy=self.httpProxy,
                                       httpProxyUsername=self.httpProxyUsername,
                                       httpProxyPassword=self.httpProxyPassword,
                                       caChain=self.caChain)

        f = rep.get_function(funct)
        if not f:
            raise rhnFault(1000,
                _("RHN Proxy configuration error: invalid function %s") % funct)

        log_debug(3, "Calling %s(%s)" % (funct, params))
        try:
            if params:
                ret = apply(f, params)
            else:
                ret = f()
        except rhnRepository.NotLocalError:
            # The package is not local
            return None
        return ret
Пример #8
0
    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
Пример #9
0
    def __callLocalRepository(self, channelName, funct, params):
        """ Contacts the local repository and retrieves files

            URI looks like:
              /$RHN/<channel>/<function>/<params>
        """

        log_debug(2, channelName, funct, params)

        # Find the channel version
        version = None
        for c in self.authChannels:
            ch, ver = c[:2]
            if ch == channelName:
                version = ver
                break

        # NOTE: X-RHN-Proxy-Auth described in broker/rhnProxyAuth.py
        if rhnFlags.get('outputTransportOptions').has_key('X-RHN-Proxy-Auth'):
            self.cachedClientInfo['X-RHN-Proxy-Auth'] = rhnFlags.get('outputTransportOptions')['X-RHN-Proxy-Auth']
        if rhnFlags.get('outputTransportOptions').has_key('Host'):
            self.cachedClientInfo['Host'] = rhnFlags.get('outputTransportOptions')['Host']

        # We already know he's subscribed to this channel
        # channel, so the version is non-null
        rep = rhnRepository.Repository(channelName, version,
                                       self.cachedClientInfo,
                                       rhnParent=self.rhnParent,
                                       rhnParentXMLRPC=self.rhnParentXMLRPC,
                                       httpProxy=self.httpProxy,
                                       httpProxyUsername=self.httpProxyUsername,
                                       httpProxyPassword=self.httpProxyPassword,
                                       caChain=self.caChain)

        f = rep.get_function(funct)
        if not f:
            raise rhnFault(1000,
                _("Spacewalk Proxy configuration error: invalid function %s") % funct)

        log_debug(3, "Calling %s(%s)" % (funct, params))
        if params is None:
            params = ()
        try:
            ret = f(*params)
        except rhnRepository.NotLocalError:
            # The package is not local
            return None
        return ret
Пример #10
0
def _verifyProxyAuthToken(auth_token):
    """ verifies the validity of a proxy auth token

        NOTE: X-RHN-Proxy-Auth described in proxy/broker/rhnProxyAuth.py
    """

    log_debug(4, auth_token)
    token, hostname = splitProxyAuthToken(auth_token)
    hostname = hostname.strip()
    ipv4_regex = '^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])$'
    # This ipv6 regex was develeoped by Stephen Ryan at Dataware.
    # (http://forums.intermapper.com/viewtopic.php?t=452) It is licenced
    # under a Creative Commons Attribution-ShareAlike 3.0 Unported
    # License, so we are free to use it as long as we attribute it to him.
    ipv6_regex = '^((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?$'
    hostname_is_ip_address = re.match(ipv4_regex, hostname) or re.match(ipv6_regex, hostname)

    headers = rhnFlags.get('outputTransportOptions')
    if len(token) < 5:
        # Bad auth information; decline any action
        log_debug(4, "incomplete proxy authentication token: %s"
                  % auth_token)
        headers['X-RHN-Proxy-Auth-Error'] = '%s:%s' % (
            1003, _("incomplete proxy authentication token: %s") % auth_token)
        if not hostname_is_ip_address:
            headers['X-RHN-Proxy-Auth-Origin'] = hostname
        raise rhnFault(1003)  # Invalid session key

    log_debug(5, "proxy auth token: %s,  hostname: %s"
                 % (repr(token), hostname or 'n/a'))

    proxyId, proxyUser, rhnServerTime, expireOffset, signature = token[:5]
    computed = computeSignature(CFG.SECRET_KEY, proxyId, proxyUser,
                                rhnServerTime, expireOffset)

    if computed != signature:
        log_error("Proxy signature failed: proxy id='%s', proxy user='******'" %
                  (proxyId, proxyUser))
        log_debug(4, "Sent proxy signature %s does not match ours %s." % (
            signature, computed))
        headers['X-RHN-Proxy-Auth-Error'] = '%s:%s' % (
            1003, _("Sent proxy signature %s does not match ours %s.") % (
                signature, computed))
        if not hostname_is_ip_address:
            headers['X-RHN-Proxy-Auth-Origin'] = hostname
        raise rhnFault(1003)  # Invalid session key

    # Convert the expiration/time to floats:
    rhnServerTime = float(rhnServerTime)
    expireOffset = float(expireOffset)

    if rhnServerTime + expireOffset < time.time():
        log_debug(4, "Expired proxy authentication token")
        headers['X-RHN-Proxy-Auth-Error'] = '%s:%s' % (1004, "Expired")
        if not hostname_is_ip_address:
            headers['X-RHN-Proxy-Auth-Origin'] = hostname
        raise rhnFault(1004)  # Expired client authentication token

    log_debug(4, "Proxy auth OK: sigs match; not an expired token")
    return 1
Пример #11
0
    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)
Пример #12
0
    def __redirectFailover(self):
        """ This routine resends the original request back to the satellite/hosted
            system if a redirect to a 3rd party failed.  To prevent redirection loops
            from occurring, an "X-RHN-Redirect: 0" header is passed along with the
            request.  This function will return apache.HTTP_OK if everything
            succeeded, otherwise it will return an appropriate HTTP error code.
        """

        # Add a special header which will tell the server not to send us any
        # more redirects.

        headers = rhnFlags.get('outputTransportOptions')
        headers[rhnConstants.HEADER_RHN_REDIRECT] = '0'

        log_debug(4, "Added X-RHN-Redirect header to outputTransportOptions:",
                  headers)

        # Reset the existing connection and reconnect to the RHN parent server.

        self.responseContext.clear()
        self._connectToParent()

        # We'll just call serverCommo once more.  The X-RHN-Redirect constant
        # will prevent us from falling into an infinite loop.  Only GETs are
        # redirected, so we can safely pass an empty string in as the request
        # body.

        status = self._serverCommo()

        # This little hack isn't pretty, but lets us normalize our result code.

        if status == apache.OK:
            status = apache.HTTP_OK

        return status
Пример #13
0
    def _proxy2server(self):
        hdrs = rhnFlags.get('outputTransportOptions')
        log_debug(3, hdrs)
        size = -1

        # Put the headers into the output connection object
        http_connection = self.responseContext.getConnection()
        for (k, vals) in hdrs.items():
            if k.lower() in ['content_length', 'content-length']:
                try:
                    size = int(vals)
                except ValueError:
                    pass
            if k.lower() in ['content_length', 'content_type']:
                # mod_wsgi modifies incoming headers so we have to transform them back
                k = k.replace('_', '-')
            if not (k.lower()[:2] == 'x-' or
                    k.lower() in [  # all but 'host', and 'via'
                        'accept', 'accept-charset', 'accept-encoding', 'accept-language',
                        'accept-ranges', 'age', 'allow', 'authorization', 'cache-control',
                        'connection', 'content-encoding', 'content-language', 'content-length',
                        'content-location', 'content-md5', 'content-range', 'content-type',
                        'date', 'etag', 'expect', 'expires', 'from', 'if-match',
                        'if-modified-since', 'if-none-match', 'if-range', 'if-unmodified-since',
                        'last-modified', 'location', 'max-forwards', 'pragma', 'proxy-authenticate',
                        'proxy-authorization', 'range', 'referer', 'retry-after', 'server',
                        'te', 'trailer', 'transfer-encoding', 'upgrade', 'user-agent', 'vary',
                        'warning', 'www-authenticate']):
                # filter out header we don't want to send
                continue
            if not isinstance(vals, (ListType, TupleType)):
                vals = [vals]
            for v in vals:
                log_debug(5, "Outgoing header", k, v)
                http_connection.putheader(k, v)
        http_connection.endheaders()

        # Send the body too if there is a body
        if size > 0:
            # reset file to beginning so it can be read again
            self.req.headers_in['wsgi.input'].seek(0, 0)
            if sys.version_info < (2, 6):
                data = self.req.headers_in['wsgi.input'].read(size)
            else:
                data = self.req.headers_in['wsgi.input']
            http_connection.send(data)

        # At this point everything is sent to the server
        # We now wait for the response
        try:
            response = http_connection.getresponse()
        except TimeoutException:
            log_error("Connection timed out")
            return apache.HTTP_GATEWAY_TIME_OUT, None, None
        headers = response.msg
        status = response.status
        # Get the body of the request too - well, just a fd actually
        # in this case, the response object itself.
        bodyFd = response
        return status, headers, bodyFd
Пример #14
0
 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
Пример #15
0
    def getPackageErratum(self, system_id, pkg):
        """ Clients v2+ - Get errata for a package given [n,v,r,e,a,...] format

            Sing-along: You say erratum(sing), I say errata(pl)! :)
            IN:  pkg:   [n,v,r,e,s,a,ch,...]
            RET: a hash by errata that applies to this package
        """
        log_debug(5, system_id, pkg)
        if type(pkg) != type([]) or len(pkg) < 7:
            log_error("Got invalid package specification: %s" % str(pkg))
            raise rhnFault(30, _("Expected a package, not: %s") % pkg)
        # Authenticate and decode server id.
        self.auth_system(system_id)
        # log the entry
        log_debug(1, self.server_id, pkg)
        # Stuff the action in the headers:
        transport = rhnFlags.get("outputTransportOptions")
        transport["X-RHN-Action"] = "getPackageErratum"

        name, ver, rel, epoch, arch, size, channel = pkg[:7]
        if epoch in ["", "none", "None"]:
            epoch = None

        # XXX: also, should arch/size/channel ever be used?
        # bug#186996:adding synopsis field to errata info
        # client side changes are needed to access this data.
        h = rhnSQL.prepare(
            """
        select distinct
            e.id            errata_id,
            e.advisory_type errata_type,
            e.advisory      advisory,
            e.topic         topic,
            e.description   description,
            e.synopsis      synopsis
        from
            rhnServerChannel sc,
            rhnChannelPackage cp,
            rhnChannelErrata ce,
            rhnErrata e,
            rhnErrataPackage ep,
            rhnPackage p
        where
            p.name_id = LOOKUP_PACKAGE_NAME(:name)
        and p.evr_id = LOOKUP_EVR(:epoch, :ver, :rel)
        -- map to a channel
        and p.id = cp.package_id
        -- map to an errata as well
        and p.id = ep.package_id
        and ep.errata_id = e.id
        -- the errata and the channel have to be linked
        and e.id = ce.errata_id
        and ce.channel_id = cp.channel_id
        -- and the server has to be subscribed to the channel
        and cp.channel_id = sc.channel_id
        and sc.server_id = :server_id
        """
        )  # " emacs sucks
        h.execute(name=name, ver=ver, rel=rel, epoch=epoch, server_id=str(self.server_id))
        return self._sanitize_result(h)
Пример #16
0
def _set_server_capabilities():
    # XXX Will have to figure out how to define this
    capabilities = {
        'registration.register_osad'            : {'version' : 1, 'value' : 1},
        'registration.finish_message'           : {'version' : 1, 'value' : 1},
        'registration.remaining_subscriptions'  : {'version' : 1, 'value' : 1},
        'registration.update_contact_info'      : {'version' : 1, 'value' : 1},
        'registration.delta_packages'           : {'version' : 1, 'value' : 1},
        'registration.extended_update_support'  : {'version' : 1, 'value' : 1},
        'registration.smbios'                   : {'version' : 1, 'value' : 1},
        'registration.update_systemid'          : {'version' : 1, 'value' : 1},
        'applet.has_base_channel'               : {'version' : 1, 'value' : 1},
        'xmlrpc.login.extra_data'               : {'version' : 1, 'value' : 1},
        'rhncfg.content.base64_decode'          : {'version' : 1, 'value' : 1},
        'rhncfg.filetype.directory'             : {'version' : 1, 'value' : 1},
        'xmlrpc.packages.extended_profile'      : {'version' : '1-2', 'value' : 1},
        'xmlrpc.packages.checksums'             : {'version' : 1, 'value' : 1},
        'xmlrpc.errata.patch_names'             : {'version' : 1, 'value' : 1},
        'staging_content'                       : {'version' : 1, 'value' : 1},
        'ipv6'                                  : {'version' : 1, 'value' : 1},
        'abrt'                                  : {'version' : 1, 'value' : 1},
        'cpu_sockets'                           : {'version' : 1, 'value' : 1},
    }
    l = []
    for name, hashval in capabilities.items():
        l.append("%s(%s)=%s" % (name, hashval['version'], hashval['value']))

    log_debug(4, "Setting capabilities", l)
    rhnFlags.get("outputTransportOptions")['X-RHN-Server-Capability'] = l
Пример #17
0
    def process_kickstart_info(self):
        log_debug(4)
        tokens_obj = rhnFlags.get("registration_token")
        if not tokens_obj:
            log_debug(4, "no registration token found")
            # Nothing to do here
            return

        # If there are kickstart sessions associated with this system (other
        # than, possibly, the current one), mark them as failed
        history = server_kickstart.terminate_kickstart_sessions(self.getid())
        for k, v in history:
            self.add_history(k, v)

        kickstart_session_id = tokens_obj.get_kickstart_session_id()
        if kickstart_session_id is None:
            log_debug(
                4, "No kickstart_session_id associated with token %s (%s)" % (tokens_obj.get_names(), tokens_obj.tokens)
            )

            # Nothing to do here
            return

        # Flush server actions
        self.flush_actions()

        server_id = self.getid()
        action_id = server_kickstart.schedule_kickstart_sync(server_id, kickstart_session_id)

        server_kickstart.subscribe_to_tools_channel(server_id, kickstart_session_id)

        server_kickstart.schedule_virt_pkg_install(server_id, kickstart_session_id)

        # Update the next action to the newly inserted one
        server_kickstart.update_ks_session_table(kickstart_session_id, "registered", action_id, server_id)
Пример #18
0
    def load_token(self):
        # Fetch token
        tokens_obj = rhnFlags.get("registration_token")
        if not tokens_obj:
            # No tokens present
            return 0

        # make sure we have reserved a server_id. most likely if this
        # is a new server object (just created from
        # registration.new_system) then we have no associated a
        # server["id"] yet -- and getid() will reserve that for us.
        self.getid()
        # pull in the extra information needed to fill in the
        # required registration fields using tokens

        user_id = tokens_obj.get_user_id()
        org_id = tokens_obj.get_org_id()

        self.user = rhnUser.User("", "")
        if user_id is not None:
            self.user.reload(user_id)
        self.server["creator_id"] = user_id
        self.server["org_id"] = org_id
        self.server["contact_method_id"] = tokens_obj.get_contact_method_id()
        return 0
Пример #19
0
def reboot(server_id, action_id, data={}):
    log_debug(3, action_id)

    action_status = rhnFlags.get('action_status')
    server_kickstart.update_kickstart_session(server_id, action_id,
        action_status, kickstart_state='restarted',
        next_action_type=None)
Пример #20
0
def reboot(server_id, action_id, data={}):
    log_debug(3, action_id)

    action_status = rhnFlags.get('action_status')
    server_kickstart.update_kickstart_session(server_id, action_id,
        action_status, kickstart_state='restarted',
        next_action_type=None)
Пример #21
0
def _verifyProxyAuthToken(auth_token):
    """ verifies the validity of a proxy auth token

        NOTE: X-RHN-Proxy-Auth described in proxy/broker/rhnProxyAuth.py
    """

    log_debug(4, auth_token)
    token, hostname = splitProxyAuthToken(auth_token)
    hostname = hostname.strip()
    ipv4_regex = '^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])$'
    # This ipv6 regex was develeoped by Stephen Ryan at Dataware.
    # (http://forums.intermapper.com/viewtopic.php?t=452) It is licenced
    # under a Creative Commons Attribution-ShareAlike 3.0 Unported
    # License, so we are free to use it as long as we attribute it to him.
    ipv6_regex = '^((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?$'
    hostname_is_ip_address = re.match(ipv4_regex, hostname) or re.match(ipv6_regex, hostname)

    headers = rhnFlags.get('outputTransportOptions')
    if len(token) < 5:
        # Bad auth information; decline any action
        log_debug(4, "incomplete proxy authentication token: %s"
                  % auth_token)
        headers['X-RHN-Proxy-Auth-Error'] = '%s:%s' % (
            1003, _("incomplete proxy authentication token: %s") % auth_token)
        if not hostname_is_ip_address:
            headers['X-RHN-Proxy-Auth-Origin'] = hostname
        raise rhnFault(1003)  # Invalid session key

    log_debug(5, "proxy auth token: %s,  hostname: %s"
                 % (repr(token), hostname or 'n/a'))

    proxyId, proxyUser, rhnServerTime, expireOffset, signature = token[:5]
    computed = computeSignature(CFG.SECRET_KEY, proxyId, proxyUser,
                                rhnServerTime, expireOffset)

    if computed != signature:
        log_error("Proxy signature failed: proxy id='%s', proxy user='******'" %
                  (proxyId, proxyUser))
        log_debug(4, "Sent proxy signature %s does not match ours %s." % (
            signature, computed))
        headers['X-RHN-Proxy-Auth-Error'] = '%s:%s' % (
            1003, _("Sent proxy signature %s does not match ours %s.") % (
                signature, computed))
        if not hostname_is_ip_address:
            headers['X-RHN-Proxy-Auth-Origin'] = hostname
        raise rhnFault(1003)  # Invalid session key

    # Convert the expiration/time to floats:
    rhnServerTime = float(rhnServerTime)
    expireOffset = float(expireOffset)

    if rhnServerTime + expireOffset < time.time():
        log_debug(4, "Expired proxy authentication token")
        headers['X-RHN-Proxy-Auth-Error'] = '%s:%s' % (1004, "Expired")
        if not hostname_is_ip_address:
            headers['X-RHN-Proxy-Auth-Origin'] = hostname
        raise rhnFault(1004)  # Expired client authentication token

    log_debug(4, "Proxy auth OK: sigs match; not an expired token")
    return 1
Пример #22
0
    def getPackagePath(self, pkgFilename, redirect_capable=0):
        """ Retrieves package path
        Overloads getPackagePath in common/rhnRepository.
        checks if redirect and hosted;
        makes a call to query the db for pkg_location
        """

        log_debug(2, pkgFilename, redirect_capable)
        # check for re-direct check flag from header to issue package
        # request from client in order to avoid failover loops.
        skip_redirect = rhnFlags.get('x-rhn-redirect')
        log_debug(3, "check flag for X-RHN-REDIRECT  ::", skip_redirect)

        # get the redirect and local paths
        remotepath, localpath = self.getAllPackagePaths(pkgFilename)

        # check for redirect conditions and fail over checks
        if redirect_capable and not CFG.SATELLITE and not skip_redirect \
                and remotepath is not None:
            self.redirect_location = remotepath
            # We've set self.redirect_location, we're done here
            # we throw a redirectException in _getFile method.
            return None
            # Package cannot be served from the edge, we serve it ourselves
        return localpath
Пример #23
0
    def _proxy2server(self):
        hdrs = rhnFlags.get('outputTransportOptions')
        log_debug(3, hdrs)
        size = -1

        # Put the headers into the output connection object
        http_connection = self.responseContext.getConnection()
        for (k, vals) in hdrs.items():
            if k.lower() in ['content_length', 'content-length']:
                try:
                    size = int(vals)
                except ValueError:
                    pass
            if k.lower() in ['content_length', 'content_type']:
                # mod_wsgi modifies incoming headers so we have to transform them back
                k = k.replace('_', '-')
            if not (k.lower()[:2] == 'x-' or
                    k.lower() in [  # all but 'host', and 'via'
                        'accept', 'accept-charset', 'accept-encoding', 'accept-language',
                        'accept-ranges', 'age', 'allow', 'authorization', 'cache-control',
                        'connection', 'content-encoding', 'content-language', 'content-length',
                        'content-location', 'content-md5', 'content-range', 'content-type',
                        'date', 'etag', 'expect', 'expires', 'from', 'if-match',
                        'if-modified-since', 'if-none-match', 'if-range', 'if-unmodified-since',
                        'last-modified', 'location', 'max-forwards', 'pragma', 'proxy-authenticate',
                        'proxy-authorization', 'range', 'referer', 'retry-after', 'server',
                        'te', 'trailer', 'transfer-encoding', 'upgrade', 'user-agent', 'vary',
                        'warning', 'www-authenticate']):
                # filter out header we don't want to send
                continue
            if type(vals) not in (ListType, TupleType):
                vals = [vals]
            for v in vals:
                log_debug(5, "Outgoing header", k, v)
                http_connection.putheader(k, v)
        http_connection.endheaders()

        # Send the body too if there is a body
        if size > 0:
            # reset file to beginning so it can be read again
            self.req.headers_in['wsgi.input'].seek(0, 0)
            if sys.version_info < (2, 6):
                data = self.req.headers_in['wsgi.input'].read(size)
            else:
                data = self.req.headers_in['wsgi.input']
            http_connection.send(data)

        # At this point everything is sent to the server
        # We now wait for the response
        try:
            response = http_connection.getresponse()
        except TimeoutException:
            log_error("Connection timed out")
            return apache.HTTP_GATEWAY_TIME_OUT, None, None
        headers = response.msg
        status = response.status
        # Get the body of the request too - well, just a fd actually
        # in this case, the response object itself.
        bodyFd = response
        return status, headers, bodyFd
Пример #24
0
    def getxml(self):

        # see if there were any template strings loaded from the db,
        # {label:value}
        templateOverrides = rhnFlags.get('templateOverrides')

        # update the templateValues in the module
        if templateOverrides:
            for label in templateOverrides.keys():
                # only care about values we've defined defaults for...
                if label in templateValues:
                    templateValues[label] = templateOverrides[label]

        s = StringIO()
        s.write("\n")
        if self.text:
            s.write(_("Error Message:\n    %s\n") % self.text.strip())
        if self.code:
            s.write(_("Error Class Code: %s\n") % self.code)
        if self.arrayText:
            cinfo = self.arrayText % templateValues
            s.write(_("Error Class Info: %s\n") % cinfo.rstrip())
        if self.explain:
            s.write(_("Explanation: %s") % Explain)
        if not self.code:
            return xmlrpclib.Fault(1, s.getvalue())
        return xmlrpclib.Fault(-self.code, s.getvalue())
Пример #25
0
    def __redirectFailover(self):
        """ This routine resends the original request back to the satellite/hosted
            system if a redirect to a 3rd party failed.  To prevent redirection loops
            from occurring, an "X-RHN-Redirect: 0" header is passed along with the
            request.  This function will return apache.HTTP_OK if everything
            succeeded, otherwise it will return an appropriate HTTP error code.
        """

        # Add a special header which will tell the server not to send us any
        # more redirects.

        headers = rhnFlags.get('outputTransportOptions')
        headers[rhnConstants.HEADER_RHN_REDIRECT] = '0'

        log_debug(4, "Added X-RHN-Redirect header to outputTransportOptions:",
                  headers)

        # Reset the existing connection and reconnect to the RHN parent server.

        self.responseContext.clear()
        self._connectToParent()

        # We'll just call serverCommo once more.  The X-RHN-Redirect constant
        # will prevent us from falling into an infinite loop.  Only GETs are
        # redirected, so we can safely pass an empty string in as the request
        # body.

        status = self._serverCommo()

        # This little hack isn't pretty, but lets us normalize our result code.

        if status == apache.OK:
            status = apache.HTTP_OK

        return status
Пример #26
0
    def listChannels(self, system_id):
        """ Clients v2+ """
        log_debug(5, system_id)
        # Authenticate the system certificate
        self.auth_system('listChannels', system_id)
        # log the entry
        log_debug(1, self.server_id)
        channelList = rhnChannel.channels_for_server(self.server_id)

        loginDict = {
            'X-RHN-Server-Id':
            self.server_id,
            'X-RHN-Auth-Channels':
            rhnChannel.getSubscribedChannels(self.server_id),
        }

        # Duplicate these values in the headers so that the proxy can
        # intercept and cache them without parseing the xmlrpc.
        transport = rhnFlags.get('outputTransportOptions')
        for k, v in list(loginDict.items()):
            # Special case for channels
            if k.lower() == 'x-rhn-auth-channels'.lower():
                # Concatenate the channel information column-separated
                transport[k] = [':'.join(x) for x in v]
            else:
                transport[k] = v
        return channelList
Пример #27
0
    def getxml(self):

        # see if there were any template strings loaded from the db,
        # {label:value}
        templateOverrides = rhnFlags.get('templateOverrides')

        # update the templateValues in the module
        if templateOverrides:
            for label in templateOverrides.keys():
                # only care about values we've defined defaults for...
                if label in templateValues:
                    templateValues[label] = templateOverrides[label]

        s = StringIO()
        s.write("\n")
        if self.text:
            s.write(_("Error Message:\n    %s\n") % self.text.strip())
        if self.code:
            s.write(_("Error Class Code: %s\n") % self.code)
        if self.arrayText:
            cinfo = self.arrayText % templateValues
            s.write(_("Error Class Info: %s\n") % cinfo.rstrip())
        if self.explain:
            s.write(_("Explanation: %s") % Explain)
        if not self.code:
            return xmlrpclib.Fault(1, s.getvalue())
        return xmlrpclib.Fault(-self.code, s.getvalue())
Пример #28
0
    def load_token(self):
        # Fetch token
        tokens_obj = rhnFlags.get("registration_token")
        if not tokens_obj:
            # No tokens present
            return 0

        # make sure we have reserved a server_id. most likely if this
        # is a new server object (just created from
        # registration.new_system) then we have no associated a
        # server["id"] yet -- and getid() will reserve that for us.
        self.getid()
        # pull in the extra information needed to fill in the
        # required registration fields using tokens

        user_id = tokens_obj.get_user_id()
        org_id = tokens_obj.get_org_id()

        self.user = rhnUser.User("", "")
        if user_id is not None:
            self.user.reload(user_id)
        self.server["creator_id"] = user_id
        self.server["org_id"] = org_id
        self.server["contact_method_id"] = tokens_obj.get_contact_method_id()
        return 0
Пример #29
0
    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)
Пример #30
0
def update(server_id, action_id, data={}):
    log_debug(3, server_id, action_id)

    action_status = rhnFlags.get('action_status')

    if action_status == 3:
        # Action failed
        kickstart_state = 'failed'
        next_action_type = None
    else:
        kickstart_state = 'deployed'

        #This is horrendous, but in order to fix it I would have to change almost all of the
        #actions code, which we don't have time to do for the 500 beta. --wregglej
        try:
            ks_session_type = server_kickstart.get_kickstart_session_type(server_id, action_id)
        except rhnException, re:
            ks_session_type = None

        if ks_session_type is None:
            next_action_type = "None"
        elif ks_session_type == 'para_guest':
            next_action_type = 'kickstart_guest.initiate'
        else:
            next_action_type = 'kickstart.initiate'
Пример #31
0
def initiate(server_id, action_id, data={}):
    log_debug(3, action_id)

    action_status = rhnFlags.get('action_status')
    server_kickstart.update_kickstart_session(server_id, action_id,
                                              action_status, kickstart_state='injected',
                                              next_action_type='reboot.reboot')
Пример #32
0
 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
Пример #33
0
    def getPackagePath(self, pkgFilename, redirect_capable=0):
        """ Retrieves package path
        Overloads getPackagePath in common/rhnRepository.
        checks if redirect and hosted;
        makes a call to query the db for pkg_location
        """

        log_debug(2, pkgFilename, redirect_capable)
        # check for re-direct check flag from header to issue package
        # request from client in order to avoid failover loops.
        skip_redirect = rhnFlags.get('x-rhn-redirect')
        log_debug(3, "check flag for X-RHN-REDIRECT  ::", skip_redirect)

        # get the redirect and local paths
        remotepath, localpath = self.getAllPackagePaths(pkgFilename)

        # check for redirect conditions and fail over checks
        if redirect_capable and not CFG.SATELLITE and not skip_redirect \
                and remotepath is not None:
            self.redirect_location = remotepath
            # We've set self.redirect_location, we're done here
            # we throw a redirectException in _getFile method.
            return None
            # Package cannot be served from the edge, we serve it ourselves
        return localpath
Пример #34
0
def update(server_id, action_id, data={}):
    log_debug(3, server_id, action_id)

    action_status = rhnFlags.get('action_status')

    if action_status == 3:
        # Action failed
        kickstart_state = 'failed'
        next_action_type = None
    else:
        kickstart_state = 'deployed'

        #This is horrendous, but in order to fix it I would have to change almost all of the
        #actions code, which we don't have time to do for the 500 beta. --wregglej
        try:
            ks_session_type = server_kickstart.get_kickstart_session_type(server_id, action_id)
        except rhnException, re:
            ks_session_type = None

        if ks_session_type is None:
            next_action_type = "None"
        elif ks_session_type == 'para_guest':
            next_action_type = 'kickstart_guest.initiate'
        else:
            next_action_type = 'kickstart.initiate'
Пример #35
0
def _set_server_capabilities():
    # XXX Will have to figure out how to define this
    capabilities = {
        "registration.register_osad": {"version": 1, "value": 1},
        "registration.finish_message": {"version": 1, "value": 1},
        "registration.remaining_subscriptions": {"version": 1, "value": 1},
        "registration.update_contact_info": {"version": 1, "value": 1},
        "registration.delta_packages": {"version": 1, "value": 1},
        "registration.extended_update_support": {"version": 1, "value": 1},
        "registration.smbios": {"version": 1, "value": 1},
        "registration.update_systemid": {"version": 1, "value": 1},
        "applet.has_base_channel": {"version": 1, "value": 1},
        "xmlrpc.login.extra_data": {"version": 1, "value": 1},
        "rhncfg.content.base64_decode": {"version": 1, "value": 1},
        "rhncfg.filetype.directory": {"version": 1, "value": 1},
        "xmlrpc.packages.extended_profile": {"version": "1-2", "value": 1},
        "xmlrpc.packages.checksums": {"version": 1, "value": 1},
        "xmlrpc.errata.patch_names": {"version": 1, "value": 1},
        "staging_content": {"version": 1, "value": 1},
        "ipv6": {"version": 1, "value": 1},
        "abrt": {"version": 1, "value": 1},
        "cpu_sockets": {"version": 1, "value": 1},
    }
    l = []
    for name, hashval in capabilities.items():
        l.append("%s(%s)=%s" % (name, hashval["version"], hashval["value"]))

    log_debug(4, "Setting capabilities", l)
    rhnFlags.get("outputTransportOptions")["X-RHN-Server-Capability"] = l
Пример #36
0
def initiate(server_id, action_id, data={}):
    log_debug(3, action_id)

    action_status = rhnFlags.get('action_status')
    server_kickstart.update_kickstart_session(server_id, action_id,
        action_status, kickstart_state='injected',
        next_action_type='reboot.reboot')
Пример #37
0
    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:
Пример #38
0
    def GetByPackage(self, pkg, osRel):
        """ Clients v1- Get errata for a package given "n-v-r" format
            IN:  pkg:   "n-v-r" (old client call)
                        or [n,v,r]
                 osRel: OS release
            RET: a hash by errata that applies to this package
                 (ie, newer packages are available). We also limit the scope
                 for a particular osRel.
        """
        if type(pkg) == type(''):  # Old client support.
            pkg = parseRPMName(pkg)
        log_debug(1, pkg, osRel)
        # Stuff the action in the headers:
        transport = rhnFlags.get('outputTransportOptions')
        transport['X-RHN-Action'] = 'GetByPackage'

        # now look up the errata
        if type(pkg[0]) != type(''):
            log_error("Invalid package name: %s %s" % (type(pkg[0]), pkg[0]))
            raise rhnFault(30, _("Expected a package name, not: %s") % pkg[0])
        # bug#186996:adding synopsis field to advisory info
        # client side changes are needed to access this data.
        h = rhnSQL.prepare("""
            select distinct
                    e.id            errata_id,
                    e.advisory_type errata_type,
                    e.advisory      advisory,
                    e.topic         topic,
                    e.description   description,
                    e.synopsis      synopsis
            from
                    rhnErrata e,
                    rhnPublicChannelFamily pcf,
                    rhnChannelFamilyMembers cfm,
                    rhnErrataPackage ep,
                    rhnChannelPackage cp,
                    rhnChannelErrata ce,
                    rhnDistChannelMap dcm,
                    rhnPackage p
            where    1=1
                and p.name_id = LOOKUP_PACKAGE_NAME(:name)
                -- map to a channel
                and p.id = cp.package_id
                and cp.channel_id = dcm.channel_id
                and dcm.release = :dist
                and dcm.org_id is null
                -- map to an errata as well
                and p.id = ep.package_id
                and ep.errata_id = e.id
                -- the errata and the channel have to be linked
                and ce.channel_id = cp.channel_id
                -- and the channel has to be public
                and cp.channel_id = cfm.channel_id
                and cfm.channel_family_id = pcf.channel_family_id
                -- and get the erratum
                and e.id = ce.errata_id
        """)
        h.execute(name=pkg[0], dist=str(osRel))
        return self._sanitize_result(h)
Пример #39
0
    def getPackageErratum(self, system_id, pkg):
        """ Clients v2+ - Get errata for a package given [n,v,r,e,a,...] format

            Sing-along: You say erratum(sing), I say errata(pl)! :)
            IN:  pkg:   [n,v,r,e,s,a,ch,...]
            RET: a hash by errata that applies to this package
        """
        log_debug(5, system_id, pkg)
        if type(pkg) != type([]) or len(pkg) < 7:
            log_error("Got invalid package specification: %s" % str(pkg))
            raise rhnFault(30, _("Expected a package, not: %s") % pkg)
        # Authenticate and decode server id.
        self.auth_system(system_id)
        # log the entry
        log_debug(1, self.server_id, pkg)
        # Stuff the action in the headers:
        transport = rhnFlags.get('outputTransportOptions')
        transport['X-RHN-Action'] = 'getPackageErratum'

        name, ver, rel, epoch, arch, size, channel = pkg[:7]
        if epoch in ['', 'none', 'None']:
            epoch = None

        # XXX: also, should arch/size/channel ever be used?
        # bug#186996:adding synopsis field to errata info
        # client side changes are needed to access this data.
        h = rhnSQL.prepare("""
        select distinct
            e.id            errata_id,
            e.advisory_type errata_type,
            e.advisory      advisory,
            e.topic         topic,
            e.description   description,
            e.synopsis      synopsis
        from
            rhnServerChannel sc,
            rhnChannelPackage cp,
            rhnChannelErrata ce,
            rhnErrata e,
            rhnErrataPackage ep,
            rhnPackage p
        where
            p.name_id = LOOKUP_PACKAGE_NAME(:name)
        and p.evr_id = LOOKUP_EVR(:epoch, :ver, :rel)
        -- map to a channel
        and p.id = cp.package_id
        -- map to an errata as well
        and p.id = ep.package_id
        and ep.errata_id = e.id
        -- the errata and the channel have to be linked
        and e.id = ce.errata_id
        and ce.channel_id = cp.channel_id
        -- and the server has to be subscribed to the channel
        and cp.channel_id = sc.channel_id
        and sc.server_id = :server_id
        """)  # " emacs sucks
        h.execute(name=name, ver=ver, rel=rel, epoch=epoch,
                  server_id=str(self.server_id))
        return self._sanitize_result(h)
Пример #40
0
    def GetByPackage(self, pkg, osRel):
        """ Clients v1- Get errata for a package given "n-v-r" format
            IN:  pkg:   "n-v-r" (old client call)
                        or [n,v,r]
                 osRel: OS release
            RET: a hash by errata that applies to this package
                 (ie, newer packages are available). We also limit the scope
                 for a particular osRel.
        """
        if type(pkg) == type(''):  # Old client support.
            pkg = parseRPMName(pkg)
        log_debug(1, pkg, osRel)
        # Stuff the action in the headers:
        transport = rhnFlags.get('outputTransportOptions')
        transport['X-RHN-Action'] = 'GetByPackage'

        # now look up the errata
        if type(pkg[0]) != type(''):
            log_error("Invalid package name: %s %s" % (type(pkg[0]), pkg[0]))
            raise rhnFault(30, _("Expected a package name, not: %s") % pkg[0])
        # bug#186996:adding synopsis field to advisory info
        # client side changes are needed to access this data.
        h = rhnSQL.prepare("""
            select distinct
                    e.id            errata_id,
                    e.advisory_type errata_type,
                    e.advisory      advisory,
                    e.topic         topic,
                    e.description   description,
                    e.synopsis      synopsis
            from
                    rhnErrata e,
                    rhnPublicChannelFamily pcf,
                    rhnChannelFamilyMembers cfm,
                    rhnErrataPackage ep,
                    rhnChannelPackage cp,
                    rhnChannelErrata ce,
                    rhnDistChannelMap dcm,
                    rhnPackage p
            where    1=1
                and p.name_id = LOOKUP_PACKAGE_NAME(:name)
                -- map to a channel
                and p.id = cp.package_id
                and cp.channel_id = dcm.channel_id
                and dcm.release = :dist
                and dcm.org_id is null
                -- map to an errata as well
                and p.id = ep.package_id
                and ep.errata_id = e.id
                -- the errata and the channel have to be linked
                and ce.channel_id = cp.channel_id
                -- and the channel has to be public
                and cp.channel_id = cfm.channel_id
                and cfm.channel_family_id = pcf.channel_family_id
                -- and get the erratum
                and e.id = ce.errata_id
        """)
        h.execute(name=pkg[0], dist=str(osRel))
        return self._sanitize_result(h)
Пример #41
0
 def __init__(self):
     # We store the security list in the global flags. This way, we don't
     # have to worry about clearing it up.
     if rhnFlags.test(self._flag_string):
         self.sec = rhnFlags.get(self._flag_string)
     else:
         self.sec = []
         rhnFlags.set(self._flag_string, self.sec)
Пример #42
0
def deploy(server_id, action_id, data={}):
    log_debug(3)

    action_status = rhnFlags.get('action_status')
    server_kickstart.update_kickstart_session(server_id,
                                              action_id, action_status, kickstart_state='complete',
                                              next_action_type=None)
    return
Пример #43
0
 def __init__(self):
     # We store the security list in the global flags. This way, we don't
     # have to worry about clearing it up.
     if rhnFlags.test(self._flag_string):
         self.sec = rhnFlags.get(self._flag_string)
     else:
         self.sec = []
         rhnFlags.set(self._flag_string, self.sec)
Пример #44
0
    def _prepHandler(self):
        """ Handler part 0 """

        # Just to be on the safe side
        if self.req.main:
            # A subrequest
            return apache.DECLINE
        log_debug(4, rhnFlags.all())

        if not self.rhnParent:
            raise rhnException("Oops, no proxy parent! Exiting")

        # Copy the headers.
        rhnFlags.get('outputTransportOptions').clear()
        rhnFlags.get('outputTransportOptions').update(self._getHeaders(self.req))

        return apache.OK
Пример #45
0
    def _prepHandler(self):
        """ Handler part 0 """

        # Just to be on the safe side
        if self.req.main:
            # A subrequest
            return apache.DECLINED
        log_debug(4, rhnFlags.all())

        if not self.rhnParent:
            raise rhnException("Oops, no proxy parent! Exiting")

        # Copy the headers.
        rhnFlags.get('outputTransportOptions').clear()
        rhnFlags.get('outputTransportOptions').update(self._getHeaders(self.req))

        return apache.OK
Пример #46
0
def deploy(server_id, action_id, data={}):
    log_debug(3)

    action_status = rhnFlags.get('action_status')
    server_kickstart.update_kickstart_session(server_id,
            action_id, action_status, kickstart_state='complete',
            next_action_type=None)
    return
Пример #47
0
    def response_file(req, response):
        """ send a file out """

        log_debug(1, response.name)
        # We may set the content type remotely
        if rhnFlags.test("Content-Type"):
            req.content_type = rhnFlags.get("Content-Type")
        else:
            # Safe default
            req.content_type = "application/octet-stream"

        # find out the size of the file
        if response.length == 0:
            response.file_obj.seek(0, 2)
            size = response.file_obj.tell()
            response.file_obj.seek(0, 0)
        else:
            size = response.length
        req.headers_out["Content-Length"] = str(size)

        # if we loaded this from a real fd, set it as the X-Replace-Content
        # check for "name" since sometimes we get xmlrpclib.File's that have
        # a stringIO as the file_obj, and they dont have a .name (ie,
        # fileLists...)
        if response.name:
            req.headers_out["X-Package-FileName"] = response.name

        # yum can request for HTTP_PARTIAL_CONTENT content
        if req.headers_in.has_key('Range'):
            (start, end) = parse_byteranges(req.headers_in['Range'], size)
            req.headers_out["Accept-Ranges"] = "bytes"
            req.headers_out["Content-Range"] = get_content_range(
                start, end, size)
            size = end - start + 1
            response.file_obj.seek(start, 0)
            status = apache.HTTP_PARTIAL_CONTENT
        else:
            start = 0
            end = size
            status = apache.OK

        # send the headers
        req.send_http_header()
        # and the file
        buffer_size = CFG.BUFFER_SIZE
        while 1:
            if buffer_size > size:
                buffer_size = size
            buf = response.read(buffer_size)
            size = size - buffer_size
            if not buf:
                break
            try:
                req.write(buf)
            except IOError:
                return apache.HTTP_BAD_REQUEST
        response.close()
        return status
Пример #48
0
    def response_file(req, response):
        """ send a file out """

        log_debug(1, response.name)
        # We may set the content type remotely
        if rhnFlags.test("Content-Type"):
            req.content_type = rhnFlags.get("Content-Type")
        else:
            # Safe default
            req.content_type = "application/octet-stream"

        # find out the size of the file
        if response.length == 0:
            response.file_obj.seek(0, 2)
            size = response.file_obj.tell()
            response.file_obj.seek(0, 0)
        else:
            size = response.length
        req.headers_out["Content-Length"] = str(size)

        # if we loaded this from a real fd, set it as the X-Replace-Content
        # check for "name" since sometimes we get xmlrpclib.File's that have
        # a stringIO as the file_obj, and they dont have a .name (ie,
        # fileLists...)
        if response.name:
            req.headers_out["X-Package-FileName"] = response.name

        # yum can request for HTTP_PARTIAL_CONTENT content
        if req.headers_in.has_key('Range'):
            (start, end)=parse_byteranges(req.headers_in['Range'], size)
            req.headers_out["Accept-Ranges"] = "bytes"
            req.headers_out["Content-Range"] = get_content_range(start, end, size)
            size = end - start + 1
            response.file_obj.seek(start, 0)
            status = apache.HTTP_PARTIAL_CONTENT
        else:
            start = 0
            end = size
            status = apache.OK

        # send the headers
        req.send_http_header()
        # and the file
        buffer_size = CFG.BUFFER_SIZE
        while 1:
            if buffer_size > size:
                buffer_size = size
            buf = response.read(buffer_size)
            size = size - buffer_size
            if not buf:
                break
            try:
                req.write(buf)
            except IOError:
                return apache.HTTP_BAD_REQUEST
        response.close()
        return status
Пример #49
0
    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:
Пример #50
0
 def _response_fault_get(req, response):
     req.err_headers_out["X-RHN-Fault-Code"] = str(response.faultCode)
     faultString = base64.encodestring(response.faultString).strip()
     # Split the faultString into multiple lines
     for line in faultString.split('\n'):
         req.err_headers_out.add("X-RHN-Fault-String", line.strip())
     # And then send all the other things
     for k, v in rhnFlags.get('outputTransportOptions').items():
         setHeaderValue(req.err_headers_out, k, v)
     return apache.HTTP_NOT_FOUND
Пример #51
0
 def _response_fault_get(req, response):
     req.headers_out["X-RHN-Fault-Code"] = str(response.faultCode)
     faultString = base64.encodestring(response.faultString).strip()
     # Split the faultString into multiple lines
     for line in faultString.split('\n'):
         req.headers_out.add("X-RHN-Fault-String", line.strip())
     # And then send all the other things
     for k, v in rhnFlags.get('outputTransportOptions').items():
         setHeaderValue(req.headers_out, k, v)
     return apache.HTTP_NOT_FOUND
Пример #52
0
 def __checkLegalRedirect(self):
     """ Check request to see if this coming from a RHN Proxy.
     
         THIS SHOULD NEVER FAIL!!!
         Probably not necessary, but stymies the casual abuser.
     """
     if not rhnFlags.get('outputTransportOptions').has_key('X-RHN-Proxy-Version'):
         log_debug(-1, 'THIS SHOULD NEVER HAPPEN!!!')
         raise rhnFault(1000,
             _("RHN Proxy Error: No SSL Redirect Request found!"))
Пример #53
0
def terminate_kickstart_sessions(server_id):
    log_debug(3, server_id)
    history = []
    tokens_obj = rhnFlags.get('registration_token')
    current_ks_session_id = tokens_obj.get_kickstart_session_id()
    # ks_session_id can be null
    h = rhnSQL.prepare(_query_lookup_pending_kickstart_sessions)
    h.execute(server_id=server_id, ks_session_id=current_ks_session_id)
    log_debug(4, "current_ks_session_id", current_ks_session_id)
    ks_session_ids = []
    action_ids = []
    while 1:
        row = h.fetchone_dict()
        if not row:
            break
        ks_session_ids.append(row['id'])
        action_ids.append(row['action_id'])

    if not ks_session_ids:
        # Nothing to do
        log_debug(4, "Nothing to do", server_id, current_ks_session_id)
        return []

    ks_session_table = rhnSQL.Table('rhnKickstartSessionState', 'label')
    state_id_failed = ks_session_table['failed']['id']
    state_ids = [state_id_failed] * len(ks_session_ids)

    # Add a history item
    for ks_session_id in ks_session_ids:
        log_debug(4, "Adding history entry for session id", ks_session_id)
        history.append(
            ("Kickstart session canceled",
             "A kickstart session for this system was canceled because "
             "the system was re-registered with token <strong>%s</strong>" %
             tokens_obj.get_names()))

    h = rhnSQL.prepare(_query_terminate_pending_kickstart_sessions)

    params = {
        'kickstart_session_id': ks_session_ids,
        'state_id': state_ids,
    }
    # Terminate pending actions
    log_debug(4, "Terminating sessions", params)
    h.execute_bulk(params)

    # Invalidate pending actions
    for action_id in action_ids:
        if action_id is None:
            continue
        rhnAction.invalidate_action(server_id, action_id)
    return history
Пример #54
0
    def login(self, system_id, extra_data={}):
        """ Clients v2+
            Log in routine.
            Return a dictionary of session token/channel information.
            Also sets this information in the headers.
        """
        log_debug(5, system_id)
        # Authenticate the system certificate. We need the user record
        # to generate the tokens
        self.load_user = 1
        server = self.auth_system('login', system_id)
        # log the entry
        log_debug(1, self.server_id)
        # Update the capabilities list
        rhnCapability.update_client_capabilities(self.server_id)
        # Fetch the channels this client is subscribed to
        channels = rhnChannel.getSubscribedChannels(self.server_id)

        rhnServerTime = str(time.time())
        expireOffset = str(CFG.CLIENT_AUTH_TIMEOUT)
        signature = computeSignature(CFG.SECRET_KEY,
                                     self.server_id,
                                     self.user,
                                     rhnServerTime,
                                     expireOffset)

        loginDict = {
            'X-RHN-Server-Id': self.server_id,
            'X-RHN-Auth-User-Id': self.user,
            'X-RHN-Auth': signature,
            'X-RHN-Auth-Server-Time': rhnServerTime,
            'X-RHN-Auth-Expire-Offset': expireOffset,
            # List of lists [[label,last_mod],...]:
            'X-RHN-Auth-Channels': channels
        }

        # Duplicate these values in the headers so that the proxy can
        # intercept and cache them without parseing the xmlrpc.
        transport = rhnFlags.get('outputTransportOptions')
        for k, v in loginDict.items():
            # Special case for channels
            if string.lower(k) == string.lower('X-RHN-Auth-Channels'):
                # Concatenate the channel information column-separated
                transport[k] = [string.join(x, ':') for x in v]
            else:
                transport[k] = v
        log_debug(5, "loginDict", loginDict, transport)

        # store route in DB (schema for RHN 3.1+ only!)
        server_route.store_client_route(self.server_id)

        return loginDict
Пример #55
0
    def response(self, response):
        log_debug(3)
        # pkilambi:if redirectException caught returns path(<str>)
        if isinstance(response, str):
            method, params = self._get_method_params()
            if method == "getPackage":
                return self.redirect(self.req, response)

        # GET requests resulting in a Fault receive special treatment
        # since we have to stick the error message in the HTTP header,
        # and to return an Apache error code

        if isinstance(response, xmlrpclib.Fault):
            log_debug(4, "Return FAULT",
                      response.faultCode, response.faultString)
            retcode = apache.HTTP_NOT_FOUND
            if abs(response.faultCode) in (33, 34, 35, 37, 39, 41):
                retcode = apache.HTTP_UNAUTHORIZED

            self.req.headers_out["X-RHN-Fault-Code"] = \
                str(response.faultCode)
            faultString = string.strip(base64.encodestring(
                response.faultString))
            # Split the faultString into multiple lines
            for line in string.split(faultString, '\n'):
                self.req.headers_out.add("X-RHN-Fault-String",
                                             string.strip(line))
            # And then send all the other things
            for k, v in rhnFlags.get('outputTransportOptions').items():
                setHeaderValue(self.req.headers_out, k, v)
            return retcode
        # Otherwise we're pretty much fine with the standard response
        # handler

        # Copy the fields from the transport options, if necessary
        for k, v in rhnFlags.get('outputTransportOptions').items():
            setHeaderValue(self.req.headers_out, k, v)
        # and jump into the base handler
        return apacheRequest.response(self, response)
Пример #56
0
def runTransaction(server_id, action_id, data={}):
    log_debug(3, action_id)

    # If it's a kickstart-related transaction, mark the kickstart session as
    # completed
    action_status = rhnFlags.get('action_status')
    ks_session_id = _next_kickstart_step(server_id, action_id, action_status)

    # Cleanup package profile
    server_kickstart.cleanup_profile(server_id, action_id, ks_session_id,
        action_status)

    _mark_dep_failures(server_id, action_id, data)
Пример #57
0
def diff(server_id, action_id, data={}):
    log_debug(3)
    if not data:
        # Nothing to do here
        return
    status = rhnFlags.get('action_status')
    if status == 2:
        # Completed
        _reset_diff_errors(server_id, action_id)
        missing_files = data.get('missing_files') or []
        _mark_missing_diff_files(server_id, action_id, missing_files)
        diffs = data.get('diffs') or {}
        _process_diffs(server_id, action_id, diffs)
Пример #58
0
 def _set_proxy_info(self, req):
     """ Spacewalk Proxy stuff. """
     proxyVersion = 'X-RHN-Proxy-Version'
     if proxyVersion in req.headers_in:
         self.proxyVersion = req.headers_in[proxyVersion]
     # Make sure the proxy version gets set in the headers.
     rhnFlags.get('outputTransportOptions')[proxyVersion] = str(
         self.proxyVersion)
     # Make sure the proxy auth-token gets set in global flags.
     if 'X-RHN-Proxy-Auth' in req.headers_in:
         rhnFlags.set('X-RHN-Proxy-Auth',
                      req.headers_in['X-RHN-Proxy-Auth'])
     return apache.OK