def add_file(self, ks_file): h = rhnSQL.prepare("alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS'") h.execute() log_debug(3, 'trying to insert ' + str(self.id) + ' , ' + ks_file['relative_path'] + \ ' , ' + str(ks_file['checksum_type']) + ':' ' , ' + str(ks_file['checksum']) + ' , ' + str(ks_file['file_size']) + \ ' , ' + ks_file['last_modified']) insert_file_q = rhnSQL.prepare(""" insert into rhnKSTreeFile (kstree_id, relative_filename, checksum_id, file_size, last_modified) values (:kstree_id, :relative_filename, lookup_checksum(:checksum_type, :checksum), :file_size, :last_modified) """) insert_file_q.execute(kstree_id = self.id, relative_filename = ks_file['relative_path'], checksum_type = ks_file['checksum_type'], checksum = ks_file['checksum'], file_size = ks_file['file_size'], last_modified = ks_file['last_modified']) update_channel = rhnSQL.Procedure('rhn_channel.update_channel') invalidate_ss = 0 update_channel(self.channel_id, invalidate_ss)
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 __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
def check_password(self, password): """ simple check for a password that might become more complex sometime """ good_pwd = str(self.contact["password"]) old_pwd = str(self.contact["old_password"]) if CFG.pam_auth_service: # a PAM service is defined # We have to check the user's rhnUserInfo.use_pam_authentication # XXX Should we create yet another __init_blah function? # since it's the first time we had to lool at rhnUserInfo, # I'll assume it's not something to happen very frequently, # so I'll use a query for now # - misa # h = rhnSQL.prepare(""" select ui.use_pam_authentication from web_contact w, rhnUserInfo ui where w.login_uc = UPPER(:login) and w.id = ui.user_id""") h.execute(login=self.contact["login"]) data = h.fetchone_dict() if not data: # This should not happen raise rhnException("No entry found for user %s" % self.contact["login"]) if data['use_pam_authentication'] == 'Y': # use PAM import rhnAuthPAM return rhnAuthPAM.check_password(self.contact["login"], password, CFG.pam_auth_service) # If the entry in rhnUserInfo is 'N', perform regular # authentication return check_password(password, good_pwd, old_pwd)
def solve_dependencies(server_id, deps, version, nvre=None): """ The unchanged version of solve_dependencies. IN: server_id := id info of the server deps := list of filenames that are needed by the caller version := version of the client OUT: Dictionary with key values being the filnames in deps and the values being a list of lists of package info. Example := {'filename1' : [['name', 'version', 'release', 'epoch'], ['name2', 'version2', 'release2', 'epoch2']]} """ if not nvre: # list of the keys to the values in each row of the recordset. nvre = ['name', 'version', 'release', 'epoch'] # first, uniquify deps deplist = set(deps) # SQL statement. It is a union of 3 statements: # - Lookup by package name # - Lookup by provides # - Lookup by file name statement = "%s UNION ALL %s UNION ALL %s" % ( __packages_sql, __provides_sql, __files_sql) h = rhnSQL.prepare(statement) # prepare return value packages = {} # Iterate through the dependency problems for dep in deplist: dict = {} h.execute(server_id=server_id, dep=dep) rs = h.fetchall_dict() or [] if not rs: # test shortcut log_error("Unable to solve dependency", server_id, dep) packages[dep] = [] continue for p in rs: if p['epoch'] is None: p['epoch'] = "" entry = [] list(map(lambda f, e=entry, p=p: e.append(p[f]), nvre)) name_key = entry[0] if name_key in dict and dict[name_key][1] < p['preference']: # Already have it with a lower preference continue # The first time we see this package. dict[name_key] = (entry, p['preference']) packages[dep] = _avoid_compat_packages(dict) # v2 clients are done if version > 1: return packages else: return _v2packages_to_v1list(packages, deplist)
def clear_files(self): clear_files_q = rhnSQL.prepare(""" delete from rhnKSTreeFile where kstree_id = :kstree_id """) clear_files_q.execute(kstree_id = self.id)
def solve_dependencies(server_id, deps, version, nvre=None): """ The unchanged version of solve_dependencies. IN: server_id := id info of the server deps := list of filenames that are needed by the caller version := version of the client OUT: Dictionary with key values being the filnames in deps and the values being a list of lists of package info. Example := {'filename1' : [['name', 'version', 'release', 'epoch'], ['name2', 'version2', 'release2', 'epoch2']]} """ if not nvre: # list of the keys to the values in each row of the recordset. nvre = ['name', 'version', 'release', 'epoch'] # first, uniquify deps deplist = set(deps) # SQL statement. It is a union of 3 statements: # - Lookup by package name # - Lookup by provides # - Lookup by file name statement = "%s UNION ALL %s UNION ALL %s" % (__packages_sql, __provides_sql, __files_sql) h = rhnSQL.prepare(statement) # prepare return value packages = {} # Iterate through the dependency problems for dep in deplist: dict = {} h.execute(server_id=server_id, dep=dep) rs = h.fetchall_dict() or [] if not rs: # test shortcut log_error("Unable to solve dependency", server_id, dep) packages[dep] = [] continue for p in rs: if p['epoch'] is None: p['epoch'] = "" entry = [] list(map(lambda f, e=entry, p=p: e.append(p[f]), nvre)) name_key = entry[0] if name_key in dict and dict[name_key][1] < p['preference']: # Already have it with a lower preference continue # The first time we see this package. dict[name_key] = (entry, p['preference']) packages[dep] = _avoid_compat_packages(dict) # v2 clients are done if version > 1: return packages else: return _v2packages_to_v1list(packages, deplist)
def lookup_tree(ks_label, pkgs): ks_label_query = rhnSQL.prepare (""" SELECT KT.id, KT.label, KT.base_path, KT.channel_id, KT.boot_image, KT.org_id, KTT.id AS TREE_TYPE, KTT.label AS TREE_TYPE_LABEL, KTT.name AS TREE_TYPE_NAME, KIT.id AS install_type, KIT.label AS install_type_label, KIT.name AS install_type_name, C.channel_arch_id, CA.label AS CHANNEL_ARCH_LABEL, CA.name AS CHANNEL_ARCH_NAME FROM rhnKSTreeType KTT, rhnKSInstallType KIT, rhnChannel C, rhnChannelArch CA, rhnKickstartableTree KT WHERE KT.label = :ks_label AND KTT.id = KT.kstree_type AND KIT.id = KT.install_type AND C.id = KT.channel_id AND CA.id = C.channel_arch_id """) ks_label_query.execute(ks_label = ks_label) ks_row = ks_label_query.fetchone_dict() if ks_row: kickstart = Kickstart(ks_row, pkgs) return kickstart else: return None
def create_tree(ks_label, channel_label, path, boot_image, kstree_type, install_type, pkgs): channel = rhnChannel.channel_info(channel_label) if channel is '': raise rhnFault(40, 'Could not lookup channel ' + channel_label) channel_id = channel['id'] create_ks_query = rhnSQL.prepare(""" insert into rhnKickstartableTree ( id, org_id, label, base_path, channel_id, boot_image, kstree_type, install_type) values ( sequence_nextval('rhn_kstree_id_seq'), :org_id, :label, :base_path, :channel_id, :boot_image, (select id from rhnKSTreeType where label = :kstree_type), (select id from rhnKSInstallType where label = :install_type)) """) create_ks_query.execute(org_id = None, label = ks_label, base_path = path, channel_id = channel_id, boot_image = boot_image, kstree_type = kstree_type, install_type = install_type) return lookup_tree(ks_label, pkgs)
def load(self, session): arr = string.split(session, "x", 1) if len(arr) != 2: raise InvalidSessionError("Invalid session string") digest = arr[1] if len(digest) != 64: raise InvalidSessionError("Invalid session string (wrong length)") try: self.session_id = int(arr[0]) except ValueError: raise_with_tb(InvalidSessionError("Invalid session identifier"), sys.exc_info()[2]) if digest != self.digest(): raise InvalidSessionError("Bad session checksum") h = rhnSQL.prepare( """ select web_user_id, expires, value from pxtSessions where id = :session_id """ ) h.execute(session_id=self.session_id) row = h.fetchone_dict() if row: # Session is stored in the DB if time.time() < row["expires"]: # And it's not expired yet - good to go self.expires = row["expires"] self.uid = row["web_user_id"] return self # Old session - clean it up h = rhnSQL.prepare( """ delete from pxtSessions where id = :session_id """ ) h.execute(session_id=self.session_id) rhnSQL.commit() raise ExpiredSessionError("Session not found")
def __single_query_with_arch_and_id(server_id, deps, query): """ Run one of the queries and return the results along with the arch. """ ret = {} h = rhnSQL.prepare(query) for dep in deps: h.execute(server_id=server_id, dep=dep) data = h.fetchall() or [] ret[dep] = [a[:6] for a in data] return ret
def load(self, session): arr = string.split(session, 'x', 1) if len(arr) != 2: raise InvalidSessionError("Invalid session string") digest = arr[1] if len(digest) != 64: raise InvalidSessionError("Invalid session string (wrong length)") try: self.session_id = int(arr[0]) except ValueError: raise_with_tb(InvalidSessionError("Invalid session identifier"), sys.exc_info()[2]) if digest != self.digest(): raise InvalidSessionError("Bad session checksum") h = rhnSQL.prepare(""" select web_user_id, expires, value from pxtSessions where id = :session_id """) h.execute(session_id=self.session_id) row = h.fetchone_dict() if row: # Session is stored in the DB if time.time() < row['expires']: # And it's not expired yet - good to go self.expires = row['expires'] self.uid = row['web_user_id'] return self # Old session - clean it up h = rhnSQL.prepare(""" delete from pxtSessions where id = :session_id """) h.execute(session_id=self.session_id) rhnSQL.commit() raise ExpiredSessionError("Session not found")
def save(self): expires = int(time.time()) + self.duration h = rhnSQL.prepare(""" insert into PXTSessions (id, web_user_id, expires, value) values (:id, :web_user_id, :expires, :value) """) h.execute(id=self.session_id, web_user_id=self.uid, expires=expires, value='RHNAPP') rhnSQL.commit() return self
def get_user_id(username): username = str(username) h = rhnSQL.prepare(""" select w.id from web_contact w where w.login_uc = upper(:username) """) h.execute(username=username) data = h.fetchone_dict() if data: return data["id"] return None
def get_user_id(username): """ search for an userid """ username = str(username) h = rhnSQL.prepare(""" select w.id from web_contact w where w.login_uc = upper(:username) """) h.execute(username=username) data = h.fetchone_dict() if data: return data["id"] return None
def is_user_disabled(user): log_debug(3, user) username = str(user) h = rhnSQL.prepare(""" select 1 from rhnWebContactDisabled where login_uc = upper(:username) """) h.execute(username=username) row = h.fetchone_dict() if row: return 1 return 0
def delete_tree(self): delete_query = rhnSQL.prepare(""" delete from rhnKickstartableTree where id = :id """) delete_query.execute(id = self.id) update_channel = rhnSQL.Procedure('rhn_channel.update_channel') invalidate_ss = 0 update_channel(self.channel_id, invalidate_ss)
def is_user_read_only(user): log_debug(3, user) username = str(user) h = rhnSQL.prepare(""" select 1 from web_contact where login_uc = upper(:username) and read_only = 'Y' """) h.execute(username=username) row = h.fetchone_dict() if row: return 1 return 0
def get_roles(self): user_id = self.getid() h = rhnSQL.prepare(""" select ugt.label as role from rhnUserGroup ug, rhnUserGroupType ugt, 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) return map(lambda x: x['role'], h.fetchall_dict() or [])
def handler(self, req): """ main Apache handler """ log_debug(2) ret = apacheSession.handler(self, req) if ret != apache.OK: return ret if not CFG.SEND_MESSAGE_TO_ALL: # Need to get any string template overrides here, before any app # code gets executed, as the rhnFault error messages use the # templates # If send_message_to_all, we don't have DB connectivity though h = rhnSQL.prepare("select label, value from rhnTemplateString") h.execute() templateStrings = {} while 1: row = h.fetchone_dict() if not row: break templateStrings[row['label']] = row['value'] if templateStrings: rhnFlags.set('templateOverrides', templateStrings) log_debug(4, "template strings: %s" % templateStrings) if not CFG.SECRET_KEY: # Secret key not defined, complain loudly try: raise rhnException("Secret key not found!") except: rhnTB.Traceback(mail=1, req=req, severity="schema") req.status = 500 req.send_http_header() return apache.OK # Try to authenticate the proxy if it this request passed # through a proxy. if self.proxyVersion: try: ret = self._req_processor.auth_proxy() except rhnFault, f: return self._req_processor.response(f.getxml())
def _get_files(self, tree_id): files_query = rhnSQL.prepare(""" SELECT relative_filename, file_size, c.checksum_type, c.checksum, TO_CHAR(last_modified, 'YYYY-MM-DD HH24:MI:SS') AS LAST_MODIFIED FROM rhnKSTreeFile, rhnChecksumViev c WHERE kstree_id = :tree_id AND checksum_id = c.id """) files_query.execute(tree_id = tree_id) file_list = files_query.fetchall_dict() if file_list: return file_list else: return []
def check_password(self, password, allow_read_only=False): """ simple check for a password that might become more complex sometime """ if not allow_read_only and is_user_read_only(self.contact["login"]): raise rhnFault(702) good_pwd = str(self.contact["password"]) if CFG.pam_auth_service: # a PAM service is defined # We have to check the user's rhnUserInfo.use_pam_authentication # XXX Should we create yet another __init_blah function? # since it's the first time we had to lool at rhnUserInfo, # I'll assume it's not something to happen very frequently, # so I'll use a query for now # - misa # h = rhnSQL.prepare(""" select ui.use_pam_authentication from web_contact w, rhnUserInfo ui where w.login_uc = UPPER(:login) and w.id = ui.user_id""") h.execute(login=self.contact["login"]) data = h.fetchone_dict() if not data: # This should not happen raise rhnException("No entry found for user %s" % self.contact["login"]) if data['use_pam_authentication'] == 'Y': # use PAM import rhnAuthPAM return rhnAuthPAM.check_password(self.contact["login"], password, CFG.pam_auth_service) # If the entry in rhnUserInfo is 'N', perform regular authentication ret = check_password(password, good_pwd) if ret and CFG.encrypted_passwords and self.contact['password'].find( '$1$') == 0: # If successfully authenticated and the current password is # MD5 encoded, convert the password to SHA-256 and save it in the DB. self.contact['password'] = encrypt_password(password) self.contact.save() rhnSQL.commit() return ret
def get_db_client_capabilities(server_id): h = rhnSQL.prepare(""" select cc.capability_name_id, ccn.name capability, cc.version from rhnClientCapability cc, rhnClientCapabilityName ccn where cc.server_id = :server_id and cc.capability_name_id = ccn.id """) h.execute(server_id=server_id) ret = {} while 1: row = h.fetchone_dict() if not row: break name = row['capability'] version = row['version'] value = None ret[name] = { 'version' : version, 'value' : value, } return ret
def check_password(self, password, allow_read_only=False): """ simple check for a password that might become more complex sometime """ if not allow_read_only and is_user_read_only(self.contact["login"]): raise rhnFault(702) good_pwd = str(self.contact["password"]) if CFG.pam_auth_service: # a PAM service is defined # We have to check the user's rhnUserInfo.use_pam_authentication # XXX Should we create yet another __init_blah function? # since it's the first time we had to lool at rhnUserInfo, # I'll assume it's not something to happen very frequently, # so I'll use a query for now # - misa # h = rhnSQL.prepare( """ select ui.use_pam_authentication from web_contact w, rhnUserInfo ui where w.login_uc = UPPER(:login) and w.id = ui.user_id""" ) h.execute(login=self.contact["login"]) data = h.fetchone_dict() if not data: # This should not happen raise rhnException("No entry found for user %s" % self.contact["login"]) if data["use_pam_authentication"] == "Y": # use PAM import rhnAuthPAM return rhnAuthPAM.check_password(self.contact["login"], password, CFG.pam_auth_service) # If the entry in rhnUserInfo is 'N', perform regular authentication ret = check_password(password, good_pwd) if ret and CFG.encrypted_passwords and self.contact["password"].find("$1$") == 0: # If successfully authenticated and the current password is # MD5 encoded, convert the password to SHA-256 and save it in the DB. self.contact["password"] = encrypt_password(password) self.contact.save() rhnSQL.commit() return ret
def __save(self): is_admin = 0 if self.customer.real: # get the org_id and the applicant group id for this org org_id = self.customer["id"] h = rhnSQL.prepare(""" select ug.id from rhnUserGroup ug, rhnUserGroupType ugt where ugt.label = 'org_applicant' and ug.group_type = ugt.id and ug.org_id = :org_id """) h.execute(org_id=org_id) data = h.fetchone_dict() # XXX: prone to errors, but we'll need to see them first grp_id = data["id"] else: # an org does not exist... create one create_new_org = rhnSQL.Procedure("create_new_org") ret = create_new_org( self.customer["name"], self.customer["password"], None, None, "B", rhnSQL.types.NUMBER(), rhnSQL.types.NUMBER(), rhnSQL.types.NUMBER(), ) org_id, adm_grp_id, app_grp_id = ret[-3:] # We want to make sure we set the group limits right tbl = rhnSQL.Row("rhnUserGroup", "id") # Set the default admin limits to Null tbl.load(adm_grp_id) # bz:210230: this value should default to Null tbl.save() # Set the default applicats limit to 0 tbl.load(app_grp_id) tbl["max_members"] = 0 tbl.save() # reload the customer table self.customer.load(org_id) # and finally, we put this one in the admin group grp_id = adm_grp_id is_admin = 1 # save the contact if self.contact.real: if not self.contact["org_id"]: raise rhnException("Undefined org_id for existing user entry", self.contact.data) userid = self.contact["id"] self.contact.save() else: userid = self.getid() self.contact["org_id"] = org_id # if not admin, obfuscate the password # (and leave the old_password set) if not is_admin: # we only do this for new users. log_debug(5, "Obfuscating user password") user_pwd = self.contact["password"] crypt_pwd = crypt.crypt(user_pwd, str(userid)[-2:]) self.contact["password"] = crypt_pwd self.contact.create(userid) # rhnUserInfo h = rhnSQL.prepare("insert into rhnUserInfo (user_id) " "values (:user_id)") h.execute(user_id=userid) # now add this user to the admin/applicant group for his org create_ugm = rhnSQL.Procedure("rhn_user.add_to_usergroup") # grp_id is the admin or the applicant, depending on whether we # just created the org or not create_ugm(userid, grp_id) # and now reload this data self.contact.load(userid) # do the same for the other structures indexed by web_user_id # personal info if self.info.real: self.info.save() else: self.info.create(userid) # contact permissions if self.perms.real: self.perms.save() else: self.perms.create(userid) # And now save the site information if self.site.real: siteid = self.site["id"] self.site.save() else: siteid = rhnSQL.Sequence("web_user_site_info_id_seq")() self.site["web_user_id"] = userid self.site.create(siteid) return 0
def solve_dependencies_with_limits(server_id, deps, version, all=0, limit_operator=None, limit=None): """ This version of solve_dependencies allows the caller to get all of the packages that solve a dependency and limit the packages that are returned to those that match the criteria defined by limit_operator and limit. This version of the function also returns the architecture label of the package[s] that get returned. limit_operator can be any of: '<', '<=', '==', '>=', or '>'. limit is a a string of the format [epoch:]name-version-release deps is a list of filenames that the packages that are returned must provide. version is the version of the client that is calling the function. Indexes for the tuple entry_index = 0 preference_index = 1 Indexes for the list of package fields. name_index = 0 version_index = 1 release_index = 2 epoch_index = 3 """ # Containers used while the packages get categorized, sorted, and filtered. packages_all = {} package_list = [] # List of fields in a package. Corresponds to the keys for the dictionary that holds the package information. nvre = ['name', 'version', 'release', 'epoch', 'arch'] # Make sure there are no duplicate dependencies. deplist = set(deps) statement = "%s UNION ALL %s UNION ALL %s" % ( __packages_all_sql, __provides_all_sql, __files_all_sql) h = rhnSQL.prepare(statement) # prepare return value packages = {} for dep in deplist: dict = {} # Retrieve the package information from the database. h.execute(server_id=server_id, dep=dep) # Get a list of dictionaries containing row data. rs = h.fetchall_dict() or [] # rs = [{},{},... ] # Each package gets a list that may contain multiple versions of a package for record in rs: if record['name'] in packages_all: packages_all[record['name']].append(record) else: packages_all[record['name']] = [record] # sort all the package lists so the most recent version is first for pl in packages_all.keys(): packages_all[pl].sort(cmp_evr) package_list = package_list + packages_all[pl] package_list.reverse() # Use the limit* parameters to filter out packages you don't want. if limit_operator is not None and limit is not None: keep_list = [] try: limit = rhnLib.make_evr(limit) except: raise for package in package_list: try: keep = test_evr(package, limit_operator, limit) except: raise if keep: keep_list.append(package) package_list = keep_list list_of_tuples = [] for p in package_list: if p['epoch'] is None: p['epoch'] = "" entry = [] list(map(lambda f, e=entry, p=p: e.append(p[f]), nvre)) # Added for readability name_key = entry[0] if all == 0: # NOTE: Remember that the values in dict are tuples that look like (entry, preference). # NOTE, Part Deux: the '<=' was a '<' originally. I changed it because if two packages # with the same preference but different versions came through, the second package was being used. # The changes I made above make it so that at this point the packages are sorted from highest nvre # to lowest nvre. Selecting the second package was causing the earlier package to be # returned, which is bad. if name_key in dict and dict[name_key][1] <= p['preference']: # Already have it with a lower preference continue # The first time we see this package. dict[name_key] = (entry, p['preference']) else: name_key = entry[0] newtuple = (entry, p['preference']) list_of_tuples.append(newtuple) if all == 0: packages[dep] = _avoid_compat_packages(dict) else: # filter out compats if len(list_of_tuples) > 1: filterstring = "compat-" len_filter = len(filterstring) tup_keep = [] for tup in list_of_tuples: if tup[0][0][:len_filter] != filterstring: tup_keep.append(tup) list_of_tuples = tup_keep list_of_tuples.sort(lambda a, b: cmp(a[1], b[1])) packages[dep] = [x[0] for x in list_of_tuples] # v2 clients are done if version > 1: return packages else: return _v2packages_to_v1list(packages, deplist, all)
def handler(self, req): """ main Apache handler """ log_debug(2) ret = apacheSession.handler(self, req) if ret != apache.OK: return ret if not CFG.SEND_MESSAGE_TO_ALL: # Need to get any string template overrides here, before any app # code gets executed, as the rhnFault error messages use the # templates # If send_message_to_all, we don't have DB connectivity though h = rhnSQL.prepare("select label, value from rhnTemplateString") h.execute() templateStrings = {} while 1: row = h.fetchone_dict() if not row: break templateStrings[row['label']] = row['value'] if templateStrings: rhnFlags.set('templateOverrides', templateStrings) log_debug(4, "template strings: %s" % templateStrings) if not CFG.SECRET_KEY: # Secret key not defined, complain loudly try: raise rhnException("Secret key not found!") except: rhnTB.Traceback(mail=1, req=req, severity="schema") req.status = 500 req.send_http_header() return apache.OK # Try to authenticate the proxy if it this request passed # through a proxy. if self.proxyVersion: try: ret = self._req_processor.auth_proxy() except rhnFault: f = sys.exc_info()[1] return self._req_processor.response(f.getxml()) # Decide what to do with the request: try to authenticate the client. # NOTE: only upon GET requests is there Signature information to # authenticate. XMLRPC requests DO NOT use signature # authentication. if req.method == "GET": try: ret = self._req_processor.auth_client() except rhnFault: f = sys.exc_info()[1] return self._req_processor.response(f.getxml()) # be safe rather than sorry if not ret: log_error("Got a GET call, but auth_client declined", req.path_info) return apache.HTTP_METHOD_NOT_ALLOWED # Avoid leaving Oracle deadlocks try: ret = self._req_processor.process() rhnSQL.rollback() except: if not CFG.SEND_MESSAGE_TO_ALL: rhnSQL.rollback() raise log_debug(4, "Leave with return value", ret) return ret
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, w.old_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, password old_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"], data["old_password"]) == 0: # Bad password raise rhnFault(2) # From this point on, the password may be encrypted if encrypted_password: password = encrypt_password(password) is_real = 0 # the password matches, do we need to create a new entry? if not data.has_key("id"): user = User(username, password) else: # we have to reload this entry into a User structure user = User(username, password) if not user.reload(data["id"]) == 0: # something horked during reloading entry from database # we can not really say that the entry does not exist... raise rhnFault(10) is_real = 1 # now we have user reloaded, check for updated email if email: # don't update the user's email address in the satellite context... # we *must* in the live context, but user creation through up2date --register # is disallowed in the satellite context anyway... if not pre_existing_user: user.set_info("email", email) # XXX This should go away eventually if org_id and org_password: # check out this org h = rhnSQL.prepare(""" select id, password from web_customer where id = :org_id """) h.execute(org_id=str(org_id)) data = h.fetchone_dict() if not data: # wrong organization raise rhnFault(2, _("Invalid Organization Credentials")) # The org password is not encrypted, easy comparison if string.lower(org_password) != string.lower(data["password"]): # Invalid org password raise rhnFault(2, _("Invalid Organization Credentials")) if is_real: # this is a real entry, don't clobber the org_id old_org_id = user.contact["org_id"] new_org_id = data["id"] if old_org_id != new_org_id: raise rhnFault(42, _("User `%s' not a member of organization %s") % (username, org_id)) else: # new user, set its org user.set_org_id(data["id"]) # force the save if this is a new entry ret = user.save() if not ret == 0: raise rhnFault(5) # check if we need to remove the reservation if not data.has_key("id"): # remove reservation h = rhnSQL.prepare(""" delete from rhnUserReserved where login_uc = upper(:username) """) h.execute(username=username) return 0
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.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']) > 0: return 1 return -1 # user doesn't exist. now we fail, instead of reserving user. if CFG.disallow_user_creation: raise rhnFault(2001) user, password = check_user_password(user, password) # 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"]) > 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 update_client_capabilities(server_id): caps = get_client_capabilities() if caps is None: caps = {} caps = caps.copy() h = rhnSQL.prepare( """ select cc.capability_name_id, ccn.name capability, cc.version from rhnClientCapability cc, rhnClientCapabilityName ccn where cc.server_id = :server_id and cc.capability_name_id = ccn.id """ ) updates = {"server_id": [], "capability_name_id": [], "version": []} deletes = {"server_id": [], "capability_name_id": []} inserts = {"server_id": [], "capability": [], "version": []} h.execute(server_id=server_id) while 1: row = h.fetchone_dict() if not row: break name = row["capability"] version = row["version"] capability_name_id = row["capability_name_id"] if caps.has_key(name): local_ver = caps[name]["version"] del caps[name] if local_ver == version: # Nothing to do - same version continue updates["server_id"].append(server_id) updates["capability_name_id"].append(capability_name_id) updates["version"].append(local_ver) continue # Have to delete it deletes["server_id"].append(server_id) deletes["capability_name_id"].append(capability_name_id) # Everything else has to be inserted for name, hash in caps.items(): inserts["server_id"].append(server_id) inserts["capability"].append(name) inserts["version"].append(hash["version"]) log_debug(5, "Deletes:", deletes) log_debug(5, "Updates:", updates) log_debug(5, "Inserts:", inserts) if deletes["server_id"]: h = rhnSQL.prepare( """ delete from rhnClientCapability where server_id = :server_id and capability_name_id = :capability_name_id """ ) h.executemany(**deletes) if updates["server_id"]: h = rhnSQL.prepare( """ update rhnClientCapability set version = :version where server_id = :server_id and capability_name_id = :capability_name_id """ ) h.executemany(**updates) if inserts["server_id"]: h = rhnSQL.prepare( """ insert into rhnClientCapability (server_id, capability_name_id, version) values (:server_id, LOOKUP_CLIENT_CAPABILITY(:capability), :version) """ ) h.executemany(**inserts) # Commit work. This can be dangerous if there is previously uncommited # work rhnSQL.commit()
def solve_dependencies_arch(server_id, deps, version): """ Does the same thing as solve_dependencies, but also returns the architecture label with the package info. IN: server_id := id info of the server deps := list of filenames that are needed by the caller version := version of the client OUT: Dictionary with key values being the filnames in deps and the values being a list of lists of package info. Example := {'filename1' : [['name', 'version', 'release', 'epoch', 'architecture'], ['name2', 'version2', 'release2', 'epoch2', 'architecture2']]} Indexes for the tuple stored as the value in dict entry_index = 0 preference_index = 1 indexes for the list nvre name_index = 0 version_index = 1 release_index = 2 epoch_index = 3 """ #list of the keys to the values in each row of the recordset. nvre = ['name', 'version', 'release', 'epoch', 'arch'] # first, uniquify deps deplist = [] for dep in deps: if dep not in deplist: deplist.append(dep) # SQL statement. It is a union of 3 statements: # - Lookup by package name # - Lookup by provides # - Lookup by file name statement = "%s UNION ALL %s UNION ALL %s" % ( __packages_sql, __provides_sql, __files_sql) h = rhnSQL.prepare(statement) # prepare return value packages = {} # Iterate through the dependency problems for dep in deplist: dict = {} #Each value will be a tuple like (list, preference) h.execute(server_id = server_id, dep = dep) rs = h.fetchall_dict() or [] if not rs: # test shortcut log_error("Unable to solve dependency", server_id, dep) packages[dep] = [] continue for p in rs: if p['epoch'] == None: p['epoch'] = "" entry = [] map(lambda f, e = entry, p = p: e.append(p[f]), nvre) #Exists for readability name_key = entry[0] if dict.has_key(name_key) and dict[name_key][1] < p['preference']: # Already have it with a lower preference continue # The first time we see this package. dict[name_key] = (entry, p['preference']) packages[dep] = _avoid_compat_packages(dict) # v2 clients are done if version > 1: return packages else: return _v2packages_to_v1list(packages, deplist)
def solve_dependencies_with_limits(server_id, deps, version, all=0, limit_operator=None, limit=None): """ This version of solve_dependencies allows the caller to get all of the packages that solve a dependency and limit the packages that are returned to those that match the criteria defined by limit_operator and limit. This version of the function also returns the architecture label of the package[s] that get returned. limit_operator can be any of: '<', '<=', '==', '>=', or '>'. limit is a a string of the format [epoch:]name-version-release deps is a list of filenames that the packages that are returned must provide. version is the version of the client that is calling the function. Indexes for the tuple entry_index = 0 preference_index = 1 Indexes for the list of package fields. name_index = 0 version_index = 1 release_index = 2 epoch_index = 3 """ # Containers used while the packages get categorized, sorted, and filtered. packages_all = {} package_list = [] # List of fields in a package. Corresponds to the keys for the dictionary that holds the package information. nvre = ['name', 'version', 'release', 'epoch', 'arch'] # Make sure there are no duplicate dependencies. deplist = set(deps) statement = "%s UNION ALL %s UNION ALL %s" % (__packages_all_sql, __provides_all_sql, __files_all_sql) h = rhnSQL.prepare(statement) # prepare return value packages = {} for dep in deplist: dict = {} # Retrieve the package information from the database. h.execute(server_id=server_id, dep=dep) # Get a list of dictionaries containing row data. rs = h.fetchall_dict() or [] # rs = [{},{},... ] # Each package gets a list that may contain multiple versions of a package for record in rs: if record['name'] in packages_all: packages_all[record['name']].append(record) else: packages_all[record['name']] = [record] # sort all the package lists so the most recent version is first for pl in packages_all.keys(): packages_all[pl].sort(cmp_evr) package_list = package_list + packages_all[pl] package_list.reverse() # Use the limit* parameters to filter out packages you don't want. if limit_operator is not None and limit is not None: keep_list = [] try: limit = rhnLib.make_evr(limit) except: raise for package in package_list: try: keep = test_evr(package, limit_operator, limit) except: raise if keep: keep_list.append(package) package_list = keep_list list_of_tuples = [] for p in package_list: if p['epoch'] is None: p['epoch'] = "" entry = [] list(map(lambda f, e=entry, p=p: e.append(p[f]), nvre)) # Added for readability name_key = entry[0] if all == 0: # NOTE: Remember that the values in dict are tuples that look like (entry, preference). # NOTE, Part Deux: the '<=' was a '<' originally. I changed it because if two packages # with the same preference but different versions came through, the second package was being used. # The changes I made above make it so that at this point the packages are sorted from highest nvre # to lowest nvre. Selecting the second package was causing the earlier package to be # returned, which is bad. if name_key in dict and dict[name_key][1] <= p['preference']: # Already have it with a lower preference continue # The first time we see this package. dict[name_key] = (entry, p['preference']) else: name_key = entry[0] newtuple = (entry, p['preference']) list_of_tuples.append(newtuple) if all == 0: packages[dep] = _avoid_compat_packages(dict) else: # filter out compats if len(list_of_tuples) > 1: filterstring = "compat-" len_filter = len(filterstring) tup_keep = [] for tup in list_of_tuples: if tup[0][0][:len_filter] != filterstring: tup_keep.append(tup) list_of_tuples = tup_keep list_of_tuples.sort(lambda a, b: cmp(a[1], b[1])) packages[dep] = [x[0] for x in list_of_tuples] # v2 clients are done if version > 1: return packages else: return _v2packages_to_v1list(packages, deplist, all)
def update_client_capabilities(server_id): caps = get_client_capabilities() if caps is None: caps = {} caps = caps.copy() h = rhnSQL.prepare(""" select cc.capability_name_id, ccn.name capability, cc.version from rhnClientCapability cc, rhnClientCapabilityName ccn where cc.server_id = :server_id and cc.capability_name_id = ccn.id """) updates = {'server_id': [], 'capability_name_id': [], 'version': []} deletes = {'server_id': [], 'capability_name_id': []} inserts = {'server_id': [], 'capability': [], 'version': []} h.execute(server_id=server_id) while 1: row = h.fetchone_dict() if not row: break name = row['capability'] version = row['version'] capability_name_id = row['capability_name_id'] if name in caps: local_ver = caps[name]['version'] del caps[name] if local_ver == version: # Nothing to do - same version continue updates['server_id'].append(server_id) updates['capability_name_id'].append(capability_name_id) updates['version'].append(local_ver) continue # Have to delete it deletes['server_id'].append(server_id) deletes['capability_name_id'].append(capability_name_id) # Everything else has to be inserted for name, hash in caps.items(): inserts['server_id'].append(server_id) inserts['capability'].append(name) inserts['version'].append(hash['version']) log_debug(5, "Deletes:", deletes) log_debug(5, "Updates:", updates) log_debug(5, "Inserts:", inserts) if deletes['server_id']: h = rhnSQL.prepare(""" delete from rhnClientCapability where server_id = :server_id and capability_name_id = :capability_name_id """) h.executemany(**deletes) if updates['server_id']: h = rhnSQL.prepare(""" update rhnClientCapability set version = :version where server_id = :server_id and capability_name_id = :capability_name_id """) h.executemany(**updates) if inserts['server_id']: h = rhnSQL.prepare(""" insert into rhnClientCapability (server_id, capability_name_id, version) values (:server_id, LOOKUP_CLIENT_CAPABILITY(:capability), :version) """) h.executemany(**inserts) # Commit work. This can be dangerous if there is previously uncommited # work rhnSQL.commit()