# -*- coding: utf-8 -*- """ @author: Fabio Erculiani @contact: lxnay@sabayon.org @copyright: Fabio Erculiani @license: GPL-2 B{Entropy Package Manager Client}. """ from entropy.const import etpConst from entropy.output import red, darkred, blue, brown, darkgreen, darkblue, \ bold, purple, green, print_error, print_warning, print_info from entropy.i18n import _ import entropy.tools def security(options): rc = 0 if not options: return -10 only_affected = False only_unaffected = False fetch = False for opt in options: if opt == "--affected": only_affected = True elif opt == "--unaffected": only_unaffected = True elif opt == "--fetch": fetch = True from entropy.client.interfaces import Client entropy_client = Client() try: if options[0] == "update": security_intf = entropy_client.Security() er_txt = darkred(_("You must be either root or in this group:")) + \ " " + etpConst['sysgroup'] if not entropy.tools.is_user_in_entropy_group(): print_error(er_txt) return 1 rc = security_intf.fetch_advisories() elif options[0] == "list": security_intf = entropy_client.Security() rc = list_advisories(security_intf, only_affected = only_affected, only_unaffected = only_unaffected) elif options[0] == "install": security_intf = entropy_client.Security() rc = install_packages(entropy_client, security_intf, fetch = fetch) elif options[0] == "info": security_intf = entropy_client.Security() rc = show_advisories_info(security_intf, options[1:]) else: rc = -10 finally: entropy_client.destroy() return rc def show_advisories_info(security_intf, advisories): if not advisories: print_error(brown(" :: ")+darkgreen("%s." % ( _("No advisories provided"),))) return 1 adv_metadata = security_intf.get_advisories_metadata() for advisory in advisories: if advisory not in adv_metadata: print_warning(brown(" :: ") + darkred("%s " % (_("Advisory"),)) + \ blue(advisory) + darkred(" %s." % (_("does not exist"),))) continue print_advisory_information(adv_metadata[advisory], key = advisory) return 0 def print_advisory_information(advisory_data, key): # print advisory code print_info(blue(" @@ ")+red("%s " % (_("GLSA Identifier"),))+bold(key) + \ red(" | ")+blue(advisory_data['url'])) # title print_info("\t"+darkgreen("%s:\t\t" % (_("Title"),)) + \ darkred(advisory_data['title'])) # description description = advisory_data['description'].split("\n") desc_text = "\t"+darkgreen("%s:\t" % (_("Description"),) ) for x in description: print_info(desc_text+x.strip()) desc_text = "\t\t\t" for item in advisory_data['description_items']: desc_text = "\t\t\t %s " % (darkred("(*)"),) count = 8 mystr = [] for word in item.split(): count -= 1 mystr.append(word) if count < 1: print_info(desc_text+' '.join(mystr)) desc_text = "\t\t\t " mystr = [] count = 8 if count < 8: print_info(desc_text+' '.join(mystr)) # background if advisory_data['background']: background = advisory_data['background'].split("\n") bg_text = "\t"+darkgreen("%s:\t" % (_("Background"),)) for x in background: print_info(bg_text+purple(x.strip())) bg_text = "\t\t\t" # access if advisory_data['access']: print_info("\t"+darkgreen("%s:\t" % (_("Exploitable"),)) + \ bold(advisory_data['access'])) # impact if advisory_data['impact']: impact = advisory_data['impact'].split("\n") imp_text = "\t"+darkgreen("%s:\t\t" % (_("Impact"),)) for x in impact: print_info(imp_text+brown(x.strip())) imp_text = "\t\t\t" # impact type if advisory_data['impacttype']: print_info("\t"+darkgreen("%s:\t" % (_("Impact type"),)) + \ bold(advisory_data['impacttype'])) # revised if advisory_data['revised']: print_info("\t"+darkgreen("%s:\t" % (_("Revised"),)) + \ brown(advisory_data['revised'])) # announced if advisory_data['announced']: print_info("\t"+darkgreen("%s:\t" % (_("Announced"),)) + \ brown(advisory_data['announced'])) # synopsis synopsis = advisory_data['synopsis'].split("\n") syn_text = "\t"+darkgreen("%s:\t" % (_("Synopsis"),)) for x in synopsis: print_info(syn_text+x.strip()) syn_text = "\t\t\t" # references if advisory_data['references']: print_info("\t"+darkgreen("%s:" % (_("References"),))) for reference in advisory_data['references']: print_info("\t\t\t"+darkblue(reference)) # gentoo bugs if advisory_data['bugs']: print_info("\t"+darkgreen("%s:" % (_("Upstream bugs"),))) for bug in advisory_data['bugs']: print_info("\t\t\t"+darkblue(bug)) # affected if advisory_data['affected']: print_info("\t"+darkgreen("%s:" % (_("Affected"),))) for key in advisory_data['affected']: print_info("\t\t\t"+darkred(key)) affected_data = advisory_data['affected'][key][0] vul_vers = affected_data['vul_vers'] unaff_vers = affected_data['unaff_vers'] if vul_vers: print_info("\t\t\t "+brown("%s: " % ( _("vulnerable versions"),))+", ".join(vul_vers)) if unaff_vers: print_info("\t\t\t "+brown("%s: " % ( _("unaffected versions"),))+", ".join(unaff_vers)) # workaround if advisory_data['workaround']: print_info("\t"+darkgreen("%s:\t" % (_("Workaround"),)) + \ darkred(advisory_data['workaround'])) # resolution if advisory_data['resolution']: res_text = "\t"+darkgreen("%s:\t" % (_("Resolution"),)) resolutions = advisory_data['resolution'] for resolution in resolutions: for x in resolution.split("\n"): print_info(res_text+x.strip()) res_text = "\t\t\t" def list_advisories(security_intf, only_affected = False, only_unaffected = False): if (not only_affected and not only_unaffected) or \ (only_affected and only_unaffected): adv_metadata = security_intf.get_advisories_metadata() elif only_affected: adv_metadata = security_intf.get_vulnerabilities() else: adv_metadata = security_intf.get_fixed_vulnerabilities() if not adv_metadata: print_info(brown(" :: ")+darkgreen("%s." % ( _("No advisories available or applicable"),))) return 0 adv_keys = sorted(adv_metadata.keys()) for key in adv_keys: affected = security_intf.is_affected(key) if only_affected and not affected: continue if only_unaffected and affected: continue if affected: affection_string = red("A") else: affection_string = green("N") if adv_metadata[key]['affected']: affected_data = list(adv_metadata[key]['affected'].keys()) if affected_data: for a_key in affected_data: k_data = adv_metadata[key]['affected'][a_key] vulnerables = ', '.join(k_data[0]['vul_vers']) description = "[GLSA:%s:%s][%s] %s: %s" % ( darkgreen(key), affection_string, brown(vulnerables), darkred(a_key), blue(adv_metadata[key]['title'])) print_info(description) return 0 def install_packages(entropy_client, security_intf, fetch = False): import text_ui print_info(red(" @@ ")+blue("%s..." % (_("Calculating security updates"),))) affected_atoms = security_intf.get_affected_atoms() # match in client database valid_matches = set() for atom in affected_atoms: match = entropy_client.clientDbconn.atomMatch(atom) if match[0] == -1: continue # get key + slot key, slot = entropy_client.clientDbconn.retrieveKeySlot(match[0]) # match in repos match = entropy_client.atom_match(key, matchSlot = slot) if match[0] != -1: valid_matches.add(match) if not valid_matches: print_info(red(" @@ ")+blue("%s." % ( _("All the available updates have been already installed"),))) return 0 rc, stat = text_ui.install_packages(atomsdata = valid_matches, onlyfetch = fetch) return rc