summaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2019-08-12 18:24:04 -0700
committerZac Medico <zmedico@gentoo.org>2019-08-18 20:42:40 -0700
commit429b629e3bb0469cf34d170ad06663e0eabd2d9f (patch)
treebc52ed94333ff3bd4cbe5df0f980724727c7b30d /bin
parentaccf36f00070427170a4b46b2e3522de7b33d5b0 (diff)
downloadgentoolkit-429b629e3bb0469cf34d170ad06663e0eabd2d9f.tar.gz
glsa-check moved to portage repository (bug 463952)
This copy of glsa-check is no longer need since it has moved to the portage repository. Bug: https://bugs.gentoo.org/463952 Signed-off-by: Zac Medico <zmedico@gentoo.org>
Diffstat (limited to 'bin')
-rwxr-xr-xbin/glsa-check418
1 files changed, 0 insertions, 418 deletions
diff --git a/bin/glsa-check b/bin/glsa-check
deleted file mode 100755
index 3f691b8..0000000
--- a/bin/glsa-check
+++ /dev/null
@@ -1,418 +0,0 @@
-#!/usr/bin/python
-
-# $Header: $
-# This program is licensed under the GPL, version 2
-
-import sys
-import os
-import codecs
-from functools import reduce
-
-import portage
-from portage.output import *
-
-from getopt import getopt, GetoptError
-
-__program__ = "glsa-check"
-__author__ = "Marius Mauch <genone@gentoo.org>"
-__version__ = "git"
-
-optionmap = [
-["-l", "--list", "list the GLSAs"],
-["-d", "--dump", "--print", "show all information about the GLSAs"],
-["-t", "--test", "test if this system is affected by the GLSAs"],
-["-p", "--pretend", "show the necessary steps to apply the GLSAs"],
-["-f", "--fix", "try to auto-apply the GLSAs (experimental)"],
-["-i", "--inject", "inject the given GLSA into the glsa_injected file"],
-["-n", "--nocolor", "disable colors (option)"],
-["-e", "--emergelike", "upgrade to latest version (not least-change, option)"],
-["-h", "--help", "show this help message"],
-["-V", "--version", "some information about this tool"],
-["-v", "--verbose", "print more information (option)"],
-["-c", "--cve", "show CVE ids in listing mode (option)"],
-["-q", "--quiet", "be less verbose and do not send empty mail (option)"],
-["-m", "--mail", "send a mail with the given GLSAs to the administrator"],
-]
-
-# print a warning as this is beta code (but proven by now, so no more warning)
-#sys.stderr.write("WARNING: This tool is completely new and not very tested, so it should not be\n")
-#sys.stderr.write("used on production systems. It's mainly a test tool for the new GLSA release\n")
-#sys.stderr.write("and distribution system, it's functionality will later be merged into emerge\n")
-#sys.stderr.write("and equery.\n")
-#sys.stderr.write("Please read http://www.gentoo.org/proj/en/portage/glsa-integration.xml\n")
-#sys.stderr.write("before using this tool AND before reporting a bug.\n\n")
-
-# option parsing
-args = []
-params = []
-try:
- args, params = getopt(sys.argv[1:], "".join([o[0][1] for o in optionmap]), \
- [x[2:] for x in reduce(lambda x,y: x+y, [z[1:-1] for z in optionmap])])
- args = [a for a, b in args]
-
- for option in ["--nocolor", "-n"]:
- if option in args:
- nocolor()
- args.remove(option)
-
- verbose = False
- for option in ["--verbose", "-v"]:
- if option in args:
- verbose = True
- args.remove(option)
-
- list_cve = False
- for option in ["--cve", "-c"]:
- if option in args:
- list_cve = True
- args.remove(option)
-
- least_change = True
- for option in ["--emergelike", "-e"]:
- if option in args:
- least_change = False
- args.remove(option)
-
- quiet = False
- for option in ["--quiet", "-q"]:
- if option in args:
- quiet = True
- args.remove(option)
-
-
- # sanity checking
- if len(args) <= 0:
- sys.stderr.write("no option given: what should I do ?\n")
- mode = "HELP"
- elif len(args) > 1:
- sys.stderr.write("please use only one command per call\n")
- mode = "HELP"
- else:
- # in what mode are we ?
- args = args[0]
- for m in optionmap:
- if args in [o for o in m[:-1]]:
- mode = m[1][2:]
-
-except GetoptError as e:
- sys.stderr.write("unknown option given: ")
- sys.stderr.write(str(e)+"\n")
- mode = "HELP"
-
-# we need a set of glsa for most operation modes
-if len(params) <= 0 and mode in ["fix", "test", "pretend", "dump", "inject", "mail"]:
- sys.stderr.write("\nno GLSA given, so we'll do nothing for now. \n")
- sys.stderr.write("If you want to run on all GLSA please tell me so \n")
- sys.stderr.write("(specify \"all\" as parameter)\n\n")
- mode = "HELP"
-elif len(params) <= 0 and mode == "list":
- params.append("affected")
-
-# show help message
-if mode == "help" or mode == "HELP":
- msg = "Syntax: glsa-check <option> [glsa-list]\n\n"
- for m in optionmap:
- msg += m[0] + "\t" + m[1] + " \t: " + m[-1] + "\n"
- for o in m[2:-1]:
- msg += "\t" + o + "\n"
- msg += "\nglsa-list can contain an arbitrary number of GLSA ids, \n"
- msg += "filenames containing GLSAs or the special identifiers \n"
- msg += "'all' and 'affected'\n"
- if mode == "help":
- sys.stdout.write(msg)
- sys.exit(0)
- else:
- sys.stderr.write("\n" + msg)
- sys.exit(1)
-
-# we need root privileges for write access
-if mode in ["fix", "inject"] and os.geteuid() != 0:
- sys.stderr.write(__program__ + ": root access is needed for \""+mode+"\" mode\n")
- sys.exit(2)
-
-# show version and copyright information
-if mode == "version":
- sys.stderr.write("%(program)s (%(version)s)\n" % {
- "program": __program__,
- "version": __version__
- })
- sys.stderr.write("Author: %s\n" % __author__)
- sys.stderr.write("This program is licensed under the GPL, version 2\n")
- sys.exit(0)
-
-# delay this for speed increase
-from gentoolkit.glsa import *
-
-glsaconfig = checkconfig(portage.config(clone=portage.settings))
-
-if quiet:
- glsaconfig["EMERGE_OPTS"] += " --quiet"
-
-vardb = portage.db[portage.root]["vartree"].dbapi
-portdb = portage.db[portage.root]["porttree"].dbapi
-
-# Check that we really have a glsa dir to work on
-if not (os.path.exists(glsaconfig["GLSA_DIR"]) and os.path.isdir(glsaconfig["GLSA_DIR"])):
- sys.stderr.write(red("ERROR")+": GLSA_DIR %s doesn't exist. Please fix this.\n" % glsaconfig["GLSA_DIR"])
- sys.exit(1)
-
-# build glsa lists
-completelist = get_glsa_list(glsaconfig["GLSA_DIR"], glsaconfig)
-
-if os.access(glsaconfig["CHECKFILE"], os.R_OK):
- checklist = [line.strip() for line in open(glsaconfig["CHECKFILE"], "r").readlines()]
-else:
- checklist = []
-todolist = [e for e in completelist if e not in checklist]
-
-glsalist = []
-if "new" in params:
- params.remove("new")
- sys.stderr.write("Warning: The 'new' glsa-list target has been removed, using 'affected'.\n")
- params.append("affected")
-
-if "all" in params:
- glsalist = completelist
- params.remove("all")
-
-if "affected" in params:
- for x in todolist:
- try:
- myglsa = Glsa(x, glsaconfig)
- except (GlsaTypeException, GlsaFormatException) as e:
- if verbose:
- sys.stderr.write(("invalid GLSA: %s (error message was: %s)\n" % (x, e)))
- continue
- if myglsa.isVulnerable():
- glsalist.append(x)
- params.remove("affected")
-
-# remove invalid parameters
-for p in params[:]:
- if not (p in completelist or os.path.exists(p)):
- sys.stderr.write(("(removing %s from parameter list as it isn't a valid GLSA specification)\n" % p))
- params.remove(p)
-
-glsalist.extend([g for g in params if g not in glsalist])
-
-def summarylist(myglsalist, fd1=sys.stdout, fd2=sys.stderr, encoding="utf-8"):
- # Get to the raw streams in py3k before wrapping them with an encoded writer
- # to avoid writing bytes to a text stream (stdout/stderr are text streams
- # by default in py3k)
- if hasattr(fd1, "buffer"):
- fd1 = fd1.buffer
- if hasattr(fd2, "buffer"):
- fd2 = fd2.buffer
- fd1 = codecs.getwriter(encoding)(fd1)
- fd2 = codecs.getwriter(encoding)(fd2)
- if not quiet:
- fd2.write(white("[A]")+" means this GLSA was marked as applied (injected),\n")
- fd2.write(green("[U]")+" means the system is not affected and\n")
- fd2.write(red("[N]")+" indicates that the system might be affected.\n\n")
-
- myglsalist.sort()
- for myid in myglsalist:
- try:
- myglsa = Glsa(myid, glsaconfig)
- except (GlsaTypeException, GlsaFormatException) as e:
- if verbose:
- fd2.write(("invalid GLSA: %s (error message was: %s)\n" % (myid, e)))
- continue
- if myglsa.isInjected():
- status = "[A]"
- color = white
- elif myglsa.isVulnerable():
- status = "[N]"
- color = red
- else:
- status = "[U]"
- color = green
-
- if verbose:
- access = ("[%-8s] " % myglsa.access)
- else:
- access = ""
-
- fd1.write(color(myglsa.nr) + " " + color(status) + " " + color(access) + myglsa.title + " (")
- if not verbose:
- for pkg in list(myglsa.packages.keys())[:3]:
- fd1.write(" " + pkg + " ")
- if len(myglsa.packages) > 3:
- fd1.write("... ")
- else:
- for cpv in myglsa.packages.keys():
- pkg = myglsa.packages[cpv]
- for path in pkg:
- v_installed = reduce(operator.add, [match(v, "vartree") for v in path["vul_atoms"]], [])
- u_installed = reduce(operator.add, [match(u, "vartree") for u in path["unaff_atoms"]], [])
- mylist = sorted(set(v_installed).difference(set(u_installed)))
- if len(mylist) > 0:
- cpv = color(" ".join(mylist))
- fd1.write(" " + cpv + " ")
-
- fd1.write(")")
- if list_cve:
- fd1.write(" "+(",".join([r[:13] for r in myglsa.references if r[:4] in ["CAN-", "CVE-"]])))
- fd1.write("\n")
- return 0
-
-if mode == "list":
- sys.exit(summarylist(glsalist))
-
-# dump, fix, inject and fix are nearly the same code, only the glsa method call differs
-if mode in ["dump", "fix", "inject", "pretend"]:
- for myid in glsalist:
- try:
- myglsa = Glsa(myid, glsaconfig)
- except (GlsaTypeException, GlsaFormatException) as e:
- if verbose:
- sys.stderr.write(("invalid GLSA: %s (error message was: %s)\n" % (myid, e)))
- continue
- if mode == "dump":
- myglsa.dump()
- elif mode == "fix":
- if not quiet:
- sys.stdout.write("Fixing GLSA "+myid+"\n")
- if not myglsa.isVulnerable():
- if not quiet:
- sys.stdout.write(">>> no vulnerable packages installed\n")
- else:
- if quiet:
- sys.stdout.write("Fixing GLSA "+myid+"\n")
- mergelist = myglsa.getMergeList(least_change=least_change)
- if mergelist == []:
- sys.stdout.write(">>> cannot fix GLSA, no unaffected packages available\n")
- sys.exit(2)
- for pkg in mergelist:
- sys.stdout.write(">>> merging "+pkg+"\n")
- # using emerge for the actual merging as it contains the dependency
- # code and we want to be consistent in behaviour. Also this functionality
- # will be integrated in emerge later, so it shouldn't hurt much.
- emergecmd = "emerge --oneshot " + glsaconfig["EMERGE_OPTS"] + " =" + pkg
- if verbose:
- sys.stderr.write(emergecmd+"\n")
- exitcode = os.system(emergecmd)
- # system() returns the exitcode in the high byte of a 16bit integer
- if exitcode >= 1 << 8:
- exitcode >>= 8
- if exitcode:
- sys.exit(exitcode)
- if len(mergelist):
- sys.stdout.write("\n")
- elif mode == "pretend":
- if not quiet:
- sys.stdout.write("Checking GLSA "+myid+"\n")
- if not myglsa.isVulnerable():
- if not quiet:
- sys.stdout.write(">>> no vulnerable packages installed\n")
- else:
- if quiet:
- sys.stdout.write("Checking GLSA "+myid+"\n")
- mergedict = {}
- for (vuln, update) in myglsa.getAffectionTable(least_change=least_change):
- mergedict.setdefault(update, []).append(vuln)
-
- # first, extract the atoms that cannot be upgraded (where key == "")
- no_upgrades = []
- if "" in mergedict:
- no_upgrades = mergedict[""]
- del mergedict[""]
-
- # see if anything is left that can be upgraded
- if mergedict:
- sys.stdout.write(">>> Updates that will be performed:\n")
- for (upd, vuln) in mergedict.items():
- sys.stdout.write(" " + green(upd) + " (vulnerable: " + red(", ".join(vuln)) + ")\n")
-
- if no_upgrades:
- sys.stdout.write(">>> No upgrade path exists for these packages:\n")
- sys.stdout.write(" " + red(", ".join(no_upgrades)) + "\n")
- elif mode == "inject":
- sys.stdout.write("injecting " + myid + "\n")
- myglsa.inject()
- sys.exit(0)
-
-# test is a bit different as Glsa.test() produces no output
-if mode == "test":
- outputlist = []
- for myid in glsalist:
- try:
- myglsa = Glsa(myid, glsaconfig)
- except (GlsaTypeException, GlsaFormatException) as e:
- if verbose:
- sys.stderr.write(("invalid GLSA: %s (error message was: %s)\n" % (myid, e)))
- continue
- if myglsa.isVulnerable():
- outputlist.append(str(myglsa.nr))
- if len(outputlist) > 0:
- sys.stderr.write("This system is affected by the following GLSAs:\n")
- if verbose:
- summarylist(outputlist)
- else:
- sys.stdout.write("\n".join(outputlist)+"\n")
- else:
- sys.stderr.write("This system is not affected by any of the listed GLSAs\n")
- sys.exit(0)
-
-# mail mode as requested by solar
-if mode == "mail":
- try:
- import portage.mail as portage_mail
- except ImportError:
- import portage_mail
-
- import socket
- from io import BytesIO
- try:
- from email.mime.text import MIMEText
- except ImportError:
- from email.MIMEText import MIMEText
-
- # color doesn't make any sense for mail
- nocolor()
-
- if "PORTAGE_ELOG_MAILURI" in glsaconfig:
- myrecipient = glsaconfig["PORTAGE_ELOG_MAILURI"].split()[0]
- else:
- myrecipient = "root@localhost"
-
- if "PORTAGE_ELOG_MAILFROM" in glsaconfig:
- myfrom = glsaconfig["PORTAGE_ELOG_MAILFROM"]
- else:
- myfrom = "glsa-check"
-
- mysubject = "[glsa-check] Summary for %s" % socket.getfqdn()
-
- # need a file object for summarylist()
- myfd = BytesIO()
- line = "GLSA Summary report for host %s\n" % socket.getfqdn()
- myfd.write(line.encode("utf-8"))
- line = "(Command was: %s)\n\n" % " ".join(sys.argv)
- myfd.write(line.encode("utf-8"))
- summarylist(glsalist, fd1=myfd, fd2=myfd)
- summary = myfd.getvalue().decode("utf-8")
- myfd.close()
-
- myattachments = []
- for myid in glsalist:
- try:
- myglsa = Glsa(myid, glsaconfig)
- except (GlsaTypeException, GlsaFormatException) as e:
- if verbose:
- sys.stderr.write(("invalid GLSA: %s (error message was: %s)\n" % (myid, e)))
- continue
- myfd = BytesIO()
- myglsa.dump(outstream=myfd)
- attachment = myfd.getvalue().decode("utf-8")
- myattachments.append(MIMEText(attachment, _charset="utf8"))
- myfd.close()
-
- if glsalist or not quiet:
- mymessage = portage_mail.create_message(myfrom, myrecipient, mysubject, summary, myattachments)
- portage_mail.send_mail(glsaconfig, mymessage)
-
- sys.exit(0)
-
-# something wrong here, all valid paths are covered with sys.exit()
-sys.stderr.write("nothing more to do\n")
-sys.exit(2)