Пример #1
0
def validate_new_password(password):
    """ Perform all the checks required for new passwords """
    log_debug(3, "Entered validate_new_password")
    #
    # We're copying the code because we don't want to
    # invalidate any of the existing passwords.
    #

    # Validate password based on configurable length
    # regular expression
    if not password:
        raise rhnFault(12)
    if len(password) < CFG.MIN_PASSWD_LEN:
        raise rhnFault(14, _("password must be at least %d characters")
                       % CFG.MIN_PASSWD_LEN)
    if len(password) > CFG.MAX_PASSWD_LEN:
        raise rhnFault(701, _("Password must be shorter than %d characters")
                       % CFG.MAX_PASSWD_LEN)

    password = password[:CFG.MAX_PASSWD_LEN]
    invalid_re = re.compile(
        r"[^ A-Za-z0-9`!@#$%^&*()-_=+[{\]}\\|;:'\",<.>/?~]")
    asterisks_re = re.compile(r"^\**$")

    # make sure the password isn't all *'s
    tmp = asterisks_re.match(password)
    if tmp is not None:
        raise rhnFault(15, "password cannot be all asterisks '*'")

    # make sure we have only printable characters
    tmp = invalid_re.search(password)
    if tmp is not None:
        pos = tmp.regs[0]
        raise rhnFault(15,
                       _("password contains character `%s'") % password[pos[1] - 1])
Пример #2
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())
Пример #3
0
def get_package_path(server_id, pkg_spec, channel):
    log_debug(3, server_id, pkg_spec, channel)
    if isinstance(pkg_spec, ListType):
        pkg = pkg_spec[:4]
        #Insert EPOCH
        pkg.insert(1, None)
    else:
        pkg = parseRPMFilename(pkg_spec)
        if pkg is None:
            log_debug(4, "Error", "Requested weird package", pkg_spec)
            raise rhnFault(17, _("Invalid RPM package %s requested") % pkg_spec)

    statement = """
        select  p.id, p.path path, pe.epoch epoch
        from
                rhnPackageArch pa,
                rhnChannelPackage cp,
                rhnPackage p,
                rhnPackageEVR pe,
                rhnServerChannel sc,
                rhnPackageName pn,
                rhnChannel c
        where 1=1
            and c.label = :channel
            and pn.name = :name
            and sc.server_id = :server_id
            and pe.version = :ver
            and pe.release = :rel
            and c.id = sc.channel_id
            and c.id = cp.channel_id
            and pa.label = :arch
            and pn.id = p.name_id
            and p.id = cp.package_id
            and p.evr_id = pe.id
            and sc.channel_id = cp.channel_id
            and p.package_arch_id = pa.id
    """
    h = rhnSQL.prepare(statement)
    pkg = map(str, pkg)
    h.execute(name = pkg[0], ver = pkg[2], rel = pkg[3], arch = pkg[4],
              channel = channel, server_id = server_id)
    rs = h.fetchall_dict()
    if not rs:
        log_debug(4, "Error", "Non-existant package requested", server_id,
            pkg_spec, channel)
        raise rhnFault(17, _("Invalid RPM package %s requested") % pkg_spec)
    # It is unlikely for this query to return more than one row,
    # but it is possible
    # (having two packages with the same n, v, r, a and different epoch in
    # the same channel is prohibited by the RPM naming scheme; but extra
    # care won't hurt)
    max_row = rs[0]
    for each in rs[1:]:
        # Compare the epoch as string
        if _none2emptyString(each['epoch']) > _none2emptyString(max_row['epoch']):
            max_row = each

    # Set the flag for the proxy download accelerator
    rhnFlags.set("Download-Accelerator-Path", max_row['path'])
    return check_package_file(max_row['path'], max_row['id'], pkg_spec), max_row['id']
Пример #4
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
Пример #5
0
    def authzOrg(self, info):
        # This function is a lot more complicated than it should be; the
        # corner case is pushes without a channel; we have to deny regular
        # users the ability to push to their org.

        # If the org id is not specified, default to the user's org id
        if not info.has_key("orgId"):
            info["orgId"] = self.org_id
        log_debug(4, "info[orgId]", info["orgId"], "org id", self.org_id)

        org_id = info["orgId"]

        if org_id == "":
            # Satellites are not allowwd to push in the null org
            raise rhnFault(4, _("You are not authorized to manage packages in the null org"))

        if org_id and self.org_id != org_id:
            # Not so fast...
            raise rhnFault(32, _("You are not allowed to manage packages in the %s org") % org_id)

        # Org admins and channel admins have full privileges; we could use
        # user_manages_channes, except for the case where there are no chanels

        if self.isOrgAdmin() or self.isChannelAdmin():
            log_debug(4, "Org authorized (org_admin or channel_admin)")
            return

        # regular user at this point... check if the user manages any channels
        if user_manages_channels(self.user_id):
            log_debug(4, "Org authorized (user manages a channel)")
            return

        # ok, you're a regular user who doesn't manage any channels.
        # take a hike.
        raise rhnFault(32, _("You are not allowed to perform administrative tasks"))
def prepRhnCert(options):
    """ minor prepping of the RHN cerficate
        writing to default storage location
    """

    # NOTE: default_db MUST be populated in /etc/rhn/rhn.conf before this
    #       function is run.
    #       validateSatCert() must have been run prior to this as well (it
    #       populates "/var/log/entitlementCert"
    if options.rhn_cert and options.rhn_cert != DEFAULT_RHN_CERT_LOCATION:
        try:
            cert = openGzippedFile(options.rhn_cert).read()
        except (IOError, OSError), e:
            msg = _('ERROR: "%s" (specified in commandline)\n' "could not be opened and read:\n%s") % (
                options.rhn_cert,
                str(e),
            )
            sys.stderr.write(msg + "\n")
            raise
        cert = string.strip(cert)
        try:
            writeRhnCert(options, cert)
        except (IOError, OSError), e:
            msg = _('ERROR: "%s" could not be opened\nand/or written to:\n%s') % (DEFAULT_RHN_CERT_LOCATION, str(e))
            sys.stderr.write(msg + "\n")
            raise
    def getSourcePackagePath(self, pkgFilename):
        """ OVERLOADS getSourcePackagePath in common/rhnRepository.
            snag src.rpm and nosrc.rpm from local repo, after ensuring
            we are authorized to fetch it.
        """

        log_debug(3, pkgFilename)
        if pkgFilename[-8:] != '.src.rpm' and pkgFilename[-10:] != '.nosrc.rpm':
            raise rhnFault(17, _("Invalid SRPM package requested: %s")
                                 % pkgFilename)

        # Connect to the server to get an authorization for downloading this
        # package
        server = rpclib.Server(self.rhnParentXMLRPC, proxy=self.httpProxy,
                               username=self.httpProxyUsername,
                               password=self.httpProxyPassword)
        if self.caChain:
            server.add_trusted_cert(self.caChain)

        try:
            retval = server.proxy.package_source_in_channel(
                        pkgFilename, self.channelName, self.clientInfo)
        except xmlrpclib.Fault, e:
            raise rhnFault(1000,
                    _("Error retrieving source package: %s") % str(e)), None, sys.exc_info()[2]
Пример #8
0
def exitWithTraceback(e, msg, exitnum, mail=0):
    tbOut = StringIO()
    Traceback(mail, ostream=tbOut, with_locals=1)
    log_error(-1, _('ERROR: %s %s: %s') %
              (e.__class__.__name__, msg, e))
    log_error(-1, _('TRACEBACK: %s') % tbOut.getvalue())
    sys.exit(exitnum)
Пример #9
0
def check_user_password(username, password):
    """ Do some minimal checks on the data thrown our way. """
    # username is required
    if not username:
        raise rhnFault(11)
    # password is required
    if not password:
        raise rhnFault(12)
    if len(username) < CFG.MIN_USER_LEN:
        raise rhnFault(13, _("username should be at least %d characters")
                       % CFG.MIN_USER_LEN)
    if len(username) > CFG.MAX_USER_LEN:
        raise rhnFault(700, _("username should be less than %d characters")
                       % CFG.MAX_USER_LEN)
    username = username[:CFG.MAX_USER_LEN]

    # Invalid characters
    # ***NOTE*** Must coordinate with web and installer folks about any
    # changes to this set of characters!!!!
    invalid_re = re.compile(".*[\s&+%'`\"=#]", re.I)
    tmp = invalid_re.match(username)
    if tmp is not None:
        pos = tmp.regs[0]
        raise rhnFault(15, _("username = `%s', invalid character `%s'") % (
            username, username[pos[1] - 1]))

    # use new password validation method
    validate_new_password(password)

    return username, password
Пример #10
0
    def auth_client(self, token):
        """ Authenticate a system based on the same authentication tokens
            the client is sending for GET requests
        """
        log_debug(3)
        # Build a UserDictCase out of the token
        dict = UserDictCase(token)
        # Set rhnFlags so that we can piggyback on apacheAuth's auth_client
        rhnFlags.set('AUTH_SESSION_TOKEN', dict)

        # XXX To clean up apacheAuth.auth_client's logging, this is not about
        # GET requests
        result = apacheAuth.auth_client()

        if not result:
            raise rhnFault(33, _("Invalid session key"))

        log_debug(4, "Client auth OK")
        # We checked it already, so we're sure it's there
        client_id = dict['X-RHN-Server-Id']

        server = rhnServer.search(client_id)
        if not server:
            raise rhnFault(8, _("This server ID no longer exists"))
        # XXX: should we check if the username still has access to it?
        # probably not, because there is no known good way we can
        # update the server system_id on the client side when
        # permissions change... Damn it. --gafton
        self.server = server
        self.server_id = client_id
        self.user = dict['X-RHN-Auth-User-Id']
        return server
Пример #11
0
 def validate_system_input(self, data):
     """ check the input data """
     if not hash_validate(data, "os_release", "architecture", "profile_name"):
         log_error("Incomplete data hash")
         raise rhnFault(21, _("Required data missing"))
     # we require either a username and a password or a token
     if not hash_validate(data, "username", "password") and \
        not hash_validate(data, "token"):
         raise rhnFault(21, _("Required members missing"))
Пример #12
0
def __new_user_db(username, password, email, org_id, org_password):
    encrypted_password = CFG.encrypted_passwords
    log_debug(3, username, email, encrypted_password)

    # now search it in the database
    h = rhnSQL.prepare("""
    select w.id, w.password, ui.use_pam_authentication
    from web_contact w, rhnUserInfo ui
    where w.login_uc = upper(:username)
    and w.id = ui.user_id
    """)
    h.execute(username=username)
    data = h.fetchone_dict()

    pre_existing_user = 0

    if not data:
        # the username is not there, check the reserved user table
        h = rhnSQL.prepare("""
        select login, password from rhnUserReserved
        where login_uc = upper(:username)
        """)
        h.execute(username=username)
        data = h.fetchone_dict()
        if not data:  # nope, not reserved either
            raise rhnFault(1, _("Username `%s' has not been reserved") % username)
    else:
        pre_existing_user = 1

    if not pre_existing_user and not email:
        # New accounts have to specify an e-mail address
        raise rhnFault(30, _("E-mail address not specified"))

    # we have to perform PAM authentication if data has a field called
    # 'use_pam_authentication' and its value is 'Y', and we do have a PAM
    # service set in the config file.
    # Note that if the user is only reserved we don't do PAM authentication
    if data.get('use_pam_authentication') == 'Y' and CFG.pam_auth_service:
        # Check the password with PAM
        import rhnAuthPAM
        if rhnAuthPAM.check_password(username, password, CFG.pam_auth_service) <= 0:
            # Bad password
            raise rhnFault(2)
        # We don't care about the password anymore, replace it with something
        import time
        password = '******' % time.time()
    else:
        # Regular authentication
        if check_password(password, data["password"]) == 0:
            # Bad password
            raise rhnFault(2)

    # creation of user was never supported in spacewalk but this call was mis-used
    # to check username/password in the past
    # so let's skip other checks and return now
    return 0
Пример #13
0
    def auth_system(self):
        if CFG.DISABLE_ISS:
            raise rhnFault(2005, _('ISS is disabled on this satellite.'))

        if not rhnSQL.fetchone_dict("select 1 from rhnISSSlave where slave = :hostname and enabled = 'Y'",
                                    hostname=idn_puny_to_unicode(self.remote_hostname)):
            raise rhnFault(2004,
                           _('Server "%s" is not enabled for ISS.')
                           % self.remote_hostname)
        return self.remote_hostname
Пример #14
0
def auth_username_password(username, password):
    user = search(username)

    if not user:
        raise rhnFault(2, _("Invalid username/password combination"))

    if not user.check_password(password):
        raise rhnFault(2, _("Invalid username/password combination"))

    return user
Пример #15
0
def check_package_file(rel_path, logpkg, raisepkg):
    if rel_path is None:
        log_error("Package path null for package id", logpkg)
        raise rhnFault(17, _("Invalid RPM package %s requested") % raisepkg)
    filePath = "%s/%s" % (CFG.MOUNT_POINT, rel_path)
    if not os.access(filePath, os.R_OK):
        # Package not found on the filesystem
        log_error("Package not found", filePath)
        raise rhnFault(17, _("Package not found"))

    return filePath
Пример #16
0
def auth_username_password(username, password):
    # hrm.  it'd be nice to move importlib.userAuth stuff here
    user = search(username)

    if not user:
        raise rhnFault(2, _("Invalid username/password combination"))

    if not user.check_password(password):
        raise rhnFault(2, _("Invalid username/password combination"))

    return user
Пример #17
0
    def header(self, system_id, pkgList):
        """ Clients v1-

            IN:  system_id: ....
                  a package identifier (or a list of them)
                    [n,v,r,e] or
                    [[n,v,r,e],...]
            OUT: If Proxy:
                If Client:
        """
        log_debug(5, system_id, pkgList)
        if type(pkgList) not in (ListType, TupleType) or not len(pkgList):
            log_error("Invalid package list spec", type(pkgList),
                      "len = %d" % len(pkgList))
            raise rhnFault(30, _("Invalid value %s (type %s)") % (
                pkgList, type(pkgList)))
        # Okay, it's a list; is it a list of lists?
        if type(pkgList[0]) is StringType:
            # Wrap it in a list
            pkgList = [pkgList]
        # Now check all params
        req_list = []
        for p in pkgList:
            req_list.append(check_package_spec(p))
        # Authenticate the system certificate
        server = self.auth_system('header', system_id)
        # log the entry
        log_debug(1, self.server_id, "items: %d" % len(req_list))

        rpmHeaders = []
        for pkg in pkgList:
            # Authorize this package fetch.
            # XXX: a bit heavy-handed I think... but old client stuff.
            #      NOTE: pkg for old client is [n,v,r,e]
            path = rhnPackage.get_package_path_compat_arches(
                self.server_id, pkg, server.archname)

            # read the header from the file on disk
            h = rhn_rpm.get_package_header(filename=path)
            if h is None:
                log_error("Unable to read package header", pkg)
                raise rhnFault(17,
                        _("Unable to retrieve package header %s") % str(pkg))
            rpmHeaders.append(rpclib.xmlrpclib.Binary(h.unload()))
            del h

        # Reset the flag for the proxy download accelerator
        # This gets set by default in rhnPackage
        rhnFlags.set("Download-Accelerator-Path", None)
        if CFG.COMPRESS_HEADERS:
            # Compress
            rhnFlags.set("compress_response", 1)
        return rpmHeaders
Пример #18
0
    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 = rpclib.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:
            # now get the function reference and call it
            func = self.method_ref(method)
            if len(params):
                response = apply(func, params)
            else:
                response = func()
        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 = rpclib.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")
            
        #pkilambi:catch exception if redirect
        except redirectException, re:
            log_debug(3,"redirect exception caught",re.path)
            response = re.path
Пример #19
0
def validate_new_username(username):
    """ Perform all the checks required for new usernames. """
    log_debug(3)
    if len(username) < CFG.MIN_NEW_USER_LEN:
        raise rhnFault(13, _("username should be at least %d characters long") % CFG.MIN_NEW_USER_LEN)

    disallowed_suffixes = CFG.DISALLOWED_SUFFIXES or []
    if not isinstance(disallowed_suffixes, type([])):
        disallowed_suffixes = [disallowed_suffixes]

    log_debug(4, "Disallowed suffixes", disallowed_suffixes)

    for suffix in disallowed_suffixes:
        if username[-len(suffix) :].upper() == suffix.upper():
            raise rhnFault(106, _("Cannot register usernames ending with %s") % suffix)
Пример #20
0
 def auth_system(self, system_id):
     """ System authentication. We override the standard function because
         we need to check additionally if this system_id is entitled for
         proxy functionality.
     """
     log_debug(3)
     server = rhnHandler.auth_system(self, system_id)
     # if it did not blow up, we have a valid server. Check proxy
     # entitlement.
     # XXX: this needs to be moved out of the rhnServer module,
     # possibly in here
     h = rhnSQL.prepare("""
     select 1
     from rhnProxyInfo pi
     where pi.server_id = :server_id
     """)
     h.execute(server_id = self.server_id)
     row = h.fetchone_dict()
     if not row:
         # we require entitlement for this functionality
         log_error("Server not entitled for Proxy", self.server_id)
         raise rhnFault(1002, _(
             'Spacewalk Proxy service not enabled for server profile: "%s"')
                        % server.server["name"])
     # we're fine...
     return server
Пример #21
0
    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,
              _("RHN Proxy could not successfully connect its RHN parent. "
                "Please contact your system administrator."))
Пример #22
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)
Пример #23
0
    def authzChannels(self, channels):
        log_debug(4, channels)
        if not channels:
            return

        # rhn_channel.user_role_check checks for the ownership of the channel
        # by this user's org

        h = rhnSQL.prepare("""
            select rhn_channel.user_role_check(id, :user_id, 'manage') manage
              from rhnChannel
             where label = :channel
        """)

        for channel in channels:
            h.execute(channel=channel, user_id=self.user_id)

            row = h.fetchone_dict()
            # Either the channel doesn't exist, or not allowed to manage it
            if not row or not row['manage']:
                raise rhnFault(32,
                               _("You are not allowed to manage channel %s, or that "
                                 "channel does not exist") % channel)

            log_debug(4, "User %s allowed to manage channel %s" %
                      (self.user_id, channel))

        return None
Пример #24
0
    def get_package_path_by_filename(self, fileName, channel):
        log_debug(3, fileName, channel)
        fileName = str(fileName)
        n, e, v, r, a = rhnLib.parseRPMFilename(fileName)

        h = rhnSQL.prepare(self._query_get_package_path_by_nvra)
        h.execute(name=n, version=v, release=r, epoch=e, arch=a, channel=channel)
        try:
            return _get_path_from_cursor(h)
        except InvalidPackageError:
            log_debug(4, "Error", "Non-existent package requested", fileName)
            raise rhnFault(17, _("Invalid RPM package %s requested") % fileName), None, sys.exc_info()[2]
        except NullPathPackageError, e:
            package_id = e[0]
            log_error("Package path null for package id", package_id)
            raise rhnFault(17, _("Invalid RPM package %s requested") % fileName), None, sys.exc_info()[2]
Пример #25
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
Пример #26
0
    def getPackagePath(self, pkgFilename):
        """ OVERLOADS getPackagePath in common/rhnRepository.
            Returns complete path to an RPM file.
        """

        log_debug(3, pkgFilename)
        mappingName = "package_mapping:%s:" % self.channelName
        pickledMapping = self._cacheObj(mappingName, self.channelVersion, self.__channelPackageMapping, ())

        mapping = cPickle.loads(pickledMapping)

        # If the file name has parameters, it's a different kind of package.
        # Determine the architecture requested so we can construct an
        # appropriate filename.
        if type(pkgFilename) == types.ListType:
            arch = pkgFilename[3]
            if isSolarisArch(arch):
                pkgFilename = "%s-%s-%s.%s.pkg" % (pkgFilename[0], pkgFilename[1], pkgFilename[2], pkgFilename[3])

        if not mapping.has_key(pkgFilename):
            log_error("Package not in mapping: %s" % pkgFilename)
            raise rhnFault(17, _("Invalid RPM package requested: %s") % pkgFilename)
        filePath = "%s/%s" % (CFG.PKG_DIR, mapping[pkgFilename])
        log_debug(4, "File path", filePath)
        if not os.access(filePath, os.R_OK):
            log_debug(4, "Package not found locally: %s" % pkgFilename)
            raise NotLocalError(filePath, pkgFilename)
        return filePath
Пример #27
0
    def entitle(self, server_id, history, virt_type=None):
        """
        Entitle a server according to the entitlements we have configured.
        """
        log_debug(3, self.entitlements)

        entitle_server = rhnSQL.Procedure("rhn_entitlements.entitle_server")
        # TODO: entitle_server calls can_entitle_server, so we're doing this
        # twice for each successful call. Is it necessary for external error
        # handling or can we ditch it?
        can_entitle_server = rhnSQL.Function(
            "rhn_entitlements.can_entitle_server", rhnSQL.types.NUMBER())

        can_ent = None

        history["entitlement"] = ""

        # Do a quick check to see if both virt entitlements are present. (i.e.
        # activation keys stacked together) If so, give preference to the more
        # powerful virtualization platform and remove the regular virt
        # entitlement from the list.
        found_virt = False
        found_virt_platform = False
        for entitlement in self.entitlements:
            if entitlement[0] == VIRT_ENT_LABEL:
                found_virt = True
            elif entitlement[0] == VIRT_PLATFORM_ENT_LABEL:
                found_virt_platform = True

        for entitlement in self.entitlements:
            if virt_type is not None and entitlement[0] in \
                    (VIRT_ENT_LABEL, VIRT_PLATFORM_ENT_LABEL):
                continue

            # If both virt entitlements are present, skip the least powerful:
            if found_virt and found_virt_platform and entitlement[0] == VIRT_ENT_LABEL:
                log_debug(1, "Virtualization and Virtualization Platform " +
                          "entitlements both present.")
                log_debug(1, "Skipping Virtualization.")
                continue

            try:
                can_ent = can_entitle_server(server_id, entitlement[0])
            except rhnSQL.SQLSchemaError, e:
                can_ent = 0

            try:
                # bugzilla #160077, skip attempting to entitle if we cant
                if can_ent:
                    entitle_server(server_id, entitlement[0])
            except rhnSQL.SQLSchemaError, e:
                log_error("Token failed to entitle server", server_id,
                          self.get_names(), entitlement[0], e.errmsg)
                if e.errno == 20220:
                    # ORA-20220: (servergroup_max_members) - Server group membership
                    # cannot exceed maximum membership
                    raise rhnFault(91,
                                   _("Registration failed: RHN Software service entitlements exhausted: %s") % entitlement[0]), None, sys.exc_info()[2]
                # No idea what error may be here...
                raise rhnFault(90, e.errmsg), None, sys.exc_info()[2]
Пример #28
0
def token_server_groups(server_id, tokens_obj):
    """ Handle server group subscriptions for the registration token """
    assert(isinstance(tokens_obj, ActivationTokens))
    h = rhnSQL.prepare(_query_token_server_groups)
    server_groups = {}
    for token in tokens_obj.tokens:
        token_id = token['token_id']
        h.execute(token_id=token_id)
        while 1:
            row = h.fetchone_dict()
            if not row:
                break
            server_group_id = row['server_group_id']
            server_groups[server_group_id] = row

    # Now try to subscribe server to group
    ret = []
    for server_group_id, sg in server_groups.items():
        log_debug(4, "token server group", sg)

        try:
            join_server_group(server_id, server_group_id)
        except rhnSQL.SQLError, e:
            log_error("Failed to add server to group", server_id,
                      server_group_id, sg["name"])
            raise rhnFault(80, _("Failed to add server to group %s") %
                           sg["name"]), None, sys.exc_info()[2]
        else:
            ret.append("Subscribed to server group '%s'" % sg["name"])
Пример #29
0
    def __getXmlrpcServer():
        """ get an xmlrpc server object

            WARNING: if CFG.USE_SSL is off, we are sending info
                     in the clear.
        """
        log_debug(3)

        # build the URL
        url = CFG.RHN_PARENT or ''
        url = parseUrl(url)[1].split(':')[0]
        if CFG.USE_SSL:
            url = 'https://' + url + '/XMLRPC'
        else:
            url = 'http://' + url + '/XMLRPC'
        log_debug(3, 'server url: %s' % url)

        if CFG.HTTP_PROXY:
            serverObj = rpclib.Server(url,
                                      proxy=CFG.HTTP_PROXY,
                                      username=CFG.HTTP_PROXY_USERNAME,
                                      password=CFG.HTTP_PROXY_PASSWORD)
        else:
            serverObj = rpclib.Server(url)
        if CFG.USE_SSL and CFG.CA_CHAIN:
            if not os.access(CFG.CA_CHAIN, os.R_OK):
                log_error('ERROR: missing or cannot access (for ca_chain): %s' % CFG.CA_CHAIN)
                raise rhnFault(1000,
                               _("Spacewalk Proxy error (file access issues). "
                                 "Please contact your system administrator. "
                                 "Please refer to Spacewalk Proxy logs."))
            serverObj.add_trusted_cert(CFG.CA_CHAIN)
        serverObj.add_header('X-RHN-Client-Version', 2)
        return serverObj
Пример #30
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)
Пример #31
0
    def set_arch(self, arch):
        self.archname = arch
        # try to detect the archid
        if arch is None:
            return

        arch = rhnLib.normalize_server_arch(arch)
        h = rhnSQL.prepare(self._query_lookup_arch)
        h.execute(archname=arch)
        data = h.fetchone_dict()
        if not data:
            # Log it to disk, it may show interesting things
            log_error("Attempt to create server with invalid arch `%s'" % arch)
            raise rhnFault(24, _("Architecture `%s' is not supported") % arch)
        self.server["server_arch_id"] = data["id"]
        self.is_rpm_managed = data['is_rpm_managed']
Пример #32
0
def check_email(email):
    """ Do some minimal checks on the e-mail address """
    if email is not None:
        email = email.strip()

    if not email:
        # Still supported
        return None

    if len(email) > CFG.MAX_EMAIL_LEN:
        raise rhnFault(
            100,
            _("Please limit your e-mail address to %s chars") %
            CFG.MAX_EMAIL_LEN)
    # XXX More to come (check the format is indeed [email protected]
    return email
Пример #33
0
    def has_base_channel(self, uuid):
        log_debug(1, uuid)
        # Verifies if a system has a base channel
        h = rhnSQL.prepare(self._query_lookup_server)
        h.execute(uuid=uuid)
        row = h.fetchone_dict()
        if not row:
            raise rhnFault(140,
                           _("Your system was not found in the RHN database"),
                           explain=0)
        server_id = row['id']

        h = rhnSQL.prepare(self._query_lookup_base_channel)
        h.execute(server_id=server_id)
        row = h.fetchone_dict()
        if row:
            return 1
        return 0
Пример #34
0
def _validate_entitlements(token_string, rereg_ents, base_entitlements,
                           extra_entitlements, remove_entitlements):
    """
    Perform various checks on the final list of entitlements accumulated after
    processing all activation keys.

    rereg_ents passed in as a list of entitlement labels.

    Extra/base entitlements passed in as a hash of tuples ('label', 'Friendly
    Name') mapping to None. (i.e. seems to be used as just a set)

    Remove entitlements being maintained as just a list of labels.
    """
    # Check for exactly one base entitlement:
    if len(base_entitlements.keys()) != 1:
        log_error("Tokens with different base entitlements", token_string,
                  base_entitlements)
        raise rhnFault(
            63,
            _("Stacking of re-registration tokens with different base entitlements "
              "is not supported"),
            explain=0)

    # Don't allow an activation key to give virt entitlement to a system
    # that's re-activating and already has virt platform: (or vice-versa)
    found_virt = False
    virt_tuple = None
    found_virt_platform = False
    for ent_tuple in extra_entitlements.keys():
        if ent_tuple[0] == VIRT_ENT_LABEL:
            found_virt = True
            virt_tuple = ent_tuple
        elif ent_tuple[0] == VIRT_PLATFORM_ENT_LABEL:
            found_virt_platform = True

    if found_virt and found_virt_platform and len(rereg_ents) > 0:
        # Both virt entitlements found, give preference to the most powerful.
        # (i.e. virtualization_host_platform) This may mean we have to remove
        # virtualization_host if a reregistration key is in use and contains
        # this entitlement.
        if VIRT_ENT_LABEL in rereg_ents:
            # The system already has virt host, so it must be removed:
            log_debug(1, "Removing Virtualization entitlement from profile.")
            remove_entitlements.append(virt_tuple[0])
Пример #35
0
    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]
Пример #36
0
    def headerParserHandler(self, req):
        # pylint: disable=W0201
        log_setreq(req)
        self.start_time = time.time()
        # init configuration options with proper component
        options = req.get_options()
        # if we are initializing out of a <Location> handler don't
        # freak out
        if "RHNComponentType" not in options:
            # clearly nothing to do
            return apache.OK
        initCFG(options["RHNComponentType"])
        initLOG(CFG.LOG_FILE, CFG.DEBUG)
        # short-circuit everything if sending a system-wide message.
        if CFG.SEND_MESSAGE_TO_ALL:
            # Drop the database connection
            # pylint: disable=W0702
            try:
                rhnSQL.closeDB()
            except:
                pass

            # 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)
            return self._send_xmlrpc(
                req,
                rhnFault(-1,
                         _("IMPORTANT MESSAGE FOLLOWS:\n%s") % msg,
                         explain=0))

        rhnSQL.initDB()
        self.server = options['SERVER']

        self.server_classes = rhnImport.load("satellite_exporter/handlers")

        if self.server not in self.server_classes:
            # XXX do something interesting here
            log_error("Missing server", self.server)
            return apache.HTTP_NOT_FOUND

        return self._wrapper(req, self._headerParserHandler)
Пример #37
0
def _check_token_limits(server_id, token_rec):
    token_id = token_rec["token_id"]

    # Mark that we used this token
    server_used_token(server_id, token_id)

    # now check we're not using this token too much
    h = rhnSQL.prepare(_query_check_token_limits)
    h.execute(token_id=token_id)
    ret = h.fetchone_dict()
    if not ret:
        raise rhnException("Could not check usage limits for token",
                           server_id, token_rec)
    # See bug #79095: if usage_limit is NULL, it means unlimited reg tokens
    if ret["max_nr"] is not None and ret["max_nr"] < ret["curr_nr"]:
        log_error("Token usage limit exceeded", token_rec,
                  ret["max_nr"], server_id)
        raise rhnFault(61, _("Maximum usage count of %s reached") % ret["max_nr"])
    # all clean, we're below usage limits
    return 0
Пример #38
0
def _validate_entitlements(token_string, rereg_ents, base_entitlements,
                           extra_entitlements, remove_entitlements):
    """
    Perform various checks on the final list of entitlements accumulated after
    processing all activation keys.

    rereg_ents passed in as a list of entitlement labels.

    Extra/base entitlements passed in as a hash of tuples ('label', 'Friendly
    Name') mapping to None. (i.e. seems to be used as just a set)

    Remove entitlements being maintained as just a list of labels.
    """
    # Check for exactly one base entitlement:
    if len(list(base_entitlements.keys())) != 1:
        log_error("Tokens with different base entitlements", token_string,
                  base_entitlements)
        raise rhnFault(63,
                       _("Stacking of re-registration tokens with different base entitlements "
                         "is not supported"), explain=0)
Пример #39
0
    def getPackagePath(self, pkgFilename, redirect=0):
        """ OVERLOADS getPackagePath in common/rhnRepository.
            Returns complete path to an RPM file.
        """

        log_debug(3, pkgFilename)
        mappingName = "package_mapping:%s:" % self.channelName
        pickledMapping = self._cacheObj(mappingName, self.channelVersion,
                                        self.__channelPackageMapping, ())

        mapping = cPickle.loads(pickledMapping)

        # If the file name has parameters, it's a different kind of package.
        # Determine the architecture requested so we can construct an
        # appropriate filename.
        if type(pkgFilename) == types.ListType:
            arch = pkgFilename[3]
            if isSolarisArch(arch):
                pkgFilename = "%s-%s-%s.%s.pkg" % \
                    (pkgFilename[0],
                     pkgFilename[1],
                     pkgFilename[2],
                     pkgFilename[3])

        if not mapping.has_key(pkgFilename):
            log_error("Package not in mapping: %s" % pkgFilename)
            raise rhnFault(
                17,
                _("Invalid RPM package requested: %s") % pkgFilename)
        # A list of possible file paths. Always a list, channel mappings are
        # cleared on package upgrade so we don't have to worry about the old
        # behavior of returning a string
        filePaths = mapping[pkgFilename]
        # Can we see a file at any of the possible filepaths?
        for filePath in filePaths:
            filePath = "%s/%s" % (CFG.PKG_DIR, filePath)
            log_debug(4, "File path", filePath)
            if os.access(filePath, os.R_OK):
                return filePath
        log_debug(4, "Package not found locally: %s" % pkgFilename)
        raise NotLocalError(filePaths[0], pkgFilename)
Пример #40
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, e:
            log_error("Error opening connection", self.rhnParent, e)
            Traceback(mail=0)
            raise rhnFault(
                1000,
                _("SUSE Manager Proxy could not successfully connect its SUSE Manager parent. "
                  "Please contact your system administrator.")
            ), None, sys.exc_info()[2]
Пример #41
0
 def __solveDep_prepare(self, system_id, deps, action, clientVersion):
     """ Response for clients:
             version 1: list
             version 2: hash
     """
     log_debug(7, system_id, deps, action, clientVersion)
     faultString = _("Invalid value %s (%s)")
     if type(deps) not in (ListType, TupleType):
         log_error("Invalid argument type", type(deps))
         raise rhnFault(30, faultString % (deps, type(deps)))
     for dep in deps:
         if type(dep) is not StringType:
             log_error("Invalid dependency member", type(dep))
             raise rhnFault(30, faultString % (dep, type(dep)))
     # Ignore empty strings
     deps = list(filter(len, deps))
     # anything left to do?
     if not deps:
         return []
     # Authenticate the system certificate
     server = self.auth_system(action, system_id)
     log_debug(1, self.server_id, action, "items: %d" % len(deps))
     return deps
Пример #42
0
def getUserGroups(login, password):
    # Authenticates a user and returns the list of groups it belongs
    # to, and the org id
    add_to_seclist(password)
    log_debug(4, login)
    user = rhnUser.search(login)

    if not user:
        log_debug("rhnUser.search failed")
        raise rhnFault(2)

    # Check the user's password
    if not user.check_password(password):
        log_debug("user.check_password failed")
        raise rhnFault(2)

    if rhnUser.is_user_disabled(username):
        msg = _("""
               %s Account has been deactivated on this server.
               Please contact your Org administrator for more help.""")
        raise rhnFault(1, msg % username, explain=0)

    return getUserGroupsFromUserInstance(user)
Пример #43
0
    def register_product(self, system_id, product, oeminfo = {}):
        """ register a product and record the data sent with the registration

            bretm:  hasn't registered a product or recorded anything since 2001, near
              as I can tell what it actually appears to be responsible for is
              protecting us against people registering systems from t7/t9
              countries

              actual use of registration numbers has been moved into the
              server_class.__save stuff
        """

        log_debug(5, system_id, product, oeminfo)
        if type(product) != type({}):
            log_error("Invalid argument type", type(product))
            raise rhnFault(21, _(
                "Expected a dictionary as a product argument"))
        log_debug(4, product)
        # As per bug 129996 using an activation key should not overwrite the
        # user's info. Also, the reg number stuff doesn't work anyway
        # Keep doing the authentication and then just bail out
        self.auth_system(system_id)
        return 0
Пример #44
0
    def __getXmlrpcServer():
        """ get an xmlrpc server object

            WARNING: if CFG.USE_SSL is off, we are sending info
                     in the clear.
        """
        log_debug(3)

        # build the URL
        url = CFG.RHN_PARENT or ''
        url = parseUrl(url)[1].split(':')[0]
        if CFG.USE_SSL:
            url = 'https://' + url + '/XMLRPC'
        else:
            url = 'http://' + url + '/XMLRPC'
        log_debug(3, 'server url: %s' % url)

        if CFG.HTTP_PROXY:
            serverObj = rpclib.Server(url,
                                      proxy=CFG.HTTP_PROXY,
                                      username=CFG.HTTP_PROXY_USERNAME,
                                      password=CFG.HTTP_PROXY_PASSWORD)
        else:
            serverObj = rpclib.Server(url)
        if CFG.USE_SSL and CFG.CA_CHAIN:
            if not os.access(CFG.CA_CHAIN, os.R_OK):
                log_error(
                    'ERROR: missing or cannot access (for ca_chain): %s' %
                    CFG.CA_CHAIN)
                raise rhnFault(
                    1000,
                    _("SUSE Manager Proxy error (file access issues). "
                      "Please contact your system administrator. "
                      "Please refer to SUSE Manager Proxy logs."))
            serverObj.add_trusted_cert(CFG.CA_CHAIN)
        serverObj.add_header('X-RHN-Client-Version', 2)
        return serverObj
Пример #45
0
    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
Пример #46
0
    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 as 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_with_tb(
                rhnFault(
                    1000,
                    _("Spacewalk Proxy error (issues connecting to auth cache). "
                      "Please contact your system administrator")),
                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_with_tb(
                rhnFault(
                    1000,
                    _("Spacewalk Proxy error (issues connecting to auth cache). "
                      "Please contact your system administrator")),
                sys.exc_info()[2])

        wfile.close()

        rfile = sock.makefile("r")
        try:
            params, methodname = recv(rfile)
        except CommunicationError as 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_with_tb(
                rhnFault(
                    1000,
                    _("Spacewalk Proxy error (issues communicating to auth cache). "
                      "Please contact your system administrator")),
                sys.exc_info()[2])
        except Fault as e:
            rfile.close()
            sock.close()
            # If e.faultCode is 0, it's another exception
            if e.faultCode != 0:
                # Treat is as a regular xmlrpc fault
                raise

            _dict = e.faultString
            if not isinstance(_dict, type({})):
                # Not the expected type
                raise

            if 'name' not in _dict:
                # Doesn't look like a marshalled exception
                raise

            name = _dict['name']
            args = _dict.get('args')
            # Look up the exception
            if not hasattr(__builtins__, name):
                # Unknown exception name
                raise

            # Instantiate the exception object
            import new
            _dict = {'args': args}
            # pylint: disable=bad-option-value,nonstandard-exception
            raise_with_tb(new.instance(getattr(__builtins__, name), _dict),
                          sys.exc_info()[2])

        return params[0]
Пример #47
0
    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 SUSE Manager Proxy auth token is a token fetched upon login from
            SUSE Manager Server 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 SUSE Manager 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 SUSE Manager 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 SUSE Manager Proxy login
            purposes. This a header used to track request routes through
            a hierarchy of SUSE Manager 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_error) as 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 as 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_error as e:  # pylint: disable=duplicate-except
                        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.SSLError as e:
                token = None
                error = ['rhn.SSL.SSL.SSLError', repr(e), str(e)]
                log_error(error)
                Traceback(mail=0)
                time.sleep(.25)
                continue
            except xmlrpclib.ProtocolError as e:
                token = None
                log_error('xmlrpclib.ProtocolError', e)
                time.sleep(.25)
                continue
            except xmlrpclib.Fault as e:
                # Report it through the mail
                # Traceback will try to walk over all the values
                # in each stack frame, and eventually will try to stringify
                # the method object itself
                # This should trick it, since the originator of the exception
                # is this function, instead of a deep call into xmlrpclib
                log_error("%s" % e)
                if e.faultCode == 10000:
                    # reraise it for the users (outage or "important message"
                    # coming through")
                    raise_with_tb(rhnFault(e.faultCode, e.faultString),
                                  sys.exc_info()[2])
                # ok... it's some other fault
                Traceback("ProxyAuth.login (Fault) - SUSE Manager Proxy not "
                          "able to log in.")
                # And raise a Proxy Error - the server made its point loud and
                # clear
                raise_with_tb(
                    rhnFault(
                        1000,
                        _("SUSE Manager Proxy error (during proxy login). "
                          "Please contact your system administrator.")),
                    sys.exc_info()[2])
            except Exception as e:  # pylint: disable=broad-except
                token = None
                log_error("Unhandled exception", e)
                Traceback(mail=0)
                time.sleep(.25)
                continue
            else:
                break

        if not token:
            if error:
                if error[0] in ('xmlrpclib.ProtocolError', 'socket.error',
                                'socket'):
                    raise rhnFault(
                        1000,
                        _("SUSE Manager Proxy error (error: %s). "
                          "Please contact your system administrator.") %
                        error[0])
                if error[0] in ('rhn.SSL.SSL.SSLError', 'socket.sslerror'):
                    raise rhnFault(
                        1000,
                        _("SUSE Manager Proxy error (SSL issues? Error: %s). "
                          "Please contact your system administrator.") %
                        error[0])
                raise rhnFault(1002, err_text='%s' % e)
            raise rhnFault(1001)
        if self.hostname:
            token = token + ':' + self.hostname
        log_debug(6, "New proxy token: %s" % token)
        return token
Пример #48
0
class Repository(rhnRepository.Repository):
    # pylint: disable=R0902
    """ Proxy local package repository lookup and manipulation code. """
    def __init__(self,
                 channelName,
                 channelVersion,
                 clientInfo,
                 rhnParent=None,
                 rhnParentXMLRPC=None,
                 httpProxy=None,
                 httpProxyUsername=None,
                 httpProxyPassword=None,
                 caChain=None):

        log_debug(3, channelName)
        rhnRepository.Repository.__init__(self, channelName)
        self.functions = CFG.PROXY_LOCAL_FLIST
        self.channelName = channelName
        self.channelVersion = channelVersion
        self.clientInfo = clientInfo
        self.rhnParent = rhnParent
        self.rhnParentXMLRPC = rhnParentXMLRPC
        self.httpProxy = httpProxy
        self.httpProxyUsername = httpProxyUsername
        self.httpProxyPassword = httpProxyPassword
        self.caChain = caChain

    def getPackagePath(self, pkgFilename, redirect=0):
        """ OVERLOADS getPackagePath in common/rhnRepository.
            Returns complete path to an RPM file.
        """

        log_debug(3, pkgFilename)
        mappingName = "package_mapping:%s:" % self.channelName
        pickledMapping = self._cacheObj(mappingName, self.channelVersion,
                                        self.__channelPackageMapping, ())

        mapping = cPickle.loads(pickledMapping)

        # If the file name has parameters, it's a different kind of package.
        # Determine the architecture requested so we can construct an
        # appropriate filename.
        if type(pkgFilename) == types.ListType:
            arch = pkgFilename[3]
            if isSolarisArch(arch):
                pkgFilename = "%s-%s-%s.%s.pkg" % \
                    (pkgFilename[0],
                     pkgFilename[1],
                     pkgFilename[2],
                     pkgFilename[3])

        if not mapping.has_key(pkgFilename):
            log_error("Package not in mapping: %s" % pkgFilename)
            raise rhnFault(
                17,
                _("Invalid RPM package requested: %s") % pkgFilename)
        # A list of possible file paths. Always a list, channel mappings are
        # cleared on package upgrade so we don't have to worry about the old
        # behavior of returning a string
        filePaths = mapping[pkgFilename]
        # Can we see a file at any of the possible filepaths?
        for filePath in filePaths:
            filePath = "%s/%s" % (CFG.PKG_DIR, filePath)
            log_debug(4, "File path", filePath)
            if os.access(filePath, os.R_OK):
                return filePath
        log_debug(4, "Package not found locally: %s" % pkgFilename)
        raise NotLocalError(filePaths[0], pkgFilename)

    def getSourcePackagePath(self, pkgFilename):
        """ OVERLOADS getSourcePackagePath in common/rhnRepository.
            snag src.rpm and nosrc.rpm from local repo, after ensuring
            we are authorized to fetch it.
        """

        log_debug(3, pkgFilename)
        if pkgFilename[-8:] != '.src.rpm' and pkgFilename[-10:] != '.nosrc.rpm':
            raise rhnFault(
                17,
                _("Invalid SRPM package requested: %s") % pkgFilename)

        # Connect to the server to get an authorization for downloading this
        # package
        server = rpclib.Server(self.rhnParentXMLRPC,
                               proxy=self.httpProxy,
                               username=self.httpProxyUsername,
                               password=self.httpProxyPassword)
        if self.caChain:
            server.add_trusted_cert(self.caChain)

        try:
            retval = server.proxy.package_source_in_channel(
                pkgFilename, self.channelName, self.clientInfo)
        except xmlrpclib.Fault, e:
            raise rhnFault(1000,
                           _("Error retrieving source package: %s") %
                           str(e)), None, sys.exc_info()[2]
        if not retval:
            raise rhnFault(
                17,
                _("Invalid SRPM package requested: %s") % pkgFilename)

        if pkgFilename[-8:] != '.src.rpm':
            # We already know the filename ends in .src.rpm
            nvrea = list(parseRPMName(pkgFilename[:-8]))
            nvrea.append("src")
        else:
            # We already know the filename ends in .nosrc.rpm
            # otherwise we did not pass first if in this func
            nvrea = list(parseRPMName(pkgFilename[:-10]))
            nvrea.append("nosrc")

        filePaths = computePackagePaths(nvrea, source=1, prepend=PREFIX)
        for filePath in filePaths:
            filePath = "%s/%s" % (CFG.PKG_DIR, filePath)
            log_debug(4, "File path", filePath)
            if os.access(filePath, os.R_OK):
                return filePath
        log_debug(4, "Source package not found locally: %s" % pkgFilename)
        raise NotLocalError(filePaths[0], pkgFilename)
Пример #49
0
def fetch_token(token_string):
    """ Fetches a token from the database """
    log_debug(3, token_string)
    # A token should always be passed to this function
    assert token_string
    tokens = token_string.split(',')
    h = rhnSQL.prepare(_query_token)
    result = []
    rereg_token_found = 0
    num_of_rereg = 0
    # Global user_id and org_id
    user_id = None
    same_user_id = 1
    org_id = None
    ks_session_id_token = None
    deploy_configs = None
    entitlements_base = {}
    entitlements_extra = {}

    # List of re-registration entitlements labels (if found):
    rereg_ents = []

    for token in tokens:
        h.execute(token=token)
        token_entry, token_entitlements = _fetch_token_from_cursor(h)

        if not token_entry:
            # Unable to find the token
            log_error("Invalid token '%s'" % token)
            raise rhnFault(60, _("Could not find token '%s'") % token, explain=0)

        row = token_entry

        if row.get('server_id'):
            rereg_token_found = row
            num_of_rereg += 1

            # Store the re-reg ents:
            for tup in token_entitlements.keys():
                rereg_ents.append(tup[0])

        # Check user_id
        token_user_id = row.get('user_id')

        # 4/27/05 wregglej - Commented this line out 'cause the token_user_id should
        # be allowed to be None. This line was causing problems when registering with
        # an activation key whose creator had been deleted.
        #assert(token_user_id is not None)

        if same_user_id and user_id is not None and user_id != token_user_id:
            log_debug(4, "Different user ids: %s, %s" % (same_user_id, user_id))
            # This token has a different user id than the rest
            same_user_id = 0
        else:
            user_id = token_user_id

        # Check org_id
        token_org_id = row.get('org_id')
        assert(token_org_id is not None)
        if org_id is not None and org_id != token_org_id:
            # Cannot use activation keys from different orgs
            raise rhnFault(63, _("Tokens from mismatching orgs"), explain=0)
        org_id = token_org_id

        # Check kickstart session ids
        token_ks_session_id = row.get('kickstart_session_id')
        if token_ks_session_id is not None:
            if ks_session_id_token is not None:
                ks_session_id = ks_session_id_token['kickstart_session_id']
                if ks_session_id != token_ks_session_id:
                    # Two tokens with different kickstart sessions
                    raise rhnFault(63, _("Kickstart session mismatch"),
                                   explain=0)
            else:
                # This token has kickstart session id info
                ks_session_id_token = row

        # Iterate through the entitlements from this token
        # and intead of picking one entitlement, create a union of
        # all the entitlemts as a list of tuples of (name, label) aka
        # (token_type, token_desc)
        _categorize_token_entitlements(token_entitlements, entitlements_base,
                                       entitlements_extra)

        # Deploy configs?
        deploy_configs = deploy_configs or (row['deploy_configs'] == 'Y')
        result.append(row)

    # One should not stack re-activation tokens
    if num_of_rereg > 1:
        raise rhnFault(63,
                       _("Stacking of re-registration tokens is not supported"), explain=0)

    entitlements_remove = []
    _validate_entitlements(token_string, rereg_ents, entitlements_base,
                           entitlements_extra, entitlements_remove)
    log_debug(5, "entitlements_base = %s" % entitlements_base)
    log_debug(5, "entitlements_extra = %s" % entitlements_extra)

    if ks_session_id_token:
        ks_session_id = ks_session_id_token['kickstart_session_id']
    else:
        ks_session_id = None

    # akl add entitles array constructed above to kwargs
    kwargs = {
        'user_id': user_id,
        'org_id': org_id,
        'kickstart_session_id': ks_session_id,
        'entitlements': entitlements_base.keys() + entitlements_extra.keys(),
        'deploy_configs': deploy_configs,
    }
    log_debug(4, "Values", kwargs)

    if rereg_token_found and len(result) > 1:
        log_debug(4, "re-activation stacked with activationkeys")
        kwargs['remove_entitlements'] = entitlements_remove
        return ReRegistrationActivationToken(result, **kwargs)
    elif rereg_token_found:
        log_debug(4, "simple re-activation")
        return ReRegistrationToken([rereg_token_found], **kwargs)

    return ActivationTokens(result, **kwargs)
Пример #50
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)
Пример #51
0
# default template values for error messages
templateValues = {
    'hostname': 'rhn.redhat.com',
}

# This array translates exception codes into meaningful messages
# for the eye of the beholder
# DOMAINS:
#   0-999:     Red Hat client/client-like interaction errors
#   1000-1999: Proxy specific interaction errors
#   2000-2999: Red Hat Satellite specific interation errors

FaultArray = {
    # 0-999: Red Hat client/client-like interaction errors:
    1:
    _("This does not appear to be a valid username."),
    2:
    _("Invalid username and password combination."),
    3:
    _("This login is already taken, or the password is incorrect."),
    4:
    _("Permission denied."),
    6:
    _("Object not found."),
    8:
    _("Invalid System Digital ID."),
    9:
    _("Invalid System Credentials."),
    10:
    _("Could not retrieve user data from database."),
    11:
Пример #52
0
def get_package_path(server_id, pkg_spec, channel):
    log_debug(3, server_id, pkg_spec, channel)
    if isinstance(pkg_spec, ListType):
        pkg = pkg_spec[:4]
        # Insert EPOCH
        pkg.insert(1, None)
    else:
        pkg = parseRPMFilename(pkg_spec)
        if pkg is None:
            log_debug(4, "Error", "Requested weird package", pkg_spec)
            raise rhnFault(17,
                           _("Invalid RPM package %s requested") % pkg_spec)

    statement = """
        select  p.id, p.path path, pe.epoch epoch
        from
                rhnPackageArch pa,
                rhnChannelPackage cp,
                rhnPackage p,
                rhnPackageEVR pe,
                rhnServerChannel sc,
                rhnPackageName pn,
                rhnChannel c
        where 1=1
            and c.label = :channel
            and pn.name = :name
            and sc.server_id = :server_id
            and pe.version = :ver
            and pe.release = :rel
            and c.id = sc.channel_id
            and c.id = cp.channel_id
            and pa.label = :arch
            and pn.id = p.name_id
            and p.id = cp.package_id
            and p.evr_id = pe.id
            and sc.channel_id = cp.channel_id
            and p.package_arch_id = pa.id
    """
    h = rhnSQL.prepare(statement)
    pkg = list(map(str, pkg))
    h.execute(name=pkg[0],
              ver=pkg[2],
              rel=pkg[3],
              arch=pkg[4],
              channel=channel,
              server_id=server_id)
    rs = h.fetchall_dict()
    if not rs:
        log_debug(4, "Error", "Non-existant package requested", server_id,
                  pkg_spec, channel)
        raise rhnFault(17, _("Invalid RPM package %s requested") % pkg_spec)
    # It is unlikely for this query to return more than one row,
    # but it is possible
    # (having two packages with the same n, v, r, a and different epoch in
    # the same channel is prohibited by the RPM naming scheme; but extra
    # care won't hurt)
    max_row = rs[0]
    for each in rs[1:]:
        # Compare the epoch as string
        if _none2emptyString(each['epoch']) > _none2emptyString(
                max_row['epoch']):
            max_row = each

    # Set the flag for the proxy download accelerator
    rhnFlags.set("Download-Accelerator-Path", max_row['path'])
    return check_package_file(max_row['path'], max_row['id'],
                              pkg_spec), max_row['id']
Пример #53
0
    def __checkAuthSessionTokenCache(self, token, channel):
        """ Authentication / authorize the channel """

        log_debug(2, token, channel)
        self.clientServerId = token['X-RHN-Server-ID']

        cachedToken = self.proxyAuth.get_client_token(self.clientServerId)
        if not cachedToken:
            # maybe client logged in through different load-balanced proxy
            # try to update the cache an try again
            cachedToken = self.proxyAuth.update_client_token_if_valid(
                self.clientServerId, token)

            if not cachedToken:
                msg = _("Invalid session key - server ID not found in cache: %s") \
                        % self.clientServerId
                log_error(msg)
                raise rhnFault(33, msg)

        self.cachedClientInfo = UserDictCase(cachedToken)

        clockSkew = self.cachedClientInfo["X-RHN-Auth-Proxy-Clock-Skew"]
        del self.cachedClientInfo["X-RHN-Auth-Proxy-Clock-Skew"]

        # Add the server id
        self.authChannels = self.cachedClientInfo['X-RHN-Auth-Channels']
        del self.cachedClientInfo['X-RHN-Auth-Channels']
        self.cachedClientInfo['X-RHN-Server-ID'] = self.clientServerId
        log_debug(4, 'Retrieved token from cache: %s' % self.cachedClientInfo)

        # Compare the two things
        if not _dictEquals(token, self.cachedClientInfo,
                           ['X-RHN-Auth-Channels']):
            # Maybe the client logged in through a different load-balanced
            # proxy? Check validity of the token the client passed us.
            updatedToken = self.proxyAuth.update_client_token_if_valid(
                self.clientServerId, token)
            # fix up the updated token the same way we did above
            if updatedToken:
                self.cachedClientInfo = UserDictCase(updatedToken)
                clockSkew = self.cachedClientInfo[
                    "X-RHN-Auth-Proxy-Clock-Skew"]
                del self.cachedClientInfo["X-RHN-Auth-Proxy-Clock-Skew"]
                self.authChannels = self.cachedClientInfo[
                    'X-RHN-Auth-Channels']
                del self.cachedClientInfo['X-RHN-Auth-Channels']
                self.cachedClientInfo['X-RHN-Server-ID'] = \
                        self.clientServerId
                log_debug(
                    4,
                    'Retrieved token from cache: %s' % self.cachedClientInfo)

            if not updatedToken or not _dictEquals(
                    token, self.cachedClientInfo, ['X-RHN-Auth-Channels']):
                log_debug(3, "Session tokens different")
                raise rhnFault(33)  # Invalid session key

        # Check the expiration
        serverTime = float(token['X-RHN-Auth-Server-Time'])
        offset = float(token['X-RHN-Auth-Expire-Offset'])
        if time.time() > serverTime + offset + clockSkew:
            log_debug(3, "Session token has expired")
            raise rhnFault(34)  # Session key has expired

        # Only autherized channels are the ones stored in the cache.
        authChannels = [x[0] for x in self.authChannels]
        log_debug(4, "Auth channels: '%s'" % authChannels)
        # Check the authorization
        if channel not in authChannels:
            log_debug(4,
                      "Not subscribed to channel %s; unauthorized" % channel)
            raise rhnFault(35, _('Unauthorized channel access requested.'))
Пример #54
0
    def __callLocalRepository(self, req_type, identifier, funct, params):
        """ Contacts the local repository and retrieves files"""

        log_debug(2, req_type, identifier, funct, params)

        # 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']

        if req_type == 'tinyurl':
            try:
                rep = rhnRepository.TinyUrlRepository(
                    identifier,
                    self.cachedClientInfo,
                    rhnParent=self.rhnParent,
                    rhnParentXMLRPC=self.rhnParentXMLRPC,
                    httpProxy=self.httpProxy,
                    httpProxyUsername=self.httpProxyUsername,
                    httpProxyPassword=self.httpProxyPassword,
                    caChain=self.caChain,
                    systemId=self.proxyAuth.get_system_id())
            except rhnRepository.NotLocalError:
                return None
        elif req_type == 'ks-dist':
            try:
                rep = rhnRepository.KickstartRepository(
                    identifier,
                    self.cachedClientInfo,
                    rhnParent=self.rhnParent,
                    rhnParentXMLRPC=self.rhnParentXMLRPC,
                    httpProxy=self.httpProxy,
                    httpProxyUsername=self.httpProxyUsername,
                    httpProxyPassword=self.httpProxyPassword,
                    caChain=self.caChain,
                    orgId=params['orgId'],
                    child=params['child'],
                    session=params['session'],
                    systemId=self.proxyAuth.get_system_id())
            except rhnRepository.NotLocalError:
                return None
            params = [params['file']]
        else:
            # Find the channel version
            version = None
            for c in self.authChannels:
                ch, ver = c[:2]
                if ch == identifier:
                    version = ver
                    break

            # We already know he's subscribed to this channel
            # channel, so the version is non-null
            rep = rhnRepository.Repository(
                identifier,
                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
Пример #55
0
    def handler(self):
        """ Main handler to handle all requests pumped through this server. """

        # pylint: disable=R0915
        log_debug(1)
        self._prepHandler()

        _oto = rhnFlags.get('outputTransportOptions')

        # tell parent that we can follow redirects, even if client is not able to
        _oto['X-RHN-Transport-Capability'] = "follow-redirects=3"

        # No reason to put Host: in the header, the connection object will
        # do that for us

        # Add/modify the X-RHN-IP-Path header.
        ip_path = None
        if 'X-RHN-IP-Path' in _oto:
            ip_path = _oto['X-RHN-IP-Path']
        log_debug(4, "X-RHN-IP-Path is: %s" % repr(ip_path))
        client_ip = self.req.connection.remote_ip
        if ip_path is None:
            ip_path = client_ip
        else:
            ip_path += ',' + client_ip
        _oto['X-RHN-IP-Path'] = ip_path

        # NOTE: X-RHN-Proxy-Auth described in broker/rhnProxyAuth.py
        if 'X-RHN-Proxy-Auth' in _oto:
            log_debug(
                5, 'X-RHN-Proxy-Auth currently set to: %s' %
                repr(_oto['X-RHN-Proxy-Auth']))
        else:
            log_debug(5, 'X-RHN-Proxy-Auth is not set')

        if self.req.headers_in.has_key('X-RHN-Proxy-Auth'):
            tokens = []
            if 'X-RHN-Proxy-Auth' in _oto:
                tokens = _oto['X-RHN-Proxy-Auth'].split(',')
            log_debug(5, 'Tokens: %s' % tokens)

        # GETs: authenticate user, and service local GETs.
        getResult = self.__local_GET_handler(self.req)
        if getResult is not None:
            # it's a GET request
            return getResult

        # 1. check cached version of the proxy login,
        #    snag token if there...
        #    if not... login...
        #    if good token, cache it.
        # 2. push into headers.
        authToken = self.proxyAuth.check_cached_token()
        log_debug(5, 'Auth token for this machine only! %s' % authToken)
        tokens = []

        _oto = rhnFlags.get('outputTransportOptions')
        if _oto.has_key('X-RHN-Proxy-Auth'):
            log_debug(
                5,
                '    (auth token prior): %s' % repr(_oto['X-RHN-Proxy-Auth']))
            tokens = _oto['X-RHN-Proxy-Auth'].split(',')

        # list of tokens to be pushed into the headers.
        tokens.append(authToken)
        tokens = [t for t in tokens if t]

        _oto['X-RHN-Proxy-Auth'] = ','.join(tokens)
        log_debug(
            5, '    (auth token after): %s' % repr(_oto['X-RHN-Proxy-Auth']))

        log_debug(3, 'Trying to connect to parent')

        # Loops twice? Here's why:
        #   o If no errors, the loop is broken and we move on.
        #   o If an error, either we get a new token and try again,
        #     or we get a critical error and we fault.
        for _i in range(2):
            self._connectToParent()  # part 1

            log_debug(4, 'after _connectToParent')
            # Add the proxy version
            rhnFlags.get('outputTransportOptions'
                         )['X-RHN-Proxy-Version'] = str(_PROXY_VERSION)

            status = self._serverCommo()  # part 2

            # check for proxy authentication blowup.
            respHeaders = self.responseContext.getHeaders()
            if not respHeaders or \
               not respHeaders.has_key('X-RHN-Proxy-Auth-Error'):
                # No proxy auth errors
                # XXX: need to verify that with respHeaders ==
                #      None that is is correct logic. It should be -taw
                break

            error = str(respHeaders['X-RHN-Proxy-Auth-Error']).split(':')[0]

            # If a proxy other than this one needs to update its auth token
            # pass the error on up to it
            if (respHeaders.has_key('X-RHN-Proxy-Auth-Origin')
                    and respHeaders['X-RHN-Proxy-Auth-Origin'] !=
                    self.proxyAuth.hostname):
                break

            # Expired/invalid auth token; go through the loop once again
            if error == '1003':  # invalid token
                msg = "Spacewalk Proxy Session Token INVALID -- bad!"
                log_error(msg)
                log_debug(0, msg)
            elif error == '1004':
                log_debug(
                    1,
                    "Spacewalk Proxy Session Token expired, acquiring new one."
                )
            else:  # this should never happen.
                msg = "Spacewalk Proxy login failed, error code is %s" % error
                log_error(msg)
                log_debug(0, msg)
                raise rhnFault(
                    1000,
                    _("Spacewalk Proxy error (issues with proxy login). "
                      "Please contact your system administrator."))

            # Forced refresh of the proxy token
            rhnFlags.get('outputTransportOptions')[
                'X-RHN-Proxy-Auth'] = self.proxyAuth.check_cached_token(1)
        else:  # for
            # The token could not be aquired
            log_debug(0, "Unable to acquire proxy authentication token")
            raise rhnFault(
                1000,
                _("Spacewalk Proxy error (unable to acquire proxy auth token). "
                  "Please contact your system administrator."))

        # Support for yum byte-range
        if (status != apache.OK) and (status != apache.HTTP_PARTIAL_CONTENT):
            log_debug(1, "Leaving handler with status code %s" % status)
            return status

        self.__handleAction(self.responseContext.getHeaders())

        return self._clientCommo()
Пример #56
0
 def __repr__(self):
     return _("Invalid request received (%s).") % self.__value
Пример #57
0
def token_channels(server, server_arch, tokens_obj):
    """ Handle channel subscriptions for the registration token """
    assert(isinstance(tokens_obj, ActivationTokens))

    server_id, server_arch_id = server['id'], server['server_arch_id']

    # what channels are associated with this token (filter only those
    # compatible with this server)
    h = rhnSQL.prepare("""
    select
        rtc.channel_id id, c.name, c.label, c.parent_channel
    from
        rhnRegTokenChannels rtc,
        rhnChannel c,
        rhnServerChannelArchCompat scac
    where rtc.token_id = :token_id
        and rtc.channel_id = c.id
        and c.channel_arch_id = scac.channel_arch_id
        and scac.server_arch_id = :server_arch_id
    """)

    chash = {}
    base_channel_token = None
    base_channel_id = None

    for token in tokens_obj.tokens:
        token_id = token['token_id']
        h.execute(token_id=token_id, server_arch_id=server_arch_id)
        while 1:
            row = h.fetchone_dict()
            if not row:
                break
            channel_id = row['id']
            chash[channel_id] = row
            if row['parent_channel'] is not None:
                # Not a base channel
                continue

            # We only allow for one base channel
            if base_channel_id is not None and channel_id != base_channel_id:
                # Base channels conflict - are they coming from the same
                # token?
                if base_channel_token == token:
                    log_error("Token has multiple base channels", token_id,
                              base_channel_id)
                    raise rhnFault(62,
                                   _("Token `%s' has more than one base channel assigned")
                                   % token['note'])
                raise rhnFault(63, _("Conflicting base channels"))
            base_channel_id = channel_id
            base_channel_token = token

    bc = chash.get(base_channel_id)
    log_debug(4, "base channel", bc)

    # get the base channel for this server
    # Note that we are hitting this codepath after newserver.__save() has been
    # run, which means we've already chosen a base channel
    # from rhnDistChannelMap
    sbc = rhnChannel.get_base_channel(server_id, none_ok=1)

    # prepare the return value
    ret = []

    # now try to figure out which base channel we prefer
    if bc is None:
        if sbc is None:
            # we need at least one base channel definition
            log_error("Server has invalid release and "
                      "token contains no base channels", server_id,
                      tokens_obj.tokens)
            ret.append("System registered without a base channel")
            ret.append("Unsupported release-architecture combination "
                       "(%s, %s)" % (server["release"], server_arch))
            return ret
    else:  # do we need to drop the one from sbc?
        if sbc and sbc["id"] != bc["id"]:  # we need to prefer the token one
            # unsubscribe from old channel(s)
            rhnChannel.unsubscribe_all_channels(server_id)
            sbc = None  # force true on the next test
        if sbc is None:
            # no base channel subscription at this point
            try:
                rhnChannel._subscribe_sql(server_id, bc["id"], commit=0)
            except rhnChannel.SubscriptionCountExceeded:
                ret.append("System registered without a base channel: "
                           "subscription count exceeded for channel %s (%s)" %
                           (bc["name"], bc["label"]))
                return ret

            ret.append("Subscribed to base channel '%s' (%s)" % (
                bc["name"], bc["label"]))
            sbc = bc

    # attempt to subscribe all non-base channels associated with this
    # token
    subscribe_channel = rhnSQL.Procedure("rhn_channel.subscribe_server")
    # Use a set here to ensure uniqueness of the
    # channel family ids used in the loop below.
    channel_family_ids = set()

    for c in filter(lambda a: a["parent_channel"], chash.values()):
        # make sure this channel has the right parent
        if str(c["parent_channel"]) != str(sbc["id"]):
            ret.append("NOT subscribed to channel '%s' "
                       "(not a child of '%s')" % (
                           c["name"], sbc["name"]))
            continue
        try:
            # don't run the EC yet
            # XXX: test return code when this one will start returning
            # a status
            subscribe_channel(server_id, c["id"], 0, None, 0)
            child = rhnChannel.Channel()
            child.load_by_id(c["id"])
            child._load_channel_families()
            cfamid = child._channel_families[0]
            channel_family_ids.add(cfamid)
        except rhnSQL.SQLError, e:
            log_error("Failed channel subscription", server_id,
                      c["id"], c["label"], c["name"])
            ret.append("FAILED to subscribe to channel '%s'" % c["name"])
        else:
            ret.append("Subscribed to channel '%s'" % c["name"])
Пример #58
0
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]
Пример #59
0
    def submit(self, system_id, action_id, result, message="", data={}):
        """ Submit the results of a queue run.
            Maps old and new rhn_check behavior to new database status codes

            The new API uses 4 slightly different status codes than the
            old client does.  This function will "hopefully" sensibly
            map them.  Old methodology:
               -rhn_check retrieves an action from the top of the action queue.
               -It attempts to execute the desired action and returns either
                   (a) 0   -- presumed successful.
                   (b) rhnFault object -- presumed failed
                   (c) some other non-fault object -- *assumed* successful.
               -Regardless of result code, action is marked as "executed"

            We try to make a smarter status selection (i.e. failed||completed).

            For reference:
            New DB status codes:      Old DB status codes:
                  0: Queued               0: queued
                  1: Picked Up            1: picked up
                  2: Completed            2: executed
                  3: Failed               3: completed
        """
        if type(action_id) is not IntType:
            # Convert it to int
            try:
                action_id = int(action_id)
            except ValueError:
                log_error("Invalid action_id", action_id)
                raise_with_tb(rhnFault(30, _("Invalid action value type %s (%s)") %
                               (action_id, type(action_id))), sys.exc_info()[2])
        # Authenticate the system certificate
        self.auth_system(system_id)
        log_debug(1, self.server_id, action_id, result)
        # check that the action is valid
        # We have a uniqueness constraint on (action_id, server_id)
        h = rhnSQL.prepare("""
            select at.label action_type,
                   at.trigger_snapshot,
                   at.name
              from rhnServerAction sa,
                   rhnAction a,
                   rhnActionType at
             where sa.server_id = :server_id
               and sa.action_id = :action_id
               and sa.status = 1
               and a.id = :action_id
               and a.action_type = at.id
        """)
        h.execute(server_id=self.server_id, action_id=action_id)
        row = h.fetchone_dict()
        if not row:
            log_error("Server %s does not own action %s" % (
                self.server_id, action_id))
            raise rhnFault(22, _("Action %s does not belong to server %s") % (
                action_id, self.server_id))

        action_type = row['action_type']
        trigger_snapshot = (row['trigger_snapshot'] == 'Y')

        if 'missing_packages' in data:
            missing_packages = "Missing-Packages: %s" % str(
                data['missing_packages'])
            rmsg = "%s %s" % (message, missing_packages)
        elif 'koan' in data:
            rmsg = "%s: %s" % (message, data['koan'])
        else:
            rmsg = message

        rcode = result
        # Careful with this one, result can be a very complex thing
        # and this processing is required for compatibility with old
        # rhn_check clients
        if type(rcode) == type({}):
            if "faultCode" in result:
                rcode = result["faultCode"]
            if "faultString" in result:
                rmsg = result["faultString"] + str(data)
        if type(rcode) in [type({}), type(()), type([])] \
                or type(rcode) is not IntType:
            rmsg = u"%s [%s]" % (UnicodeType(message), UnicodeType(rcode))
            rcode = -1
        # map to db codes.
        status = self.status_for_action_type_code(action_type, rcode)

        if status == 3:
            # Failed action - invalidate children
            self._invalidate_child_actions(action_id)
        elif action_type == 'reboot.reboot':
            # reboot action should stay as pickup
            rhnSQL.commit()
            return 0
        elif status == 2 and trigger_snapshot and self.__should_snapshot():
            # if action status is 'Completed', snapshot if allowed and if needed
            self.server.take_snapshot("Scheduled action completion:  %s" % row['name'])

        self.__update_action(action_id, status, rcode, rmsg)

        # Store the status in a flag - easier than to complicate the action
        # plugin API by adding a status
        rhnFlags.set('action_id', action_id)
        rhnFlags.set('action_status', status)

        self.process_extra_data(self.server_id, action_id, data=data,
                                action_type=action_type)

        # commit, because nobody else will
        rhnSQL.commit()
        return 0
Пример #60
0
                # in each stack frame, and eventually will try to stringify
                # the method object itself
                # This should trick it, since the originator of the exception
                # is this function, instead of a deep call into xmlrpclib
                log_error("%s" % e)
                if e.faultCode == 10000:
                    # reraise it for the users (outage or "important message"
                    # coming through")
                    raise rhnFault(e.faultCode, e.faultString), None, sys.exc_info()[2]
                # ok... it's some other fault
                Traceback("ProxyAuth.login (Fault) - Spacewalk Proxy not "
                          "able to log in.")
                # And raise a Proxy Error - the server made its point loud and
                # clear
                raise rhnFault(1000,
                               _("Spacewalk Proxy error (during proxy login). "
                                 "Please contact your system administrator.")), None, sys.exc_info()[2]
            except Exception, e:  # pylint: disable=E0012, W0703
                token = None
                log_error("Unhandled exception", e)
                Traceback(mail=0)
                time.sleep(.25)
                continue
            else:
                break

        if not token:
            if error:
                if error[0] in ('xmlrpclib.ProtocolError', 'socket.error', 'socket'):
                    raise rhnFault(1000,
                                   _("Spacewalk Proxy error (error: %s). "
                                     "Please contact your system administrator.") % error[0])