[Open-scap] [PATCH 1/1] Add the dpkginfo probe to query information on Debian packages
Pierre Chifflier
chifflier at edenwall.com
Mon Feb 22 21:22:53 UTC 2010
Implement the dpkginfo probe, mostly inspired from the rpminfo probe.
The apt-pkg library is available only in C++, so the configure script
now checks for the C++ compiler.
Signed-off-by: Pierre Chifflier <chifflier at edenwall.com>
---
configure.ac | 14 ++
src/OVAL/oval_probe.c | 2 +-
src/OVAL/probes/Makefile.am | 9 ++
src/OVAL/probes/unix/linux/dpkginfo-helper.cxx | 130 +++++++++++++++++
src/OVAL/probes/unix/linux/dpkginfo-helper.h | 34 +++++
src/OVAL/probes/unix/linux/dpkginfo.c | 182 ++++++++++++++++++++++++
6 files changed, 370 insertions(+), 1 deletions(-)
create mode 100644 src/OVAL/probes/unix/linux/dpkginfo-helper.cxx
create mode 100644 src/OVAL/probes/unix/linux/dpkginfo-helper.h
create mode 100644 src/OVAL/probes/unix/linux/dpkginfo.c
diff --git a/configure.ac b/configure.ac
index 36bc38b..3a7a0ef 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,6 +17,7 @@ AM_PATH_PYTHON
# Checks for programs.
AC_PROG_CC
AM_PROG_CC_C_O
+AC_PROG_CXX
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
@@ -170,6 +171,15 @@ AC_SEARCH_LIBS(
;;
esac
+AC_CHECK_LIB(
+ [apt-pkg],
+ [pkgVersion],
+ [deb_cflags=""
+ deb_libs="-lapt-pkg"
+ have_libapt_pkg=yes
+ ]
+)
+
#
# threads
#
@@ -252,6 +262,9 @@ AC_SUBST(pcre_libs)
AC_SUBST(rpm_cflags)
AC_SUBST(rpm_libs)
+AC_SUBST(deb_cflags)
+AC_SUBST(deb_libs)
+
AC_SUBST(libnl_cflags)
AC_SUBST(libnl_libs)
@@ -419,6 +432,7 @@ AM_CONDITIONAL([WANT_PROBES_UNIX], test "$probes_unix" = yes)
AM_CONDITIONAL([WANT_PROBES_LINUX], test "$probes_linux" = yes)
AM_CONDITIONAL([ENABLE_PROBE_RPMINFO], test "$have_librpm" = yes)
AM_CONDITIONAL([ENABLE_PROBE_RPMINFO44], test "$have_librpm44" = yes)
+AM_CONDITIONAL([ENABLE_PROBE_DPKGINFO], test "$have_libapt_pkg" = yes)
AM_CONDITIONAL([WANT_BINDINGS], test "$bindings" = yes)
AC_CONFIG_FILES([Makefile
diff --git a/src/OVAL/oval_probe.c b/src/OVAL/oval_probe.c
index be5cf6f..01bffe6 100644
--- a/src/OVAL/oval_probe.c
+++ b/src/OVAL/oval_probe.c
@@ -37,7 +37,7 @@ static const oval_pdsc_t __ovalp_ltable[] = {
/* 7007 */ {OVAL_INDEPENDENT_TEXT_FILE_CONTENT, "textfilecontent", NULL},
/* 7010 */ {OVAL_INDEPENDENT_XML_FILE_CONTENT, "xmlfilecontent", "probe_xmlfilecontent"},
/* 7999 */ {OVAL_INDEPENDENT_SYSCHAR_SUBTYPE, "system_info", "probe_system_info"},
-// /* 9001 */ { OVAL_LINUX_DPKG_INFO, "dpkginfo", "probe_dpkginfo" },
+ /* 9001 */ { OVAL_LINUX_DPKG_INFO, "dpkginfo", "probe_dpkginfo" },
/* 9003 */ {OVAL_LINUX_RPM_INFO, "rpminfo", "probe_rpminfo"},
// /* 9004 */ { OVAL_LINUX_SLACKWARE_PKG_INFO_TEST, "slackwarepkginfo", "probe_slackwarepkginfo" },
/* 13001 */ {OVAL_UNIX_FILE, "file", "probe_file"},
diff --git a/src/OVAL/probes/Makefile.am b/src/OVAL/probes/Makefile.am
index 4b888e6..d6918e9 100644
--- a/src/OVAL/probes/Makefile.am
+++ b/src/OVAL/probes/Makefile.am
@@ -55,7 +55,16 @@ pkglibexec_PROGRAMS += probe_rpminfo
probe_rpminfo_SOURCES= unix/linux/rpminfo.c
probe_rpminfo_CFLAGS= @rpm_cflags@
probe_rpminfo_LDFLAGS= @rpm_libs@
+endif
+if ENABLE_PROBE_DPKGINFO
+pkglibexec_PROGRAMS += probe_dpkginfo
+probe_dpkginfo_SOURCES= unix/linux/dpkginfo.c \
+ unix/linux/dpkginfo-helper.cxx \
+ unix/linux/dpkginfo-helper.h
+probe_dpkginfo_CFLAGS= @deb_cflags@
+probe_dpkginfo_CXXFLAGS= @deb_cflags@
+probe_dpkginfo_LDFLAGS= @deb_libs@
endif
endif
endif
diff --git a/src/OVAL/probes/unix/linux/dpkginfo-helper.cxx b/src/OVAL/probes/unix/linux/dpkginfo-helper.cxx
new file mode 100644
index 0000000..0ed544e
--- /dev/null
+++ b/src/OVAL/probes/unix/linux/dpkginfo-helper.cxx
@@ -0,0 +1,130 @@
+#ifndef __STUB_PROBE
+/*
+ * Author: Pierre Chifflier <chifflier at edenwall.com>
+ */
+
+#include <cstdio>
+#include <cstring>
+#include <iostream>
+#include <stdlib.h>
+
+#include <apt-pkg/init.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/mmap.h>
+#include <apt-pkg/pkgcache.h>
+#include <apt-pkg/pkgrecords.h>
+
+#include "dpkginfo-helper.h"
+
+using namespace std;
+
+static int _init_done = 0;
+static pkgCache *cgCache = NULL;
+
+static int opencache (void) {
+ if (pkgInitConfig (*_config) == false) return 0;
+ if (pkgInitSystem (*_config, _system) == false) return 0;
+
+ FileFd *fd = new FileFd (_config->FindFile ("Dir::Cache::pkgcache"),
+ FileFd::ReadOnly);
+
+ MMap *map = new MMap (*fd, MMap::Public|MMap::ReadOnly);
+ if (_error->PendingError () == true) {
+ _error->DumpErrors ();
+ return 0;
+ }
+
+ cgCache = new pkgCache (map);
+ if (0 == cgCache) return 0;
+ if (_error->PendingError () == true) {
+ _error->DumpErrors ();
+ return 0;
+ }
+
+ return 1;
+}
+
+struct dpkginfo_reply_t * dpkginfo_get_by_name(const char *name, int *err)
+{
+ pkgCache &cache = *cgCache;
+ pkgRecords Recs (cache);
+ struct dpkginfo_reply_t *reply = NULL;
+
+ // Locate the package
+ pkgCache::PkgIterator Pkg = cache.FindPkg(name);
+ if (Pkg.end() == true) {
+ /* not found, clear error flag */
+ if (err) *err = 0;
+ return NULL;
+ }
+
+ pkgCache::VerIterator V1 = Pkg.CurrentVer();
+ if (V1.end() == true) {
+ /* not installed, clear error flag */
+ /* FIXME this should be different that not found */
+ if (err) *err = 0;
+ return NULL;
+ }
+ pkgRecords::Parser &P = Recs.Lookup(V1.FileList());
+
+ /* split epoch, version and release */
+ string evr = V1.VerStr();
+ string epoch, version, release;
+ string::size_type version_start = 0, version_stop;
+ string::size_type pos;
+
+ pos = evr.find_first_of(":");
+ if (pos != string::npos) {
+ epoch = evr.substr(0, pos);
+ version_start = pos+1;
+ }
+
+ pos = evr.find_first_of("-");
+ if (pos != string::npos) {
+ version = evr.substr(version_start, pos-version_start);
+ version_stop = pos+1;
+ release = evr.substr(version_stop, evr.length()-version_stop);
+ } else { /* no release number, probably a native package */
+ version = evr.substr(version_start, evr.length()-version_start);
+ release = "";
+ }
+
+ reply = new(struct dpkginfo_reply_t);
+ memset(reply, 0, sizeof(struct dpkginfo_reply_t));
+ reply->name = strdup(Pkg.Name());
+ reply->arch = strdup(V1.Arch());
+ reply->epoch = strdup(epoch.c_str());
+ reply->release = strdup(release.c_str());
+ reply->version = strdup(version.c_str());
+ reply->evr = strdup(evr.c_str());
+
+ return reply;
+}
+
+void * dpkginfo_free_reply(struct dpkginfo_reply_t *reply)
+{
+ if (reply) {
+ free(reply->name);
+ delete reply;
+ }
+}
+
+int dpkginfo_init()
+{
+ if (_init_done == 0)
+ if (opencache() != 1) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int dpkginfo_fini()
+{
+ delete cgCache;
+ cgCache = NULL;
+
+ return 0;
+}
+
+#endif /* __STUB_PROBE */
diff --git a/src/OVAL/probes/unix/linux/dpkginfo-helper.h b/src/OVAL/probes/unix/linux/dpkginfo-helper.h
new file mode 100644
index 0000000..98a90e7
--- /dev/null
+++ b/src/OVAL/probes/unix/linux/dpkginfo-helper.h
@@ -0,0 +1,34 @@
+#ifndef __STUB_PROBE
+#ifndef __DPKGINFO_HELPER__
+#define __DPKGINFO_HELPER__
+
+/*
+ * Author: Pierre Chifflier <chifflier at edenwall.com>
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct dpkginfo_reply_t {
+ char *name;
+ char *arch;
+ char *epoch;
+ char *release;
+ char *version;
+ char *evr;
+};
+
+int dpkginfo_init();
+int dpkginfo_fini();
+
+struct dpkginfo_reply_t * dpkginfo_get_by_name(const char *name, int *err);
+
+void * dpkginfo_free_reply(struct dpkginfo_reply_t *reply);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DPKGINFO_HELPER__ */
+#endif /* __STUB_PROBE */
diff --git a/src/OVAL/probes/unix/linux/dpkginfo.c b/src/OVAL/probes/unix/linux/dpkginfo.c
new file mode 100644
index 0000000..e4619c6
--- /dev/null
+++ b/src/OVAL/probes/unix/linux/dpkginfo.c
@@ -0,0 +1,182 @@
+#ifndef __STUB_PROBE
+/*
+ * dpkginfo probe:
+ *
+ * dpkginfo_object(string name)
+ *
+ * dpkginfo_state(string name,
+ * string arch,
+ * string epoch,
+ * string release,
+ * string version,
+ * string evr,
+ * string signature_keyid)
+ */
+/*
+ * Author: Pierre Chifflier <chifflier at edenwall.com>
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+/* SEAP */
+#include <seap.h>
+#include <probe-api.h>
+#include <alloc.h>
+
+
+#include "dpkginfo-helper.h"
+
+
+struct dpkginfo_global {
+ pthread_mutex_t mutex;
+};
+
+static struct dpkginfo_global g_dpkg;
+
+
+void *probe_init(void)
+{
+ pthread_mutex_init (&(g_dpkg.mutex), NULL);
+ dpkginfo_init();
+
+ return ((void *)&g_dpkg);
+}
+
+void probe_fini (void *ptr)
+{
+ struct dpkginfo_global *d = (struct dpkginfo_global *)ptr;
+
+ pthread_mutex_destroy (&(d->mutex));
+ dpkginfo_fini();
+
+ return;
+}
+
+SEXP_t *probe_main (SEXP_t *object, int *err, void *arg)
+{
+ SEXP_t *probe_out, *val, *item_sexp, *r0;
+ char *request_st = NULL;
+ struct dpkginfo_reply_t *dpkginfo_reply = NULL;
+ int errflag;
+
+ val = probe_obj_getentval (object, "name", 1);
+
+ if (val == NULL) {
+ _D("%s: no value\n", "name");
+ *err = PROBE_ENOVAL;
+ return (NULL);
+ }
+
+ request_st = SEXP_string_cstr (val);
+ SEXP_free (val);
+
+ if (request_st == NULL) {
+ switch (errno) {
+ case EINVAL:
+ _D("%s: invalid value type\n", "name");
+ *err = PROBE_EINVAL;
+ break;
+ case EFAULT:
+ _D("%s: element not found\n", "name");
+ *err = PROBE_ENOELM;
+ break;
+ }
+
+ return (NULL);
+ }
+
+ probe_out = SEXP_list_new (NULL);
+
+ /* get info from debian apt cache */
+ pthread_mutex_lock (&(g_dpkg.mutex));
+ dpkginfo_reply = dpkginfo_get_by_name(request_st, &errflag);
+ pthread_mutex_unlock (&(g_dpkg.mutex));
+
+ if (dpkginfo_reply == NULL) {
+ switch (errflag) {
+ case 0: /* Not found */
+ _D("Package \"%s\" not found.\n", request_st);
+
+ item_sexp = probe_item_creat ("dpkginfo_item", NULL,
+ "name", NULL,
+ r0 = SEXP_string_newf(request_st),
+ NULL);
+
+ probe_item_setstatus (item_sexp, OVAL_STATUS_DOESNOTEXIST);
+ probe_itement_setstatus (item_sexp, "name", 1, OVAL_STATUS_DOESNOTEXIST);
+
+ SEXP_list_add (probe_out, item_sexp);
+ SEXP_free (item_sexp);
+ SEXP_free (r0);
+
+ break;
+ case -1: /* Error */
+ _D("get_dpkginfo failed\n");
+
+ item_sexp = probe_item_creat ("dpkginfo_item", NULL,
+ "name", NULL,
+ r0 = SEXP_string_newf(request_st),
+ NULL);
+
+ probe_item_setstatus (item_sexp, OVAL_STATUS_ERROR);
+
+ SEXP_list_add (probe_out, item_sexp);
+ SEXP_free (item_sexp);
+ SEXP_free (r0);
+
+ break;
+ }
+ } else { /* Ok */
+ SEXP_t *r1, *r2, *r3, *r4, *r5;
+ int i;
+ int num_items = 1; /* FIXME */
+
+ for (i = 0; i < num_items; ++i) {
+ item_sexp = probe_item_creat ("dpkginfo_item", NULL,
+
+ "name", NULL,
+ r0 = SEXP_string_newf (dpkginfo_reply->name),
+
+ "arch", NULL,
+ r1 = SEXP_string_newf (dpkginfo_reply->arch),
+
+ "epoch", NULL,
+ r2 = SEXP_string_newf (dpkginfo_reply->epoch),
+
+ "release", NULL,
+ r3 = SEXP_string_newf (dpkginfo_reply->release),
+
+ "version", NULL,
+ r4 = SEXP_string_newf (dpkginfo_reply->version),
+
+ "evr", NULL,
+ r5 = SEXP_string_newf (dpkginfo_reply->evr),
+
+ NULL, NULL,
+ NULL,
+
+ NULL);
+
+ SEXP_list_add (probe_out, item_sexp);
+ SEXP_free (item_sexp);
+ /* FIXME: this is... stupid */
+ SEXP_free (r0);
+ SEXP_free (r1);
+ SEXP_free (r2);
+ SEXP_free (r3);
+ SEXP_free (r4);
+ SEXP_free (r5);
+
+ dpkginfo_free_reply(dpkginfo_reply);
+ }
+ }
+
+ *err = 0;
+ return (probe_out);
+}
+
+#endif
+
--
1.7.0
More information about the Open-scap-list
mailing list