Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 20291 Details for
Bug 32803
GLSA updates
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
base class to handle GLSAs, contains the backend code
glsa.py (text/plain), 10.73 KB, created by
Marius Mauch (RETIRED)
on 2003-11-05 09:45:11 UTC
(
hide
)
Description:
base class to handle GLSAs, contains the backend code
Filename:
MIME Type:
Creator:
Marius Mauch (RETIRED)
Created:
2003-11-05 09:45:11 UTC
Size:
10.73 KB
patch
obsolete
># $Header: /home/cvsroot/gentoo-projects/gentoo-security/GLSA/user-tools/glsa.py,v 1.5 2003/11/04 23:00:35 genone Exp $ > ># This program is licensed under the GPL, version 2 > ># WARNING: this code is only tested by a few people and should NOT be used ># on production systems at this stage. There are possible security holes and probably ># bugs in this code. If you test it please report ANY success or failure to ># me (genone@gentoo.org). > ># This is the main class for GLSA support in portage. It's currently designed ># to interface with portage through emerge and portageq, this will be changed ># to internal portage versions over time. It's the backend code for the glsa-check.py ># tool, which will go into portage.py / emerge at some point. > ># The following planned features are currently on hold: ># - getting GLSAs from http/ftp servers (not really useful without the fixed ebuilds) ># - GPG signing/verification (until key policy is clear and reasons are outlined) > >__author__ = "Marius Mauch <genone@gentoo.org>" > >import os, sys, urllib > ># if you get a traceback on this with python-2.3 try to unmerge pyxml, worked here >import xml.dom.minidom > >sys.path += ["/usr/lib/portage/pym"] # to find portage.py > >from time import strftime, strptime >from string import split >from portage import pkgcmp > ># most/all of the commented code is for a "between" version range which is not ># implemented in portage yet, so this is a nasty hack I don't want to support, ># it was just a proof-of-concept thing. > ># This class encapsulates the <version> tag from the glsa.dtd >class version: > # package = cat/name of the package > # version = version part > # rangetype = equal | above | below | above_equal | below_equal > def __init__(self, package, version, rangetype): > self.package = package > self.rangetype = rangetype > #if rangetype == "between": > # self.version = split(version) > #else: > self.version = version > > # returns a textual represenation of this version > def getTextVersion(self): > #if self.rangetype == "between": > # return "between " + self.version[0] + " and " + self.version[1] > if self.rangetype == "equal": > prefix = "=" > elif self.rangetype == "below_equal": > prefix = "<=" > elif self.rangetype == "above_equal": > prefix = ">=" > elif self.rangetype == "below": > prefix = "<" > elif self.rangetype == "above": > prefix = ">" > else: > raise Exception("unknown range type: " + self.rangetype) > > return prefix + self.version > > # returns a representation of this version that can be passed to emerge > def getCliVersion(self): > rValue = self.getPortageVersion() > rValue = rValue.replace("<", "\<") > rValue = rValue.replace(">", "\>") > return rValue > > # returns a version string that can be passed to portage functions > def getPortageVersion(self): > #if self.rangetype == "between": > # return (self.package+"-"+self.version[0], "\<="+self.package+"-"+self.version[1]) > if self.rangetype == "equal": > prefix = "=" > elif self.rangetype == "below_equal": > prefix = "<=" > elif self.rangetype == "above_equal": > prefix = ">=" > elif self.rangetype == "below": > prefix = "<" > elif self.rangetype == "above": > prefix = ">" > else: > raise Exception("unknown range type: " + self.rangetype) > > return prefix + self.package + "-" + self.version > > ># read config file and provide default config >def getconfig(configfile): > rValue = dict([ > ("GLSA_DIR", "/usr/portage/glsa/"), > ("GLSA_PREFIX", "glsa-"), > ("GLSA_SUFFIX", ".xml"), > ("CHECKFILE", "/var/cache/edb/glsa"), > ("GLSA_SERVER", "www.gentoo.org/security/en/glsa/"), # not completely implemented yet > ("CHECKMODE", "local") # not completely implemented yet > ]) > if not os.access(configfile, os.R_OK): > return rValue > filecontent = [line for line in open(configfile).readlines() if line[1] != '#'] > for line in filecontent: > if '=' in line: > name, value = line.split('=') > value = value.strip("\n") > rValue[name] = value > return rValue > ># get a list of all available GLSA in the given repository >def get_glsa_list(p_repository): > # TODO: remote fetch code for listing > if not os.access(p_repository, os.R_OK): > return [] > dirlist = os.listdir(p_repository) > prefix = config["GLSA_PREFIX"] > suffix = config["GLSA_SUFFIX"] > return [f[len(prefix):-1*len(suffix)] for f in dirlist if f[:len(prefix)] == prefix] > >config = getconfig("/etc/portage/glsa.conf") > ># helper function for xml parser, copied from api doc >def getText(node): > rc = "" > for node in node.childNodes: > if node.nodeType == node.TEXT_NODE: > rc = rc + node.data > return rc > ># GLSA xml data wrapper class >class glsa: > # set the id and read the xml file > def __init__(self, p_id): > self.nr = p_id > self.read() > > # read the xml file for this glsa using GLSA_DIR if CHECKMODE=local or GLSA_SERVER otherwise > def read(self): > if config["CHECKMODE"] == "local": > repository = "file://" + config["GLSA_DIR"] > else: > repository = config["GLSA_SERVER"] > myurl = repository + config["GLSA_PREFIX"] + str(self.nr) + config["GLSA_SUFFIX"] > self.parse(urllib.urlopen(myurl)) > > # helper function for xml parser: create a list of version instances > def parseVersions(self, node): > versions = node.getElementsByTagName("version") > rValue = [] > for v in versions: > mytype = v.getAttribute("range") > rValue.append(version(self.package, getText(v), mytype)) > return rValue > > # parse the XML document for this glsa (using xml.dom.minidom) > def parse(self, p_file): > myroot = xml.dom.minidom.parse(p_file).getElementsByTagName("glsa")[0] > if myroot.getAttribute("id") != self.nr: > raise Exception("filename and internal id don't match:" + myroot.getAttribute("id") + " != " + self.nr) > self.package = getText(myroot.getElementsByTagName("package")[0]) > self.date = strptime(getText(myroot.getElementsByTagName("date")[0]), "%Y-%m-%d") > self.summary = getText(myroot.getElementsByTagName("summary")[0]) > self.bug = getText(myroot.getElementsByTagName("bug")[0]) > self.severity = myroot.getAttribute("severity") > > tmp = myroot.getElementsByTagName("exploit") > self.exploits = [] > for e in tmp: > self.exploits.append(getText(e)) > > self.affected = self.parseVersions(myroot.getElementsByTagName("affected")[0]) > self.fixed = self.parseVersions(myroot.getElementsByTagName("fixed")[0]) > > tmp = myroot.getElementsByTagName("cve") > self.cve = [] > for c in tmp: > self.cve.append({"id": getText(c), "url":c.getAttribute("url")}) > > self.description = getText(myroot.getElementsByTagName("description")[0]) > self.solution_description = \ > getText(myroot.getElementsByTagName("solution")[0].getElementsByTagName("description")[0]) > > tmp = myroot.getElementsByTagName("solution")[0].getElementsByTagName("command") > self.precommands = [] > self.postcommands = [] > for c in tmp: > if c.getAttribute("phase") == "before": > self.precommands.append(getText(c).strip()) > else: > self.postcommands.append(getText(c).strip()) > > # check if this glsa is already applied > self.status = "not applied" > if os.access(config["CHECKFILE"], os.R_OK): > checkfile = open(config["CHECKFILE"], "r") > for line in checkfile.readlines(): > if line.strip() == self.nr: > self.status = "applied" > checkfile.close() > > # print a info page about this glsa (like the old announcements) > def dump(self): > print "GLSA: ", self.nr > print "package: ", self.package > print "summary: ", self.summary > print "severity: ", self.severity > print "bug: ", self.bug > print "date: ", strftime("%x", self.date) > print "status: ", self.status > for cve in self.cve: > if cve["url"]: > print "CVE: ", cve["id"], "(" , cve["url"] , ")" > else: > print "CVE: ", cve["id"] > for e in self.exploits: > print "exploit: ", e > for v in self.affected: > print "affected: ", v.getTextVersion() > for v in self.fixed: > print "fixed: ", v.getTextVersion() > print > print 30*'=' + " DESCRIPTION " + 30*'=' > print self.description > if self.solution_description: > print 32*'=' + " SOLUTION " + 31*'=' > print self.solution_description > > # put this glsa into the checkfile, so it is not checked on later runs > def check_in(self): > already_in = False > checkfile = open(config["CHECKFILE"], "r+") > for line in checkfile.readlines(): > if line.strip() == self.nr: > already_in = True > if not already_in: > checkfile.write(self.nr) > checkfile.close() > > # do all steps to apply this glsa > def fix(self): > if self.test(): > myversion = os.popen("portageq match / "+self.package, "r") > if len(myversion) < 1: > raise Exception("Error: test is positive but no package version found") > print "this system is affected" > print > print "running pre-emerge commands now" > for c in self.precommands: > os.system(c) > newversion = "" > # compare the actual version to all fixed versions, use the lowest fixed version > # that is newer than the actual version > for v in self.fixed: # I assume the list is sorted in the GLSA > nextversion = os.popen("portageq best_visibe / "+v.getCliVersion(), "r") > if pkgcmp(myversion, nextversion) > 0: > newversion = nextversion > break > print "installing " + newversion > if os.system("emerge =" + newversion) == 0: > print "update was successful, adding this glsa to the checklist" > self.check_in() > else: > print "update failed, NOT adding this glsa to the ckecklist" > print > print "running post-emerge commands now" > for c in self.postcommands: > os.system(c) > else: > print "this system is not affected, adding to checklist" > self.check_in() > > # check if the system is affected > def test(self): > rValue = False > for v in self.affected: > #if v.rangetype == "between": > # output = os.popen("portageq match / " + v.getCliVersion()[1], "r") > # if len(output.read().strip()) > 0: > # rValue = (output.read().strip() >= v.getCliVersion()[0]) > #else: > output = os.popen("portageq match / " + v.getCliVersion(), "r") > if len(output.read().strip()) > 0: > rValue = True > return rValue > > # show all steps necessary to apply this glsa > def pretend(self): > print "to apply this GLSA run the following commands:\n" > print > print "# check if the system is affected:" > print "# (if the commands return nothing you're not affected)" > for v in self.affected: > #if v.rangetype == "between": > # print "portageq match / " + v.getCliVersion()[1] > # print "# check if that version is equal to or greater than " + v.getPortageVersion()[0] > #else: > print "portageq match / " + v.getCliVersion() > print > print "# pre-emerge commands:" > for c in self.precommands: > print c > print > print "# emerge commands:" > print "emerge --sync" > if len(self.fixed) > 1: > print "# (only one of the following is needed):" > for v in self.fixed: > #if v.rangetype == "between": > # print "emerge " + v.getCliVersion() > #else: > print "emerge " + v.getCliVersion() > print > print "# post-emerge commands:" > for c in self.postcommands: > print c
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 32803
:
20291
|
20292
|
22530
|
22531