def moveChannelDownloads(self, channel_id, old_channel_family_id, new_channel_family_id, username, password): log_debug(3) self._auth(username, password) if old_channel_family_id is None or \ old_channel_family_id == new_channel_family_id: # Nothing to be done here, same channel family return 0 log_debug(3, " Migrating downloads") try: rhnSQL.execute(""" update rhnDownloads set channel_family_id = :new_channel_family_id where channel_family_id = :old_channel_family_id and id in ( select downloads_id from rhnChannelDownloads where channel_id = :channel_id) """, channel_id=channel_id, old_channel_family_id=old_channel_family_id, new_channel_family_id=new_channel_family_id, ) except rhnSQL.SQLError, e: rhnSQL.rollback() raise rhnFault(23, str(e.args[1]), explain=0 )
def initiate(server_id, action_id, dry_run=0): log_debug(3) h = rhnSQL.prepare(_query_initiate_guest) h.execute(action_id=action_id) row = h.fetchone_dict() if not row: raise InvalidAction("Kickstart action without an associated kickstart") kickstart_host = row['kickstart_host'] virt_type = row['virt_type'] name = row['guest_name'] boot_image = "spacewalk-koan" append_string = row['append_string'] vcpus = row['vcpus'] disk_gb = row['disk_gb'] mem_kb = row['mem_kb'] ks_session_id = row['ks_session_id'] virt_bridge = row['virt_bridge'] disk_path = row['disk_path'] cobbler_system_name = row['cobbler_system_name'] if not boot_image: raise InvalidAction("Boot image missing") return (kickstart_host, cobbler_system_name, virt_type, ks_session_id, name, mem_kb, vcpus, disk_gb, virt_bridge, disk_path, append_string)
def _cacheObj(self, fileName, version, dataProducer, params=None): """ The real workhorse for all flavors of listall It tries to pull data out of a file; if it doesn't work, it calls the data producer with the specified params to generate the data, which is also cached. Returns a string from a cache file or, if the cache file is not there, calls dataProducer to generate the object and caches the results """ log_debug(4, fileName, version, params) fileDir = self._getPkgListDir() filePath = "%s/%s-%s" % (fileDir, fileName, version) if os.access(filePath, os.R_OK): # Slurp the file f = open(filePath, "r") data = f.read() f.close() return data # The file's not there; query the DB or whatever dataproducer used. if not params: stringObject = dataProducer() else: stringObject = apply(dataProducer, params) # Cache the thing cache(stringObject, fileDir, fileName, version) # Return the string return stringObject
def _transformKickstartRequestForBroker(self, req): # Get the checksum for the requested resource from the satellite. (status, checksum) = self._querySatelliteForChecksum(req) if status != apache.OK or not checksum: return status # If we got this far, we have the checksum. Create a new URI based on # the checksum. newURI = self._generateCacheableKickstartURI(req.uri, checksum) if not newURI: # Couldn't create a cacheable URI, log an error and revert to # BZ 158236 behavior. log_error('Could not create cacheable ks URI from "%s"' % req.uri) return apache.OK # Now we must embed the old URI into a header in the original request # so that the SSL Redirect has it available if the resource has not # been cached yet. We will also embed a header that holds the new URI, # so that the content handler can use it later. log_debug(3, "Generated new kickstart URI: %s" % newURI) req.headers_in.add(HEADER_ACTUAL_URI, req.uri) req.headers_in.add(HEADER_EFFECTIVE_URI, newURI) return apache.OK
def add_tools_channel(server_id, action_id, dry_run=0): log_debug(3) if (not dry_run): subscribe_to_tools_channel(server_id) else: log_debug(4, "dry run requested") raise ShadowAction("Subscribed guest to tools channel.")
def upload(server_id, action_id, dry_run=0): log_debug(3) h = rhnSQL.prepare(_query_upload_files) h.execute(action_id=action_id, server_id=server_id) files = map(lambda x: x['path'], h.fetchall_dict() or []) return action_id, files
def initiate(server_id, action_id, data={}): log_debug(3, action_id) action_status = rhnFlags.get('action_status') server_kickstart.update_kickstart_session(server_id, action_id, action_status, kickstart_state='injected', next_action_type='reboot.reboot')
def handler(self): """ Main handler for all requests pumped through this server. """ log_debug(4, 'In redirect handler') self._prepHandler() #self.__checkLegalRedirect() # Rebuild the X-Forwarded-For header so that it reflects the actual # path of the request. We must do this because squid is unable to # determine the "real" client, and will make each entry in the chain # 127.0.0.1. _oto = rhnFlags.get('outputTransportOptions') _oto['X-Forwarded-For'] = _oto['X-RHN-IP-Path'] self.rhnParent = self.rhnParent or '' # paranoid log_debug(4, 'Connecting to parent...') self._connectToParent() # part 1 log_debug(4, 'Initiating communication with server...') status = self._serverCommo(self.req.read()) # part 2 if (status != apache.OK) and (status != apache.HTTP_PARTIAL_CONTENT): log_debug(3, "Leaving handler with status code %s" % status) return status log_debug(4, 'Initiating communication with client...') # If we got this far, it has to be a good response return self._clientCommo(status)
def test_login(self, username, password): log_debug(5, username) try: authobj = auth( username, password ) except: return 0 return 1
def mtime_upload(server_id, action_id, data={}): # at this point in time, no rhnActionConfigFileName entries exist, because # we didn't know them at schedule time... go ahead and create them now, and then # just use the main upload to handle the updating of the state... paths = data.get('attempted_paths') or [] if not paths: log_debug(6, "no matched files") return log_debug(6, 'attempted paths', paths) # if there are already rhnActionConfigFileName entries for this sid+aid, # it's most likely a rescheduled action, and we'll need to blow away the old # entries (they might not be valid any longer) h = rhnSQL.prepare(_query_any_action_config_filenames) h.execute(server_id=server_id, action_id=action_id) already_filenames = h.fetchone_dict() or [] if already_filenames: h = rhnSQL.prepare(_query_clear_action_config_filenames) h.execute(server_id=server_id, action_id=action_id) num_paths = len(paths) h = rhnSQL.prepare(_query_create_action_config_filename) h.execute_bulk({ 'action_id' : [action_id] * num_paths, 'server_id' : [server_id] * num_paths, 'path' : paths, }) upload(server_id, action_id, data)
def __redirectFailover(self): """ This routine resends the original request back to the satellite/hosted system if a redirect to a 3rd party failed. To prevent redirection loops from occurring, an "X-RHN-Redirect: 0" header is passed along with the request. This function will return apache.HTTP_OK if everything succeeded, otherwise it will return an appropriate HTTP error code. """ # Add a special header which will tell the server not to send us any # more redirects. headers = rhnFlags.get('outputTransportOptions') headers[rhnConstants.HEADER_RHN_REDIRECT] = '0' log_debug(4, "Added X-RHN-Redirect header to outputTransportOptions:", \ headers) # Reset the existing connection and reconnect to the RHN parent server. self.responseContext.clear() self._connectToParent() # We'll just call serverCommo once more. The X-RHN-Redirect constant # will prevent us from falling into an infinite loop. Only GETs are # redirected, so we can safely pass an empty string in as the request # body. status = self._serverCommo('') # This little hack isn't pretty, but lets us normalize our result code. if status == apache.OK: status = apache.HTTP_OK return status
def update(server_id, action_id, data={}): log_debug(3, server_id, action_id) action_status = rhnFlags.get('action_status') if action_status == 3: # Action failed kickstart_state = 'failed' next_action_type = None else: kickstart_state = 'deployed' #This is horrendous, but in order to fix it I would have to change almost all of the #actions code, which we don't have time to do for the 500 beta. --wregglej try: ks_session_type = server_kickstart.get_kickstart_session_type(server_id, action_id) except rhnException, re: ks_session_type = None if ks_session_type is None: next_action_type = "None" elif ks_session_type == 'para_guest': next_action_type = 'kickstart_guest.initiate' else: next_action_type = 'kickstart.initiate'
def process(self): log_debug(3) # nice thing that req has a read() method, so it makes it look just # like an fd try: fd = self.input.decode(self.req) except IOError: # client timed out return apache.HTTP_BAD_REQUEST # Read the data from the request _body = fd.read() fd.close() # In this case, we talk to a client (maybe through a proxy) # make sure we have something to decode if _body is None or len(_body) == 0: return apache.HTTP_BAD_REQUEST # Decode the request; avoid logging crappy responses try: params, method = self.decode(_body) except rpclib.ResponseError: log_error("Got bad XML-RPC blob of len = %d" % len(_body)) return apache.HTTP_BAD_REQUEST else: if params is None: params = () # make the actual function call and return the result return self.call_function(method, params)
def updateDist(self, kwargs, username, password): log_debug(3) self._auth(username, password) if not kwargs.get('release'): raise rhnFault(23, "Insufficient data, release missing to update dist", explain=0) if not kwargs.get('os'): kwargs['os'] = 'Red Hat Linux' if kwargs.get('channel_id') is None: # Missing stuff raise rhnFault(23, "Insufficient data, channel_id missing to update dist", explain=0) if kwargs.get('channel_arch_id') is None: # Missing stuff raise rhnFault(23, "Insufficient data, channel arch id missing to update dist", explain=0) try: rhnSQL.execute(""" insert into rhnDistChannelMap (channel_id, channel_arch_id, os, release) values (:channel_id, :channel_arch_id, :os, :release) """, kwargs) except rhnSQL.SQLError, e: rhnSQL.rollback() raise rhnFault(23, str(e.args[1]), explain=0 )
def dump_errata(self, errata, verify_errata=False): log_debug(2) errata_hash = {} if verify_errata: h = self.get_errata_statement() for erratum in errata: errata_id = self._get_item_id('rhn-erratum-', str(erratum), 3004, "Wrong erratum name %s") if errata_hash.has_key(errata_id): # Already verified continue h.execute(errata_id=errata_id) row = h.fetchone_dict() if not row: # XXX Silently ignore it? raise rhnFault(3005, "No such erratum %s" % erratum) # Saving the row, it's handy later when we create the iterator errata_hash[errata_id] = row else: for erratum in errata: errata_hash[erratum['errata_id']] = erratum self._write_dump(ErrataDumper, params=errata_hash.values()) return 0
def uploadPackageBySession(self, session_string, info): log_debug(3) channels = info.get('channels', []) force = info.get('force', 0) org_id, force = rhnPackageUpload.authenticate_session(session_string, channels=channels, force=force) return self._uploadPackage(channels, org_id, force, info)
def getUserGroupsFromUserInstance(user_instance): log_debug(4, user_instance.getid()) user = user_instance if not user: log_debug("null user") raise rhnFault(2) #Don't need to check the password, the session should have already been checked. # Get the org id org_id = user.contact['org_id'] user_id = user.getid() h = rhnSQL.prepare(""" select ugt.label from rhnUserGroupType ugt, rhnUserGroup ug, rhnUserGroupMembers ugm where ugm.user_id = :user_id and ugm.user_group_id = ug.id and ug.group_type = ugt.id """) h.execute(user_id=user_id) groups = [] while 1: row = h.fetchone_dict() if not row: break groups.append(row['label']) return groups, org_id, user_id
def getAnyChecksum(self, info, username = None, password = None, session = None, is_source = 0): """ returns checksum info of available packages also does an existance check on the filesystem. """ log_debug(3) pkg_infos = info.get('packages') channels = info.get('channels', []) force = info.get('force', 0) orgid = info.get('org_id') if orgid == 'null': null_org=1 else: null_org=None if not session: org_id, force = rhnPackageUpload.authenticate(username, password, channels=channels, null_org=null_org, force=force) else: try: org_id, force = rhnPackageUpload.authenticate_session( session, channels=channels, null_org=null_org, force=force) except rhnSession.InvalidSessionError: raise rhnFault(33) except rhnSession.ExpiredSessionError: raise rhnFault(34) if is_source: ret = self._getSourcePackageChecksum(org_id, pkg_infos) else: ret = self._getPackageChecksum(org_id, pkg_infos) return ret
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
def __init__(self): log_debug(3) RPC_Base.__init__(self) self.functions.append('uploadPackageInfo') self.functions.append('uploadPackageInfoBySession') self.functions.append('uploadSourcePackageInfo') self.functions.append('uploadSourcePackageInfoBySession') self.functions.append('listChannel') self.functions.append('listChannelBySession') self.functions.append('listChannelSource') self.functions.append('listChannelSourceBySession') self.functions.append('listMissingSourcePackages') self.functions.append('listMissingSourcePackagesBySession') self.functions.append('uploadPackage') self.functions.append('uploadPackageBySession') self.functions.append('channelPackageSubscription') self.functions.append('channelPackageSubscriptionBySession') self.functions.append('no_op') self.functions.append('test_login') self.functions.append('test_new_login') self.functions.append('test_check_session') self.functions.append('login') self.functions.append('check_session') self.functions.append('getPackageChecksum') self.functions.append('getPackageChecksumBySession') self.functions.append('getSourcePackageChecksum') self.functions.append('getSourcePackageChecksumBySession') # old MD5 compatibility functions self.functions.append('getPackageMD5sum') self.functions.append('getPackageMD5sumBySession') self.functions.append('getSourcePackageMD5sum') self.functions.append('getSourcePackageMD5sumBySession')
def testPackages(self, login, password, info): authobj = auth(login, password) info['orgId'] = authobj.org_id packages = info.get('packages') for package in packages: package['header'] = rhn_rpm.headerLoad(package['header'].data) # get back dictionaries of lists, key == filename results = {} log_debug(1, info) testChecksums(info, results) testObsoletes(info, results) testDependencies(info, results) #log_debug(3, results) problems = [] for problem_package in results.keys(): problems.append(format_package_problems(problem_package, results[problem_package])) return """ rhn-lint RPM Package Tests: =========================== Problem packages: %s """ % string.join(problems, "\n\n")
def _getSourcePackageChecksum(self, org_id, pkg_infos): """ Gives checksum info of available source packages. Also does an existance check on the filesystem. """ log_debug(3) statement = """ select ps.path path, c.checksum, c.checksum_type from rhnSourceRpm sr, rhnPackageSource ps, rhnChecksumView c where sr.name = :name and ps.source_rpm_id = sr.id and ( ps.org_id = :orgid or ( ps.org_id is null and :orgid is null ) ) and ps.checksum_id = c.id """ h = rhnSQL.prepare(statement) row_list = {} for pkg in pkg_infos.keys(): row_list[pkg] = self._get_package_checksum(h, {'name':pkg, 'orgid': org_id}) return row_list
def getComponentType(req): """ Are we a 'proxy.broker' or a 'proxy.redirect'. Checks to see if the last visited RHN Proxy was itself. If so, we are a 'proxy.redirect'. If not, then we must be a 'proxy.broker'. """ # NOTE: X-RHN-Proxy-Auth described in broker/rhnProxyAuth.py if not req.headers_in.has_key('X-RHN-Proxy-Auth'): # Request comes from a client, Must be the broker return COMPONENT_BROKER # pull server id out of "t:o:k:e:n:hostname1,t:o:k:e:n:hostname2,..." proxy_auth = req.headers_in['X-RHN-Proxy-Auth'] last_auth = string.split(proxy_auth, ',')[-1] last_visited = string.split(last_auth, ':')[0] proxy_server_id = get_proxy_auth().getProxyServerId() # is it the same box? try: log_debug(4, "last_visited", last_visited, "; proxy server id", proxy_server_id) except: # incase called prior to the log files being initialized pass if last_visited == proxy_server_id: # XXX this assumes redirect runs on the same box as the broker return COMPONENT_REDIRECT return COMPONENT_BROKER
def __reserve_user_db(user, password): encrypted_password = CFG.encrypted_passwords log_debug(3, user, CFG.disallow_user_creation, encrypted_password, CFG.pam_auth_service) user = str(user) h = rhnSQL.prepare(""" select w.id, w.password, w.old_password, w.org_id, ui.use_pam_authentication from web_contact w, rhnUserInfo ui where w.login_uc = upper(:p1) and w.id = ui.user_id """) h.execute(p1=user) data = h.fetchone_dict() if data and data["id"]: # contact exists, check password if data['use_pam_authentication'] == 'Y' and CFG.pam_auth_service: # We use PAM for authentication import rhnAuthPAM if rhnAuthPAM.check_password(user, password, CFG.pam_auth_service) > 0: return 1 return -1 if check_password(password, data['password'], data['old_password']) > 0: return 1 return -1 # user doesn't exist. now we fail, instead of reserving user. if CFG.disallow_user_creation: raise rhnFault(2001) # now check the reserved table h = rhnSQL.prepare(""" select r.login, r.password from rhnUserReserved r where r.login_uc = upper(:p1) """) h.execute(p1=user) data = h.fetchone_dict() if data and data["login"]: # found already reserved if check_password(password, data["password"], None) > 0: return 1 return -2 validate_new_username(user) log_debug(3, "calling validate_new_password" ) validate_new_password(password) # this is not reserved either, register it if encrypted_password: # Encrypt the password, let the function pick the salt password = encrypt_password(password) h = rhnSQL.prepare(""" insert into rhnUserReserved (login, password) values (:username, :password) """) h.execute(username=user, password=password) rhnSQL.commit() # all should be dandy return 0
def schedule_virt_guest_pkg_install(server_id, action_id, dry_run=0): """ ShadowAction that schedules a package installation action for the rhn-virtualization-guest package. """ log_debug(3) virt_host_package_name = "rhn-virtualization-guest" tools_channel = SubscribedChannel(server_id, "rhn-tools") found_tools_channel = tools_channel.is_subscribed_to_channel() if not found_tools_channel: raise InvalidAction("System not subscribed to the RHN Tools channel.") rhn_v12n_package = ChannelPackage(server_id, virt_host_package_name) if not rhn_v12n_package.exists(): raise InvalidAction("Could not find the rhn-virtualization-guest package.") try: install_scheduler = PackageInstallScheduler(server_id, action_id, rhn_v12n_package) if (not dry_run): install_scheduler.schedule_package_install() else: log_debug(4, "dry run requested") except NoActionInfo, nai: raise InvalidAction(str(nai))
def validate_new_password(password): 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])
def _create_signature(self, jid, action): row = lookup_client_by_jid(jid) if not row: log_debug(3, 'no client found for jid', jid) if self.debug_level > 5: raise Exception(1) return None full_jid = row['jabber_id'] shared_key = row['shared_key'] attrs = { 'timestamp' : int(time.time()), 'serial' : self.get_unique_id(), 'action' : action, 'jid' : self.jid, } signing_comps = ['timestamp', 'serial', 'action', 'jid'] args = [shared_key, full_jid] for sc in signing_comps: args.append(attrs[sc]) log_debug(4, "Signature args", args) attrs['signature'] = apply(jabber_lib.sign, args) x = jabber_lib.jabber.xmlstream.Node('x') x.setNamespace(jabber_lib.NS_RHN_SIGNED) for k, v in attrs.items(): x.putAttr(k, v) return x
def dump_channels(self, channel_labels=None, start_date=None, end_date=None): log_debug(2) #channels = self._validate_channels(channel_labels=channel_labels) self._write_dump(ChannelsDumper, channels=channel_labels, start_date=start_date, end_date=end_date) return 0
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 lookupChannel(self, name, username, password): log_debug(3) authobj = self._auth(username, password) authobj.isChannelAdmin() row = rhnSQL.fetchone_dict("select * from rhnChannel where label = :label", label=name) if row: row.update(self._insert_channel_family(row['id'])) row['last_modified'] = str(row['last_modified']) row['modified'] = str(row['modified']) row['created'] = str(row['created']) return removeNone(row) # Look the channel up by id try: name = int(name) except ValueError: return '' row = rhnSQL.fetchone_dict("select * from rhnChannel where id = :channel_id", channel_id = name) if row: row.update(self._insert_channel_family(row['id'])) return removeNone(row) return ''