aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Danny van Dyk <dvandyk@exherbo.org> 2006-04-17 01:06:31 +0000
committerAvatar Danny van Dyk <dvandyk@exherbo.org> 2006-04-17 01:06:31 +0000
commit571ebf63db2c3cee8cb40a476acb9ddf5df1c6b6 (patch)
tree77bcc6062c638282fbbd0ad2722c1a2f482d6441
parent51e034bd07cc1ebb33c54511ee2291f569f96625 (diff)
downloadpaludis-571ebf63db2c3cee8cb40a476acb9ddf5df1c6b6.tar.gz
paludis-571ebf63db2c3cee8cb40a476acb9ddf5df1c6b6.tar.xz
Implement built-in 'security' package set.
-rw-r--r--AUTHORS3
-rw-r--r--paludis/config_file.cc99
-rw-r--r--paludis/config_file.hh98
-rw-r--r--paludis/dep_parser.cc2
-rw-r--r--paludis/dep_parser.hh2
-rw-r--r--paludis/portage_repository.cc61
-rw-r--r--paludis/portage_repository.hh1
7 files changed, 264 insertions, 2 deletions
diff --git a/AUTHORS b/AUTHORS
index cf9905a..7b03e70 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -15,3 +15,6 @@ John N. Laliberte <allanonjl@gentoo.org>
Stephen Klimaszewski <steev@gentoo.org>
Contributor
+
+Danny van Dyk <kugelfang@gentoo.org>
+ Contributor
diff --git a/paludis/config_file.cc b/paludis/config_file.cc
index 519ce2c..b667f48 100644
--- a/paludis/config_file.cc
+++ b/paludis/config_file.cc
@@ -2,6 +2,7 @@
/*
* Copyright (c) 2006 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ * Copyright (c) 2006 Danny van Dyk <kugelfang@gentoo.org>
*
* This file is part of the Paludis package manager. Paludis is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
@@ -269,3 +270,101 @@ KeyValueConfigFile::strip_quotes(const std::string & s) const
return s;
}
+AdvisoryFileError::AdvisoryFileError(const std::string & msg,
+ const std::string & filename) throw () :
+ ConfigurationError("Advisory file error" +
+ (filename.empty() ? ": " : "in file '" + filename + "': ") + msg)
+{
+}
+
+AdvisoryFile::AdvisoryFile(std::istream * const s) :
+ ConfigFile(s),
+ _end_of_header(false)
+{
+ need_lines();
+ sanitise();
+}
+
+AdvisoryFile::AdvisoryFile(const std::string & filename) :
+ ConfigFile(filename),
+ _end_of_header(false)
+{
+ need_lines();
+ sanitise();
+}
+
+AdvisoryFile::AdvisoryFile(std::istream * const s,
+ const std::map<std::string, std::string> & m) :
+ ConfigFile(s),
+ _entries(m.begin(), m.end()),
+ _end_of_header(false)
+{
+ _end_of_header = false;
+ need_lines();
+ sanitise();
+}
+
+AdvisoryFile::AdvisoryFile(const std::string & filename,
+ const std::map<std::string, std::string> & m) :
+ ConfigFile(filename),
+ _entries(m.begin(), m.end()),
+ _end_of_header(false)
+{
+ need_lines();
+ sanitise();
+}
+
+AdvisoryFile::~AdvisoryFile()
+{
+}
+
+void
+AdvisoryFile::accept_line(const std::string & line) const
+{
+ std::string::size_type p(line.find(':'));
+
+ if ((std::string::npos == p) || (_end_of_header))
+ {
+ _entries["Description"] += line + "\n";
+ _end_of_header = true;
+ }
+ else
+ {
+ std::string key(line.substr(0, p)), value(line.substr(p + 1));
+ normalise_line(key);
+ normalise_line(value);
+ if ((key == "Affected") || (key == "Unaffected") || (key == "Bug-Id") || (key == "Url")
+ || (key == "Reviewed-By"))
+ {
+ if (!_entries[key].empty())
+ value = "\n" + value;
+ _entries[key] += value;
+ }
+ else
+ {
+ if (_entries[key].empty())
+ _entries[key] = value;
+ else
+ throw ConfigFileError("When adding value for key '" + key + "': Duplicate key found.");
+ }
+ }
+}
+
+void
+AdvisoryFile::sanitise()
+{
+ if (_entries["Id"].empty())
+ throw AdvisoryFileError("Missing mandatory key: 'Id'.");
+
+ if (_entries["Title"].empty())
+ throw AdvisoryFileError("Missing mandatory key: 'Title'.");
+
+ if (_entries["Commited-By"].empty())
+ throw AdvisoryFileError("Missing mandatory key: 'Commited-By'.");
+
+ if (_entries["Reviewed-By"].empty())
+ throw AdvisoryFileError("Missing mandatory key: 'Reviewed-by'.");
+
+ if ((_entries["Affected"].size() + _entries["Unaffected"].size()) == 0)
+ throw AdvisoryFileError("Missing either 'Affected' or 'Unaffected' key.");
+}
diff --git a/paludis/config_file.hh b/paludis/config_file.hh
index 5edd0b5..463c0e5 100644
--- a/paludis/config_file.hh
+++ b/paludis/config_file.hh
@@ -267,6 +267,104 @@ namespace paludis
return _entries[key];
}
};
+
+ /**
+ * An AdvisoryFileError is thrown if bad data is encountered in
+ * a ConfigFile.
+ *
+ * \ingroup ConfigFile
+ * \ingroup Exception
+ */
+ class AdvisoryFileError : public ConfigurationError
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ AdvisoryFileError(const std::string & message,
+ const std::string & filename = "") throw ();
+ };
+
+ /**
+ * An AdvisoryFile is a file containing all necessary information to
+ * update one or more packages in order to avoid a security problem.
+ *
+ * It uses a textformat with RFC 822 style headers, an empty line denotes
+ * the beginning of a multi-line description of the security problem.
+ *
+ * Valid header items are:
+ * Affected, Bug-Url, Commited-By, Id, Reviewed-By, Unaffected, Url
+ *
+ * \ingroup ConfigFile
+ */
+
+ class AdvisoryFile : protected ConfigFile
+ {
+ private:
+ mutable std::map<std::string, std::string> _entries;
+ mutable bool _end_of_header;
+ protected:
+ void accept_line(const std::string &) const;
+ void sanitise();
+
+ public:
+ /**
+ * Constructor, from a stream.
+ */
+ AdvisoryFile(std::istream * const);
+
+ /**
+ * Constructor, from a filename.
+ */
+ AdvisoryFile(const std::string & filename);
+
+ /**
+ * Constructor, from a stream, with defaults.
+ */
+ AdvisoryFile(std::istream * const,
+ const std::map<std::string, std::string> &);
+
+ /**
+ * Constructor, from a filename, with defaults.
+ */
+ AdvisoryFile(const std::string & filename,
+ const std::map<std::string, std::string> &);
+
+ /**
+ * Destructor.
+ */
+ ~AdvisoryFile();
+
+ /**
+ * Iterator over our lines.
+ */
+ typedef std::map<std::string, std::string>::const_iterator Iterator;
+
+ /**
+ * Iterator to the start of our lines.
+ */
+ Iterator begin() const
+ {
+ return _entries.begin();
+ }
+
+ /**
+ * Iterator to past the end of our lines.
+ */
+ Iterator end() const
+ {
+ return _entries.end();
+ }
+
+ /**
+ * Fetch the specified key, or a blank string.
+ */
+ std::string get(const std::string & key) const
+ {
+ return _entries[key];
+ }
+ };
+
}
#endif
diff --git a/paludis/dep_parser.cc b/paludis/dep_parser.cc
index 0f47c8f..2e96a42 100644
--- a/paludis/dep_parser.cc
+++ b/paludis/dep_parser.cc
@@ -47,7 +47,7 @@ enum DepParserState
dps_had_use_flag_space
};
-CompositeDepAtom::ConstPointer
+CompositeDepAtom::Pointer
DepParser::parse(const std::string & s, const DepParserPolicyInterface * const policy)
{
Context context("When parsing dependency string '" + s + "':");
diff --git a/paludis/dep_parser.hh b/paludis/dep_parser.hh
index 88c7e78..5c2186e 100644
--- a/paludis/dep_parser.hh
+++ b/paludis/dep_parser.hh
@@ -149,7 +149,7 @@ namespace paludis
* Parse a given dependency string, and return an appropriate
* DepAtom tree.
*/
- static CompositeDepAtom::ConstPointer parse(const std::string & s,
+ static CompositeDepAtom::Pointer parse(const std::string & s,
const DepParserPolicyInterface * const policy = DefaultPolicy::get_instance());
};
}
diff --git a/paludis/portage_repository.cc b/paludis/portage_repository.cc
index 909770b..542dc78 100644
--- a/paludis/portage_repository.cc
+++ b/paludis/portage_repository.cc
@@ -2,6 +2,7 @@
/*
* Copyright (c) 2005, 2006 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ * Copyright (c) 2006 Danny van Dyk <kugelfang@gentoo.org>
*
* This file is part of the Paludis package manager. Paludis is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
@@ -1298,6 +1299,62 @@ PortageRepository::do_install(const QualifiedPackageName & q, const VersionSpec
}
DepAtom::Pointer
+PortageRepository::do_security_set() const
+{
+ Context c("When building security package set:");
+ AllDepAtom::Pointer security_packages(new AllDepAtom);
+
+ FSEntry security = _imp->location / "metadata" / "security";
+ if (!security.is_directory())
+ return DepAtom::Pointer(0);
+
+ std::list<FSEntry> advisories;
+ std::copy(DirIterator(_imp->location / "metadata" / "security"), DirIterator(),
+ filter_inserter(std::back_inserter(advisories),
+ IsFileWithExtension("advisory-", ".conf")));
+
+ std::list<FSEntry>::const_iterator f(advisories.begin()),
+ f_end(advisories.end());
+
+ for ( ; f != f_end; ++f)
+ {
+ Context c("When parsing security advisory '" + stringify(*f) + "':");
+ AdvisoryFile advisory(*f);
+ std::string advisory_tag = "GLSA " + advisory.get("Id");
+ bool is_affected = false;
+
+ std::list<std::string> a_list, u_list;
+ Tokeniser<delim_kind::AnyOfTag, delim_mode::DelimiterTag> tokeniser("\n");
+ tokeniser.tokenise(advisory.get("Affected"), std::back_inserter(a_list));
+ tokeniser.tokenise(advisory.get("Unaffected"), std::back_inserter(u_list));
+ if (a_list.size() != u_list.size())
+ throw AdvisoryFileError("Number of affected packages does not match number of unaffected packages.");
+
+ std::list<std::string>::const_iterator a(a_list.begin()), a_end(a_list.end());
+ std::list<std::string>::const_iterator u(u_list.begin()), u_end(u_list.end());
+ while ((a != a_end) && (u != u_end))
+ {
+ PackageDepAtom::Pointer affected(new PackageDepAtom(*a)),
+ unaffected(new PackageDepAtom(*u));
+ ++a; ++u;
+
+ if (affected->package() != unaffected->package())
+ throw AdvisoryFileError("Affected and unaffected items are out of sync.");
+
+ if ((_imp->db->query(affected, is_installed_only))->empty())
+ continue;
+
+ is_affected = true;
+ unaffected->set_tag(advisory_tag);
+ security_packages->add_child(unaffected);
+ }
+
+ }
+
+ return security_packages;
+}
+
+DepAtom::Pointer
PortageRepository::do_package_set(const std::string & s) const
{
if ("system" == s)
@@ -1311,6 +1368,10 @@ PortageRepository::do_package_set(const std::string & s) const
return _imp->system_packages;
}
+ else if ("security" == s)
+ {
+ return do_security_set();
+ }
else
return DepAtom::Pointer(0);
}
diff --git a/paludis/portage_repository.hh b/paludis/portage_repository.hh
index b130f6d..ea45950 100644
--- a/paludis/portage_repository.hh
+++ b/paludis/portage_repository.hh
@@ -79,6 +79,7 @@ namespace paludis
void need_category_names() const;
void need_version_names(const QualifiedPackageName &) const;
void need_virtual_names() const;
+ DepAtom::Pointer do_security_set() const;
protected:
/**