[Rpm-maint] Tizen rpm security plug-in interface

Reshetova, Elena elena.reshetova at intel.com
Mon Oct 10 13:00:53 UTC 2011


Hi,

Let me make first a short introduction and some explanation to you about the
rpm
 security related work we have been doing recently at Intel.
 I hope we can collaborate on this in the future and help to put good
enablers in rpm for security purposes. 

Some history first:
January this year, there was a set of patches posted from Tero Aho, you can
find them in archives: 
http://lists.rpm.org/pipermail/rpm-maint/2011-January/002980.html

I can see that even two tags were reserved for MSSF in rpm tags:
RPMTAG_MSSFMANIFEST and RPMTAG_MSSFDOMAIN. 

These patches were intended for wiring a MSSF rpm security plug-in for MeeGo
that 
would contain a rich set of security functionality, like setting up security
policies for installed packages,
labelling xattr for Smack and IMA and etc. I can provide more detailed
description of functionality, if needed. 

As you probably heard, LiMo and MeeGo had merged into a new project, called
Tizen (https://www.tizen.org/).
This didn't eliminate by any means the need of security and similar security
functionality that we needed in MeeGo related to rpm. 

So, our needs are still the same: we need to have a certain set of hooks in
rpm during different phases of rpm installation that
can be then implemented inside an rpm security plug-in. The hooks themselves
didn't change, but we did change their realisation  
inside the plug-in, because we will be using a different security framework.


I would like to get your opinion about the hooks' position in rpm code. I
have just today rebased them to rpm master brunch. 
Please consider this not as ready patch, but more like code for the initial
discussion.  
I have excluded for now the code of the plugin itself for simplicity.  

Best Regards,
Elena.


 Makefile.am            |    9 
 build/files.c          |   15 
 build/parsePreamble.c  |    1 
 build/rpmfc.c          |  134 ++--
 configure.ac           |   68 ++
 lib/Makefile.am        |    3 
 lib/fsm.c              |   17 
 lib/package.c          |    4 
 lib/rpmfi.h            |    1 
 lib/rpmscript.c        |    6 
 lib/rpmsecurity.c      |  269 +++++++++
 lib/rpmsecurity.h      |  160 +++++
 lib/rpmtag.h           |    4 
 lib/rpmte.c            |    9 
 lib/rpmts.c            |    4 
 lib/rpmtypes.h         |    1 
 lib/transaction.c      |   18 
 macros.in              |    2 
 preinstall.am          |    8 
 rpmio/base64.c         |    6 
 rpmio/macro.c          |    2 
 rpmio/rpmmalloc.c      |    2 
 security/Makefile.am   |   24 
 security/Makefile.msm  |   15 
 security/msm.c         |  816 +++++++++++++++++++++++++++++
 security/msm.h         |  489 +++++++++++++++++
 security/msmconfig.c   |  264 +++++++++
 security/msmmanifest.c | 1358
+++++++++++++++++++++++++++++++++++++++++++++++++
 security/msmmatch.c    |   70 ++
 security/msmxattr.c    | 1248 +++++++++++++++++++++++++++++++++++++++++++++
 security/security.h    |   25 
 31 files changed, 4972 insertions(+), 80 deletions(-)


diff -Nuarp '--exclude=.git' rpm/build/files.c rpm-security/build/files.c
--- rpm/build/files.c	2011-10-10 15:25:30.577900228 +0300
+++ rpm-security/build/files.c	2011-10-10 14:14:25.000000000 +0300
@@ -809,6 +809,7 @@ static VFA_t virtualFileAttributes[] = {
 	{ "%readme",	0,	RPMFILE_README },
 	{ "%license",	0,	RPMFILE_LICENSE },
 	{ "%pubkey",	0,	RPMFILE_PUBKEY },
+	{ "%manifest",	0,	RPMFILE_SECMANIFEST },
 	{ NULL, 0, 0 }
 };
 
@@ -876,7 +877,7 @@ static rpmRC parseForSimple(rpmSpec spec
 	    if (fl->currentFlags & RPMFILE_DOC) {
 		rstrscat(&specialDocBuf, " ", s, NULL);
 	    } else
-	    if (fl->currentFlags & RPMFILE_PUBKEY)
+	    if (fl->currentFlags & (RPMFILE_PUBKEY|RPMFILE_SECMANIFEST))
 	    {
 		*fileName = s;
 	    } else {
@@ -1583,6 +1584,14 @@ static rpmRC processMetadataFile(Package
 	apkt = pgpArmorWrap(PGPARMOR_PUBKEY, pkt, pktlen);
 	break;
     }
+    case RPMTAG_SECMANIFEST:
+	if ((xx = rpmioSlurp(fn, &pkt, &pktlen)) != 0 || pkt == NULL) {
+	    rpmlog(RPMLOG_ERR, _("%s: Security manifest file read
failed.\n"), fn);
+	    goto exit;
+	}
+	apkt = b64encode(pkt, pktlen, -1);
+	rpmlog(RPMLOG_INFO, _("Aptk: %s\n"), apkt);
+	break;
     }
 
     if (!apkt) {
@@ -1834,7 +1843,9 @@ static rpmRC processPackageFiles(rpmSpec
 	    dupAttrRec(&fl.def_ar, def_specialDocAttrRec);
 	} else if (fl.currentFlags & RPMFILE_PUBKEY) {
 	    (void) processMetadataFile(pkg, &fl, fileName, RPMTAG_PUBKEYS);
-	} else {
+	} else if (fl.currentFlags & RPMFILE_SECMANIFEST) {
+	    (void) processMetadataFile(pkg, &fl, fileName,
RPMTAG_SECMANIFEST);
+	else {
 	    (void) processBinaryFile(pkg, &fl, fileName);
 	}
     }
diff -Nuarp '--exclude=.git' rpm/build/parsePreamble.c
rpm-security/build/parsePreamble.c
--- rpm/build/parsePreamble.c	2011-10-10 15:25:30.577900228 +0300
+++ rpm-security/build/parsePreamble.c	2011-10-10 14:26:26.000000000 +0300
@@ -924,6 +924,7 @@ static struct PreambleRec_s const preamb
     {RPMTAG_BUGURL,		0, 0, LEN_AND_STR("bugurl")},
     {RPMTAG_COLLECTIONS,	0, 0, LEN_AND_STR("collections")},
     {RPMTAG_ORDERFLAGS,		2, 0,
LEN_AND_STR("orderwithrequires")},
+    {RPMTAG_SECMANIFEST,	0, 0, LEN_AND_STR("manifest")},
     {0, 0, 0, 0}
 };
 
diff -Nuarp '--exclude=.git' rpm/build/rpmfc.c rpm-security/build/rpmfc.c
--- rpm/build/rpmfc.c	2011-10-10 15:25:30.581900243 +0300
+++ rpm-security/build/rpmfc.c	2011-10-10 14:34:24.000000000 +0300
@@ -664,81 +664,83 @@ void rpmfcPrint(const char * msg, rpmfc
     int dx;
     int fx;
 
-int nprovides;
-int nrequires;
+    int nprovides;
+    int nrequires;
 
     if (fp == NULL) fp = stderr;
 
     if (msg)
 	fprintf(fp, "===================================== %s\n", msg);
 
-nprovides = rpmdsCount(fc->provides);
-nrequires = rpmdsCount(fc->requires);
 
-    if (fc)
-    for (fx = 0; fx < fc->nfiles; fx++) {
-assert(fx < fc->fcdictx->nvals);
-	cx = fc->fcdictx->vals[fx];
-assert(fx < fc->fcolor->nvals);
-	fcolor = fc->fcolor->vals[fx];
-	ARGV_t fattrs = fc->fattrs[fx];
-
-	fprintf(fp, "%3d %s", fx, fc->fn[fx]);
-	if (fcolor != RPMFC_BLACK)
-		fprintf(fp, "\t0x%x", fc->fcolor->vals[fx]);
-	else
-		fprintf(fp, "\t%s", fc->cdict[cx]);
-	if (fattrs) {
-	    char *attrs = argvJoin(fattrs, ",");
-	    fprintf(fp, " [%s]", attrs);
-	    free(attrs);
-	} else {
-	    fprintf(fp, " [none]");
-	}
-	fprintf(fp, "\n");
-
-	if (fc->fddictx == NULL || fc->fddictn == NULL)
-	    continue;
-
-assert(fx < fc->fddictx->nvals);
-	dx = fc->fddictx->vals[fx];
-assert(fx < fc->fddictn->nvals);
-	ndx = fc->fddictn->vals[fx];
-
-	while (ndx-- > 0) {
-	    const char * depval;
-	    unsigned char deptype;
-	    unsigned ix;
-
-	    ix = fc->ddictx->vals[dx++];
-	    deptype = ((ix >> 24) & 0xff);
-	    ix &= 0x00ffffff;
-	    depval = NULL;
-	    switch (deptype) {
-	    default:
-assert(depval != NULL);
-		break;
-	    case 'P':
-		if (nprovides > 0) {
-assert(ix < nprovides);
-		    (void) rpmdsSetIx(fc->provides, ix-1);
-		    if (rpmdsNext(fc->provides) >= 0)
-			depval = rpmdsDNEVR(fc->provides);
+    if (fc) {
+	
+	nprovides = rpmdsCount(fc->provides);
+	nrequires = rpmdsCount(fc->requires);
+    	for (fx = 0; fx < fc->nfiles; fx++) {
+		assert(fx < fc->fcdictx->nvals);
+		cx = fc->fcdictx->vals[fx];
+		assert(fx < fc->fcolor->nvals);
+		fcolor = fc->fcolor->vals[fx];
+		ARGV_t fattrs = fc->fattrs[fx];
+
+		fprintf(fp, "%3d %s", fx, fc->fn[fx]);
+		if (fcolor != RPMFC_BLACK)
+			fprintf(fp, "\t0x%x", fc->fcolor->vals[fx]);
+		else
+			fprintf(fp, "\t%s", fc->cdict[cx]);
+		if (fattrs) {
+		    char *attrs = argvJoin(fattrs, ",");
+		    fprintf(fp, " [%s]", attrs);
+		    free(attrs);
+		} else {
+		    fprintf(fp, " [none]");
 		}
-		break;
-	    case 'R':
-		if (nrequires > 0) {
-assert(ix < nrequires);
-		    (void) rpmdsSetIx(fc->requires, ix-1);
-		    if (rpmdsNext(fc->requires) >= 0)
-			depval = rpmdsDNEVR(fc->requires);
+		fprintf(fp, "\n");
+
+		if (fc->fddictx == NULL || fc->fddictn == NULL)
+		    continue;
+
+		assert(fx < fc->fddictx->nvals);
+		dx = fc->fddictx->vals[fx];
+		assert(fx < fc->fddictn->nvals);
+		ndx = fc->fddictn->vals[fx];
+
+		while (ndx-- > 0) {
+		    const char * depval;
+		    unsigned char deptype;
+		    unsigned ix;
+
+		    ix = fc->ddictx->vals[dx++];
+		    deptype = ((ix >> 24) & 0xff);
+		    ix &= 0x00ffffff;
+		    depval = NULL;
+		    switch (deptype) {
+			    default:
+				assert(depval != NULL);
+				break;
+			    case 'P':
+				if (nprovides > 0) {
+					assert(ix < nprovides);
+				    	(void) rpmdsSetIx(fc->provides,
ix-1);
+				    	if (rpmdsNext(fc->provides) >= 0)
+						depval =
rpmdsDNEVR(fc->provides);
+				}
+				break;
+			    case 'R':
+				if (nrequires > 0) {
+					assert(ix < nrequires);
+				    	(void) rpmdsSetIx(fc->requires,
ix-1);
+				    	if (rpmdsNext(fc->requires) >= 0)
+						depval =
rpmdsDNEVR(fc->requires);
+				}
+				break;
+		    }
+	    	    if (depval)
+			fprintf(fp, "\t%s\n", depval);
 		}
-		break;
-	    }
-	    if (depval)
-		fprintf(fp, "\t%s\n", depval);
-	}
-    }
+    	}
+   }
 }
 
 rpmfc rpmfcFree(rpmfc fc)
diff -Nuarp '--exclude=.git' rpm/configure.ac rpm-security/configure.ac
--- rpm/configure.ac	2011-10-10 15:25:30.581900243 +0300
+++ rpm-security/configure.ac	2011-10-10 14:38:41.000000000 +0300
@@ -633,6 +633,68 @@ AC_SUBST(WITH_SELINUX_LIB)
 AC_SUBST(WITH_SEMANAGE_LIB)
 AM_CONDITIONAL(SELINUX,[test "$with_selinux" = yes])
 
+
+# msm
+WITH_MSM_LIB=
+WITH_MSM_INCLUDE=
+AC_ARG_WITH(msm, [AS_HELP_STRING([--with-msm],[build with msm support])],
+[case "$with_msm" in
+yes|no) ;;
+*) AC_MSG_ERROR([invalid argument to --with-msm])
+  ;;
+esac],
+[with_msm=no])
+
+AS_IF([test "$with_msm" = yes],[
+#  AC_CHECK_HEADER([libxml2/libxml/xmlreader.h],[
+    save_LIBS="$LIBS"
+    AC_CHECK_LIB([xml2],[xmlReaderForMemory],[],[
+      AC_MSG_ERROR([--with-msm given, but xmlReaderForMemory not found in
libxml2])])
+    LIBS="$save_LIBS"
+#  ],[
+#    AC_MSG_ERROR([--with-mssf given, but libxml2/libxml/xmlreader.h not
found])
+#  ])
+  AC_CHECK_HEADER([sys/capability.h],[
+    save_LIBS="$LIBS"
+    AC_CHECK_LIB([cap],[cap_set_file],[],[
+      AC_MSG_ERROR([--with-msm given, but cap_set_file not found in
libcap])])
+    LIBS="$save_LIBS"
+  ],[
+    AC_MSG_ERROR([--with-msm given, but sys/capability.h not found])
+  ])
+  AC_CHECK_HEADER([attr/xattr.h],[
+    save_LIBS="$LIBS"
+    AC_CHECK_LIB([attr],[setxattr],[],[
+      AC_MSG_ERROR([--with-msm given, but setxattr not found in libattr])])
+    LIBS="$save_LIBS"
+  ],[
+    AC_MSG_ERROR([--with-msm given, but attr/xattr.h not found])
+  ])
+  AC_CHECK_HEADER([uthash.h],[
+    save_LIBS="$LIBS"
+    LIBS="$save_LIBS"
+  ],[
+    AC_MSG_ERROR([--with-msm given, but uthash.h not found])
+  ])
+  AC_CHECK_HEADER([sys/smack.h],[
+     save_LIBS="$LIBS"
+    LIBS="$save_LIBS"
+   ],[
+     AC_MSG_ERROR([--with-msm given, but smack.h not found])
+   ])
+])
+
+AS_IF([test "$with_msm" = yes],[
+  AC_DEFINE(WITH_MSM, 1, [Build with msm support?])
+  WITH_MSM_LIB="`xml2-config --libs` -lcap -lattr -lsmack"
+  WITH_MSM_INCLUDE="`xml2-config --cflags`"
+])
+AC_SUBST(WITH_MSM_LIB)
+AC_SUBST(WITH_MSM_INCLUDE)
+AM_CONDITIONAL(MSM,[test "$with_msm" = yes])
+
+
+
 # libcap
 WITH_CAP_LIB=
 AC_ARG_WITH(cap, [AS_HELP_STRING([--with-cap],[build with capability
support])],
@@ -712,6 +774,11 @@ AS_IF([test "$enable_plugins" = yes],[
 ])
 AM_CONDITIONAL(ENABLE_PLUGINS,[test "$enable_plugins" = yes])
 
+AC_ARG_ENABLE(security, [AS_HELP_STRING([--disable-security],[build without
security plugin support])],,[enable_security=yes])
+AS_IF([test "$enable_security" = yes],[
+  AC_DEFINE(ENABLE_SECURITY, 1, [Build with security plugin support?])
+])
+AM_CONDITIONAL(ENABLE_SECURITY,[test "$enable_security" = yes])
 
 with_dmalloc=no
 AC_ARG_WITH(dmalloc, [AS_HELP_STRING([--with-dmalloc],[build with dmalloc
debugging support])])
@@ -814,5 +881,6 @@ AC_CONFIG_FILES([Makefile
  	tests/Makefile
  	plugins/Makefile
 	python/setup.py
+	security/Makefile
   ])
 AC_OUTPUT
diff -Nuarp '--exclude=.git' rpm/lib/fsm.c rpm-security/lib/fsm.c
--- rpm/lib/fsm.c	2011-10-10 15:25:30.601900346 +0300
+++ rpm-security/lib/fsm.c	2011-10-10 14:43:16.000000000 +0300
@@ -27,6 +27,7 @@
 #include "lib/rpmte_internal.h"	/* XXX rpmfs */
 #include "lib/rpmts_internal.h"	/* rpmtsSELabelFoo() only */
 #include "lib/rpmug.h"
+#include "lib/rpmsecurity.h" /* security hooks */
 
 #include "debug.h"
 
@@ -798,6 +799,11 @@ static int expandRegular(FSM_t fsm)
 	if (rc)
 	    goto exit;
 
+	/* Call security plugin to update file status. */
+	rc = rpmsecurityCallFsmUpdated(fsm);
+	if (rc)
+	    goto exit;
+
 	rc = fsmNext(fsm, FSM_WRITE);
 	if (rc)
 	    goto exit;
@@ -1065,7 +1071,7 @@ static int fsmMakeLinks(FSM_t fsm)
     rc = fsmMapPath(fsm);
     fsm->opath = fsm->path;
     fsm->path = NULL;
-    for (i = 0; i < fsm->li->nlink; i++) {
+    for (i = 0; fsm->li && i < fsm->li->nlink; i++) {
 	if (fsm->li->filex[i] < 0) continue;
 	if (fsm->li->createdPath == i) continue;
 
@@ -1652,6 +1658,13 @@ static int fsmStage(FSM_t fsm, fileStage
 		break;
 	    }
 
+	    /* Call security plugin to start up for a file. */
+	    rc = rpmsecurityCallFsmOpened(fsm);
+	    if (rc) {
+		(void) fsmNext(fsm, FSM_UNDO);
+		break;
+	    }
+
 	    /* Extract file from archive. */
 	    rc = fsmNext(fsm, FSM_PROCESS);
 	    if (rc) {
@@ -1663,6 +1676,8 @@ static int fsmStage(FSM_t fsm, fileStage
 	    (void) fsmNext(fsm, FSM_NOTIFY);
 
 	    rc = fsmNext(fsm, FSM_FINI);
+	    /* Call security plugin with return code to finish the file. */
+	    rc = rpmsecurityCallFsmClosed(fsm, rc);
 	    if (rc) {
 		break;
 	    }
diff -Nuarp '--exclude=.git' rpm/lib/Makefile.am
rpm-security/lib/Makefile.am
--- rpm/lib/Makefile.am	2011-10-10 15:25:30.597900320 +0300
+++ rpm-security/lib/Makefile.am	2011-10-10 14:47:40.000000000 +0300
@@ -36,7 +36,8 @@ librpm_la_SOURCES = \
 	verify.c rpmlock.c rpmlock.h misc.h \
 	rpmscript.h rpmscript.c legacy.c merge.c \
 	rpmchroot.c rpmchroot.h \
-	rpmplugins.c rpmplugins.h rpmug.c rpmug.h
+	rpmplugins.c rpmplugins.h rpmug.c rpmug.h \
+	rpmsecurity.c rpmsecurity.h
 
 librpm_la_LDFLAGS = -version-info 2:0:0
 
diff -Nuarp '--exclude=.git' rpm/lib/package.c rpm-security/lib/package.c
--- rpm/lib/package.c	2011-10-10 15:25:30.605900359 +0300
+++ rpm-security/lib/package.c	2011-10-10 14:50:26.000000000 +0300
@@ -17,6 +17,7 @@
 #include "rpmio/digest.h"
 #include "rpmio/rpmio_internal.h"	/* fd digest bits */
 #include "lib/header_internal.h"	/* XXX headerCheck */
+#include "lib/rpmsecurity.h" /* security hooks */
 
 #include "debug.h"
 
@@ -640,6 +641,9 @@ static rpmRC rpmpkgRead(rpmKeyring keyri
 
     /** @todo Implement disable/enable/warn/error/anal policy. */
     rc = rpmVerifySignature(keyring, &sigtd, dig, ctx, &msg);
+
+    /* Call security plugin to verify the signature. */
+    rc = rpmsecurityCallVerify(keyring, &sigtd, dig, rc);
 	
     switch (rc) {
     case RPMRC_OK:		/* Signature is OK. */
diff -Nuarp '--exclude=.git' rpm/lib/rpmfi.h rpm-security/lib/rpmfi.h
--- rpm/lib/rpmfi.h	2011-10-10 15:25:30.609900382 +0300
+++ rpm-security/lib/rpmfi.h	2011-10-10 14:53:35.000000000 +0300
@@ -62,6 +62,7 @@ enum rpmfileAttrs_e {
     RPMFILE_EXCLUDE	= (1 <<  9),	/*!< from %%exclude, internal */
     RPMFILE_UNPATCHED	= (1 << 10),	/*!< placeholder (SuSE) */
     RPMFILE_PUBKEY	= (1 << 11),	/*!< from %%pubkey */
+    RPMFILE_SECMANIFEST	= (1 << 12),	/*!< from %%manifest */
 };
 
 typedef rpmFlags rpmfileAttrs;
diff -Nuarp '--exclude=.git' rpm/lib/rpmscript.c
rpm-security/lib/rpmscript.c
--- rpm/lib/rpmscript.c	2011-10-10 15:25:30.617900423 +0300
+++ rpm-security/lib/rpmscript.c	2011-10-10 14:55:35.000000000 +0300
@@ -13,6 +13,7 @@
 
 #include "rpmio/rpmlua.h"
 #include "lib/rpmscript.h"
+#include "lib/rpmsecurity.h"
 
 #include "debug.h"
 
@@ -169,7 +170,8 @@ static void doScriptExec(int selinux, AR
 	}
 
 	if (xx == 0) {
-	    xx = execv(argv[0], argv);
+	    /* Exec the scriptlet through security plugin */
+	    xx = rpmsecurityCallScriptExec(argv);
 	}
     }
     _exit(127); /* exit 127 for compatibility with bash(1) */
@@ -291,7 +293,7 @@ exit:
     if (fn) {
 	if (!rpmIsDebug())
 	    unlink(fn);
-	free(fn);
+	if (fn) fn =_free(fn);
     }
     return rc;
 }
diff -Nuarp '--exclude=.git' rpm/lib/rpmsecurity.c
rpm-security/lib/rpmsecurity.c
--- rpm/lib/rpmsecurity.c	1970-01-01 02:00:00.000000000 +0200
+++ rpm-security/lib/rpmsecurity.c	2011-08-04 11:29:00.000000000 +0300
@@ -0,0 +1,269 @@
+#include "system.h"
+
+#include <rpm/rpmmacro.h>
+#include <rpm/rpmtypes.h>
+#include <rpm/rpmlog.h>
+#include <rpm/rpmstring.h>
+#include <rpm/rpmts.h>
+
+#include <rpm/rpmsecurity.h>
+
+#define STR1(x) #x
+#define STR(x) STR1(x)
+
+struct rpmSecurity_s {
+    void *handle;
+    rpmRC (*SECURITYHOOK_INIT_FUNC)(rpmts, const char *);
+    rpmRC (*SECURITYHOOK_FILE_CONFLICT_FUNC)(rpmts, rpmte, rpmfi, Header,
rpmfi, int);
+    rpmRC (*SECURITYHOOK_PRE_TSM_FUNC)(rpmts);
+    rpmRC (*SECURITYHOOK_VERIFY_FUNC)(rpmKeyring, rpmtd, pgpDig, rpmRC);
+    rpmRC (*SECURITYHOOK_PRE_PSM_FUNC)(rpmte);
+    rpmRC (*SECURITYHOOK_SCRIPT_EXEC_FUNC)(ARGV_const_t);
+    rpmRC (*SECURITYHOOK_FSM_OPENED_FUNC)(FSM_t);
+    rpmRC (*SECURITYHOOK_FSM_UPDATED_FUNC)(FSM_t);
+    rpmRC (*SECURITYHOOK_FSM_CLOSED_FUNC)(FSM_t, int);
+    rpmRC (*SECURITYHOOK_POST_PSM_FUNC)(rpmte, int);
+    rpmRC (*SECURITYHOOK_POST_TSM_FUNC)(rpmts);
+    rpmRC (*SECURITYHOOK_CLEANUP_FUNC)(void);
+    int count;
+    rpmts ts;
+};
+
+static rpmSecurity securityPlugin = NULL;
+
+rpmRC rpmsecurityCallInit(const char *opts);
+rpmRC rpmsecurityCallCleanup(void);
+
+#define RPMSECURITY_GET_HOOK_FUNC(hook)
\
+    *(void **)(&securityPlugin->hook) = dlsym(securityPlugin->handle,
STR(hook)); \
+    if ((error = dlerror()) != NULL) {					\
+	rpmlog(RPMLOG_ERR, _("Failed to resolve security plugin symbol %s:
%s\n"), STR(hook), error); \
+	goto fail;							\
+    }
+
+static rpmRC rpmsecurityAdd(const char *path, const char *opts, rpmts ts)
+{
+    char *error;
+
+    void *handle = dlopen(path, RTLD_LAZY);
+    if (!handle) {
+	rpmlog(RPMLOG_ERR, _("Failed to dlopen %s %s\n"), path, dlerror());
+	goto fail;
+    }
+
+    securityPlugin = xcalloc(1, sizeof(*securityPlugin));
+    if (!securityPlugin) {
+	rpmlog(RPMLOG_ERR, _("Failed to allocate security plugin %s\n"),
path);
+	goto fail;
+    }
+
+    securityPlugin->handle = handle;
+    securityPlugin->count++;
+    securityPlugin->ts = ts;
+
+    /* Security plugin really has to have all the hooks. This means that */

+    /* if the interface is changed, all plugins have to be changed which */
+    /* in general is not nice. However, a security plugin must be aware of
*/
+    /* all the hooks declaring empty functions if it doesn't need them. */
+    RPMSECURITY_GET_HOOK_FUNC(SECURITYHOOK_INIT_FUNC);
+    RPMSECURITY_GET_HOOK_FUNC(SECURITYHOOK_FILE_CONFLICT_FUNC);
+    RPMSECURITY_GET_HOOK_FUNC(SECURITYHOOK_PRE_TSM_FUNC);
+    RPMSECURITY_GET_HOOK_FUNC(SECURITYHOOK_VERIFY_FUNC);
+    RPMSECURITY_GET_HOOK_FUNC(SECURITYHOOK_PRE_PSM_FUNC);
+    RPMSECURITY_GET_HOOK_FUNC(SECURITYHOOK_SCRIPT_EXEC_FUNC);
+    RPMSECURITY_GET_HOOK_FUNC(SECURITYHOOK_FSM_OPENED_FUNC);
+    RPMSECURITY_GET_HOOK_FUNC(SECURITYHOOK_FSM_UPDATED_FUNC);
+    RPMSECURITY_GET_HOOK_FUNC(SECURITYHOOK_FSM_CLOSED_FUNC);
+    RPMSECURITY_GET_HOOK_FUNC(SECURITYHOOK_POST_PSM_FUNC);
+    RPMSECURITY_GET_HOOK_FUNC(SECURITYHOOK_POST_TSM_FUNC);
+    RPMSECURITY_GET_HOOK_FUNC(SECURITYHOOK_CLEANUP_FUNC);
+
+    return rpmsecurityCallInit(opts);
+
+ fail:
+    if (handle) dlclose(handle);
+    if (securityPlugin) free(securityPlugin);
+    return RPMRC_FAIL;
+}
+
+rpmRC rpmsecuritySetupPlugin(rpmts ts)
+{
+    char *path;
+    char *options;
+    int rc = RPMRC_FAIL;
+
+    if (securityPlugin) {
+	securityPlugin->count++;
+	return RPMRC_OK;
+    }
+
+    path = rpmExpand("%{?__security_plugin}", NULL);
+    if (!path || rstreq(path, "")) {
+#ifdef ENFORCE_SECURITY
+	rpmlog(RPMLOG_ERR, _("Failed to expand %%__security_plugin
macro\n"));
+#else
+	rpmlog(RPMLOG_INFO, _("Failed to expand %%__security_plugin
macro\n"));
+#endif
+	goto exit;
+    }
+
+    /* split the options from the path */
+#define SKIPSPACE(s)    { while (*(s) &&  risspace(*(s))) (s)++; }
+#define SKIPNONSPACE(s) { while (*(s) && !risspace(*(s))) (s)++; }
+    options = path;
+    SKIPNONSPACE(options);
+    if (risspace(*options)) {
+	*options = '\0';
+	options++;
+	SKIPSPACE(options);
+    }
+    if (*options == '\0') {
+	options = NULL;
+    }
+
+    rc = rpmsecurityAdd(path, options, ts);
+  exit:
+    if (path) _free(path);
+    return rc;
+}
+
+int rpmsecurityPluginAdded(void)
+{
+    return (securityPlugin != NULL);
+}
+
+rpmSecurity rpmsecurityFreePlugin()
+{
+    if (securityPlugin) {
+	securityPlugin->count--;
+	if (!securityPlugin->count) {
+	    rpmsecurityCallCleanup();
+	    dlclose(securityPlugin->handle);
+	    securityPlugin = _free(securityPlugin);
+	}
+    }
+    return securityPlugin;
+}
+
+#define RPMSECURITY_SET_HOOK_FUNC(hook)
\
+    hookFunc = securityPlugin->hook;					\
+    if (rpmtsFlags(securityPlugin->ts) & RPMTRANS_FLAG_TEST) {		\
+	return RPMRC_OK;						\
+    }									\
+    rpmlog(RPMLOG_DEBUG, "Security: calling hook %s in security plugin\n",
STR(hook));
+
+rpmRC rpmsecurityCallInit(const char *opts)
+{
+    rpmRC (*hookFunc)(rpmts, const char *);
+    RPMSECURITY_SET_HOOK_FUNC(SECURITYHOOK_INIT_FUNC);
+    return hookFunc(securityPlugin->ts, opts);
+}
+
+rpmRC rpmsecurityCallCleanup(void)
+{
+    rpmRC (*hookFunc)(void);
+    RPMSECURITY_SET_HOOK_FUNC(SECURITYHOOK_CLEANUP_FUNC);
+    return hookFunc();
+}
+
+rpmRC rpmsecurityCallPreTsm(rpmts ts)
+{
+    if (securityPlugin) {
+	rpmRC (*hookFunc)(rpmts);
+	RPMSECURITY_SET_HOOK_FUNC(SECURITYHOOK_PRE_TSM_FUNC);
+	return hookFunc(ts);
+    }
+    return RPMRC_OK;
+}
+
+rpmRC rpmsecurityCallPostTsm(rpmts ts)
+{
+    if (securityPlugin) {
+	rpmRC (*hookFunc)(rpmts);
+	RPMSECURITY_SET_HOOK_FUNC(SECURITYHOOK_POST_TSM_FUNC);
+	return hookFunc(ts);
+    }
+    return RPMRC_OK;
+}
+
+rpmRC rpmsecurityCallPrePsm(rpmte te)
+{
+    if (securityPlugin) {
+	rpmRC (*hookFunc)(rpmte);
+	RPMSECURITY_SET_HOOK_FUNC(SECURITYHOOK_PRE_PSM_FUNC);
+	return hookFunc(te);
+    }
+    return RPMRC_OK;
+}
+
+rpmRC rpmsecurityCallPostPsm(rpmte te, int rpmrc)
+{
+    if (securityPlugin) {
+	rpmRC (*hookFunc)(rpmte, int);
+	RPMSECURITY_SET_HOOK_FUNC(SECURITYHOOK_POST_PSM_FUNC);
+	return hookFunc(te, rpmrc);
+    }
+    return rpmrc;
+}
+
+rpmRC rpmsecurityCallScriptExec(ARGV_const_t argv)
+{
+    if (securityPlugin) {
+	rpmRC (*hookFunc)(ARGV_const_t);
+	RPMSECURITY_SET_HOOK_FUNC(SECURITYHOOK_SCRIPT_EXEC_FUNC);
+	return hookFunc(argv);
+    }
+    return execv(argv[0], argv);
+}
+
+rpmRC rpmsecurityCallFsmOpened(FSM_t fsm)
+{
+    if (securityPlugin) {
+	rpmRC (*hookFunc)(FSM_t);
+	RPMSECURITY_SET_HOOK_FUNC(SECURITYHOOK_FSM_OPENED_FUNC);
+	return hookFunc(fsm);
+    }
+    return RPMRC_OK;
+}
+
+rpmRC rpmsecurityCallFsmUpdated(FSM_t fsm)
+{
+    if (securityPlugin) {
+	rpmRC (*hookFunc)(FSM_t);
+	RPMSECURITY_SET_HOOK_FUNC(SECURITYHOOK_FSM_UPDATED_FUNC);
+	return hookFunc(fsm);
+    }
+    return RPMRC_OK;
+}
+
+rpmRC rpmsecurityCallFsmClosed(FSM_t fsm, int rpmrc)
+{
+    if (securityPlugin) {
+	rpmRC (*hookFunc)(FSM_t, int);
+	RPMSECURITY_SET_HOOK_FUNC(SECURITYHOOK_FSM_CLOSED_FUNC);
+	return hookFunc(fsm, rpmrc);
+    }
+    return rpmrc;
+}
+
+rpmRC rpmsecurityCallVerify(rpmKeyring keyring, rpmtd sigtd, 
+			    pgpDig dig, rpmRC rpmrc)
+{
+    if (securityPlugin) {
+	rpmRC (*hookFunc)(rpmKeyring, rpmtd, pgpDig, rpmRC);
+	RPMSECURITY_SET_HOOK_FUNC(SECURITYHOOK_VERIFY_FUNC);
+	return hookFunc(keyring, sigtd, dig, rpmrc);
+    }
+    return rpmrc;
+}
+
+rpmRC rpmsecurityCallFileConflict(rpmts ts, rpmte te, rpmfi fi,
+				  Header oldHeader, rpmfi oldFi, int rpmrc)
+{
+    if (securityPlugin) {
+	rpmRC (*hookFunc)(rpmts, rpmte, rpmfi, Header, rpmfi, int);
+	RPMSECURITY_SET_HOOK_FUNC(SECURITYHOOK_FILE_CONFLICT_FUNC);
+	return hookFunc(ts, te, fi, oldHeader, oldFi, rpmrc);
+    }
+    return rpmrc;
+}
diff -Nuarp '--exclude=.git' rpm/lib/rpmsecurity.h
rpm-security/lib/rpmsecurity.h
--- rpm/lib/rpmsecurity.h	1970-01-01 02:00:00.000000000 +0200
+++ rpm-security/lib/rpmsecurity.h	2011-10-07 11:55:42.000000000 +0300
@@ -0,0 +1,160 @@
+#ifndef _SECURITY_H
+#define _SECURITY_H
+
+#include <rpm/rpmtypes.h>
+#include <rpm/rpmpgp.h>
+#include <lib/fsm.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \ingroup rpmsecurity
+ *
+ * General flow of code in rpm:
+ *
+ * The first hook SECURITYHOOK_INIT_FUNC is called right after keyring is
+ * loaded and database indexes are opened.
+ *
+ * At the time rpm prepares packages for installation, it might call
+ * SECURITYHOOK_FILE_CONFLICT_FUNC if some new package has conflicting
files.
+ * Security plugin can then decide if overwrite is allowed or not. After
+ * conflict resolving rpm calls SECURITYHOOK_PRE_TSM_FUNC.
+ *
+ * The actual package processing starts by calling SECURITYHOOK_VERIFY_FUNC
+ * where security plugin can verify the package signature (right after rpm
+ * has done it's own signature verifying). 
+
+ * Then SECURITYHOOK_PRE_PSM_FUNC is called to start installing/removing 
+ * the package. In the beginning of installation process there may be call 
+ * to SECURITYHOOK_SCRIPT_EXEC_FUNC if package spec has a pre installation
+ * script. Then SECURITYHOOK_FSM_OPENED_FUNC, SECURITYHOOK_FSM_UPDATED_FUNC
+ * and SECURITYHOOK_FSM_CLOSED_FUNC are called for each installed file to
+ * make it possible to calculate hashes for the files (or use the sum
+ * in rpm package). At the end of installation process there may be call 
+ * to SECURITYHOOK_SCRIPT_EXEC_FUNC if package spec has a post installation
+ * script. Finally SECURITYHOOK_POST_PSM_FUNC is called to wrap up package 
+ * processing.
+ * 
+ * SECURITYHOOK_POST_TSM_FUNC is called when all packages have been
processed.
+ * 
+ * Finally SECURITYHOOK_CLEANUP_FUNC is called to free used resources.
+ */
+
+/** \ingroup rpmsecurity
+ * Add and open security plugin, calls SECURITYHOOK_INIT_FUNC.
+ * This is the place for the plugin to initialize itself, load
+ * possible configuration files etc.
+ * @param ts		ts element
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmsecuritySetupPlugin(rpmts ts);
+
+/** \ingroup rpmsecurity
+ * Call the security file conflict plugin hook.
+ * This hook is called whenever there is a file conflict.
+ * @param ts		transaction set
+ * @param te		transaction element
+ * @param fi		new file
+ * @param oldHeader	old header
+ * @param oldFi		old file
+ * @param rpmrc         success from RPM
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmsecurityCallFileConflict(rpmts ts, rpmte te, rpmfi fi,
+				  Header oldHeader, rpmfi oldFi, int rpmrc);
+
+/** \ingroup rpmsecurity
+ * Call the security pre tsm plugin hook.
+ * This hook is called before the transaction state machine is started.
+ * @param ts		transaction set
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmsecurityCallPreTsm(rpmts ts);
+
+/** \ingroup rpmsecurity
+ * Call the security verify plugin hook.
+ * This hook is called right after RPM has verified package signature.
+ * @param keyring	RPM keyring
+ * @param sigtd		signature tag
+ * @param dig		PGP digest
+ * @param rpmrc		success from RPM
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmsecurityCallVerify(rpmKeyring keyring, rpmtd sigtd, 
+			    pgpDig dig, rpmRC rpmrc);
+
+/** \ingroup rpmsecurity
+ * Call the security pre psm plugin hook.
+ * This hook is called before the package state machine is started.
+ * @param te		transaction element in question
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmsecurityCallPrePsm(rpmte te);
+
+/** \ingroup rpmsecurity
+ * Call the security script exec plugin hook.
+ * Script execution takes place in child process context.
+ * @param argv		script command line arguments
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmsecurityCallScriptExec(ARGV_const_t argv);
+
+/** \ingroup rpmsecurity
+ * Call the security file opened plugin hook.
+ * This hook is called before the file state machine is started.
+ * @param fsm		fsm in question
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmsecurityCallFsmOpened(FSM_t fsm);
+
+/** \ingroup rpmsecurity
+ * Call the security file updated plugin hook.
+ * This hook is called during the file state machine is running.
+ * @param fsm		fsm in question
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmsecurityCallFsmUpdated(FSM_t fsm);
+
+/** \ingroup rpmsecurity
+ * Call the security file closed plugin hook.
+ * This hook is called after the file state machine has finished.
+ * @param fsm		fsm in question
+ * @param rpmrc		success from RPM
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmsecurityCallFsmClosed(FSM_t fsm, int rpmrc);
+
+/** \ingroup rpmsecurity
+ * Call the security post psm plugin hook.
+ * This hook is called after the package state machine has finished.
+ * @param te		transaction element in question
+ * @param rpmrc		success from RPM
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmsecurityCallPostPsm(rpmte te, int rpmrc);
+
+/** \ingroup rpmsecurity
+ * Call the security post tsm plugin hook.
+ * This hook is called after the transaction state machine has finished.
+ * @param ts		transaction set
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmsecurityCallPostTsm(rpmts ts);
+
+/** \ingroup rpmsecurity
+ * Destroy security plugin structure, calls SECURITYHOOK_CLEANUP_FUNC.
+ * Plugin can save new state and new configuration in cleanup.
+ * @return		NULL always
+ */
+rpmSecurity rpmsecurityFreePlugin(void);
+
+/** \ingroup rpmsecurity
+ * Determine if a security plugin has been added already.
+ * @return		1 if security plugin has already been added, 0
otherwise
+ */
+int rpmsecurityPluginAdded(void);
+#ifdef __cplusplus
+}
+#endif
+#endif	/* _SECURITY_H */
diff -Nuarp '--exclude=.git' rpm/lib/rpmtag.h rpm-security/lib/rpmtag.h
--- rpm/lib/rpmtag.h	2011-10-10 15:25:30.617900423 +0300
+++ rpm-security/lib/rpmtag.h	2011-10-10 15:01:01.000000000 +0300
@@ -299,8 +299,8 @@ typedef enum rpmTag_e {
     RPMTAG_ORDERNAME		= 5035,	/* s[] */
     RPMTAG_ORDERVERSION		= 5036,	/* s[] */
     RPMTAG_ORDERFLAGS		= 5037,	/* i[] */
-    RPMTAG_MSSFMANIFEST		= 5038, /* s[] reservation
(unimplemented) */
-    RPMTAG_MSSFDOMAIN		= 5039, /* s[] reservation (unimplemented)
*/
+    RPMTAG_SECMANIFEST		= 5038, /* s[] reservation (unimplemented)
*/
+    RPMTAG_SECSWSOURCE		= 5039, /* s[] reservation (unimplemented)
*/
     RPMTAG_INSTFILENAMES	= 5040, /* s[] extension */
     RPMTAG_REQUIRENEVRS		= 5041, /* s[] extension */
     RPMTAG_PROVIDENEVRS		= 5042, /* s[] extension */
diff -Nuarp '--exclude=.git' rpm/lib/rpmte.c rpm-security/lib/rpmte.c
--- rpm/lib/rpmte.c	2011-10-10 15:25:30.617900423 +0300
+++ rpm-security/lib/rpmte.c	2011-10-10 15:02:43.000000000 +0300
@@ -14,6 +14,7 @@
 #include <rpm/rpmlog.h>
 
 #include "lib/rpmplugins.h"
+#include "lib/rpmsecurity.h"
 #include "lib/rpmte_internal.h"
 
 #include "debug.h"
@@ -912,7 +913,13 @@ int rpmteProcess(rpmte te, pkgGoal goal)
     }
 
     if (rpmteOpen(te, reset_fi)) {
-	failed = rpmpsmRun(te->ts, te, goal);
+	/* Call security plugin to set te for next operations */
+	failed = rpmsecurityCallPrePsm(te);
+	if (!failed) {
+	    failed = rpmpsmRun(te->ts, te, goal);
+	    /* Call security plugin to finish any te related tasks */
+	    failed = rpmsecurityCallPostPsm(te, failed);
+	}
 	rpmteClose(te, reset_fi);
     }
     
diff -Nuarp '--exclude=.git' rpm/lib/rpmts.c rpm-security/lib/rpmts.c
--- rpm/lib/rpmts.c	2011-10-10 15:25:30.621900442 +0300
+++ rpm-security/lib/rpmts.c	2011-10-10 15:03:38.000000000 +0300
@@ -24,6 +24,7 @@
 #include "lib/rpmal.h"
 #include "lib/rpmchroot.h"
 #include "lib/rpmplugins.h"
+#include "lib/rpmsecurity.h"
 #include "lib/rpmts_internal.h"
 #include "lib/rpmte_internal.h"
 #include "lib/misc.h"
@@ -629,6 +630,9 @@ rpmts rpmtsFree(rpmts ts)
 
     ts->plugins = rpmpluginsFree(ts->plugins);
 
+    /* Free security plugin here also. */
+    rpmsecurityFreePlugin();
+
     if (_rpmts_stats)
 	rpmtsPrintStats(ts);
 
diff -Nuarp '--exclude=.git' rpm/lib/rpmtypes.h rpm-security/lib/rpmtypes.h
--- rpm/lib/rpmtypes.h	2011-10-10 15:25:30.621900442 +0300
+++ rpm-security/lib/rpmtypes.h	2011-10-10 15:04:14.000000000 +0300
@@ -78,6 +78,7 @@ typedef struct rpmPubkey_s * rpmPubkey;
 typedef struct rpmKeyring_s * rpmKeyring;
 
 typedef struct rpmPlugins_s * rpmPlugins;
+typedef struct rpmSecurity_s * rpmSecurity;
 
 typedef struct rpmgi_s * rpmgi;
 
diff -Nuarp '--exclude=.git' rpm/lib/transaction.c
rpm-security/lib/transaction.c
--- rpm/lib/transaction.c	2011-10-10 15:25:30.625900467 +0300
+++ rpm-security/lib/transaction.c	2011-10-10 15:08:14.000000000 +0300
@@ -20,6 +20,7 @@
 #include "lib/rpmte_internal.h"	/* only internal apis */
 #include "lib/rpmts_internal.h"
 #include "rpmio/rpmhook.h"
+#include "lib/rpmsecurity.h"
 
 /* XXX FIXME: merge with existing (broken?) tests in system.h */
 /* portability fiddles */
@@ -358,6 +359,9 @@ static void handleInstInstalledFile(cons
 	    }
 	}
 
+	/* Call security plugin to check the file conflict. */
+	rConflicts = rpmsecurityCallFileConflict(ts, p, fi, otherHeader,
otherFi, rConflicts);
+
 	if (rConflicts) {
 	    char *altNEVR = headerGetAsString(otherHeader, RPMTAG_NEVRA);
 	    rpmteAddProblem(p, RPMPROB_FILE_CONFLICT, altNEVR, rpmfiFN(fi),
@@ -1421,6 +1425,13 @@ int rpmtsRun(rpmts ts, rpmps okProbs, rp
 	goto exit;
     }
 
+    /* Setup the security plugin */
+    if (rpmsecuritySetupPlugin(ts)) {
+#ifdef ENFORCE_SECURITY
+	goto exit;
+#endif
+    }
+
     rpmtsSetupCollections(ts);
 
     /* Check package set for problems */
@@ -1453,9 +1464,16 @@ int rpmtsRun(rpmts ts, rpmps okProbs, rp
     tsprobs = rpmpsFree(tsprobs);
     rpmtsCleanProblems(ts);
 
+    /* Call security plugin */
+    rpmsecurityCallPreTsm(ts);
+
     /* Actually install and remove packages, get final exit code */
     rc = rpmtsProcess(ts) ? -1 : 0;
 
+    /* Call security plugin */
+    rpmsecurityCallPostTsm(ts);
+
+
     /* Run post-transaction scripts unless disabled */
     if (!(rpmtsFlags(ts) & (RPMTRANS_FLAG_NOPOST))) {
 	rpmlog(RPMLOG_DEBUG, "running post-transaction scripts\n");
diff -Nuarp '--exclude=.git' rpm/macros.in rpm-security/macros.in
--- rpm/macros.in	2011-10-10 15:25:30.625900467 +0300
+++ rpm-security/macros.in	2011-10-10 15:09:08.000000000 +0300
@@ -1050,5 +1050,7 @@ done \
 %__collection_sepolicy		%{__plugindir}/sepolicy.so
 %__collection_sepolicy_flags	1
 
+%__security_plugin		%{__plugindir}/msm.so
+
 # \endverbatim
 #*/
diff -Nuarp '--exclude=.git' rpm/Makefile.am rpm-security/Makefile.am
--- rpm/Makefile.am	2011-10-10 15:25:30.573900202 +0300
+++ rpm-security/Makefile.am	2011-10-10 15:10:41.000000000 +0300
@@ -33,7 +33,11 @@ if HAVE_FAKECHROOT
 SUBDIRS += tests
 endif
 
-DIST_SUBDIRS = po misc luaext rpmio lib sign build python scripts fileattrs
doc tests plugins
+if ENABLE_SECURITY
+SUBDIRS += security
+endif
+
+DIST_SUBDIRS = po misc luaext rpmio lib sign build python scripts fileattrs
doc tests plugins security
 
 pkgconfigdir = $(libdir)/pkgconfig
 
@@ -87,6 +91,9 @@ pkginclude_HEADERS += build/rpmbuild.h
 pkginclude_HEADERS += build/rpmfc.h
 pkginclude_HEADERS += build/rpmspec.h
 
+pkginclude_HEADERS += lib/rpmplugins.h
+pkginclude_HEADERS += lib/rpmsecurity.h
+
 
 rpmbindir = `echo $(bindir) | $(SED) -e s,usr/bin,bin,`
 rpmbin_PROGRAMS = rpm
diff -Nuarp '--exclude=.git' rpm/preinstall.am rpm-security/preinstall.am
--- rpm/preinstall.am	2011-10-10 15:25:30.673900702 +0300
+++ rpm-security/preinstall.am	2011-10-10 15:12:54.000000000 +0300
@@ -114,6 +114,14 @@ include/rpm/rpmvf.h: lib/rpmvf.h include
 	$(INSTALL_DATA) $(top_srcdir)/lib/rpmvf.h include/rpm/rpmvf.h
 BUILT_SOURCES += include/rpm/rpmvf.h
 CLEANFILES += include/rpm/rpmvf.h
+include/rpm/rpmplugins.h: lib/rpmplugins.h include/rpm/$(dirstamp)
+	$(INSTALL_DATA) $(top_srcdir)/lib/rpmplugins.h
include/rpm/rpmplugins.h
+BUILT_SOURCES += include/rpm/rpmplugins.h
+CLEANFILES += include/rpm/rpmplugins.h
+include/rpm/rpmsecurity.h: lib/rpmsecurity.h include/rpm/$(dirstamp)
+	$(INSTALL_DATA) $(top_srcdir)/lib/rpmsecurity.h
include/rpm/rpmsecurity.h
+BUILT_SOURCES += include/rpm/rpmsecurity.h
+CLEANFILES += include/rpm/rpmsecurity.h
 include/rpm/rpmsign.h: sign/rpmsign.h include/rpm/$(dirstamp)
 	$(INSTALL_DATA) $(top_srcdir)/sign/rpmsign.h include/rpm/rpmsign.h
 BUILT_SOURCES += include/rpm/rpmsign.h
diff -Nuarp '--exclude=.git' rpm/rpmio/base64.c rpm-security/rpmio/base64.c
--- rpm/rpmio/base64.c	2011-10-10 15:25:30.681900744 +0300
+++ rpm-security/rpmio/base64.c	2011-10-10 15:17:31.000000000 +0300
@@ -104,7 +104,7 @@ static int base64_decode_value(unsigned
 {
 	static const int decoding[] =
{62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4
,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1
,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,
51};
 	value_in -= 43;
-	if (value_in > sizeof(decoding)/sizeof(int))
+	if (value_in >= sizeof(decoding)/sizeof(int))
 		return -1;
 	return decoding[value_in];
 }
@@ -165,6 +165,7 @@ int b64decode(const char *in, void **out
 {
 	size_t outcnt = 0;
 	const char *inptr = in;
+	char *outptr;
 
 	*out = NULL;
 
@@ -189,12 +190,13 @@ int b64decode(const char *in, void **out
 	
 	outcnt = (outcnt / 4) * 3;
 	
-	*out = malloc(outcnt + 1); /* base64_decode_block can write one
extra character */
+	*out = outptr = malloc(outcnt + 2); /* base64_decode_block can write
one extra character, reserve one more for null termination */
 	
 	if (*out == NULL)
 		return 4;
 	
 	*outlen = base64_decode_block(in, inptr - in, *out);
+	outptr[*outlen] = '\0'; /* null terminate */
 
 	return 0;
 }
diff -Nuarp '--exclude=.git' rpm/rpmio/macro.c rpm-security/rpmio/macro.c
--- rpm/rpmio/macro.c	2011-10-10 15:25:30.685900756 +0300
+++ rpm-security/rpmio/macro.c	2011-10-10 15:19:27.000000000 +0300
@@ -617,7 +617,7 @@ doDefine(MacroBuf mb, const char * se, i
 
 exit:
     _free(buf);
-    _free(ebody);
+    if (ebody) _free(ebody);
     return se;
 }
 
diff -Nuarp '--exclude=.git' rpm/rpmio/rpmmalloc.c
rpm-security/rpmio/rpmmalloc.c
--- rpm/rpmio/rpmmalloc.c	2011-10-10 15:25:30.689900777 +0300
+++ rpm-security/rpmio/rpmmalloc.c	2011-10-10 15:20:15.000000000 +0300
@@ -80,6 +80,6 @@ char * rstrdup (const char *str)
 
 void * rfree (void *ptr)
 {
-    free(ptr);
+    if (ptr) free(ptr);
     return NULL;
 }
diff -Nuarp '--exclude=.git' rpm/security/Makefile.am
rpm-security/security/Makefile.am
--- rpm/security/Makefile.am	1970-01-01 02:00:00.000000000 +0200
+++ rpm-security/security/Makefile.am	2011-09-23 11:11:22.000000000 +0300
@@ -0,0 +1,24 @@
+# Makefile for rpm library.
+
+include $(top_srcdir)/rpm.am
+
+AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir) -I$(top_builddir)/include/
+AM_CPPFLAGS += -I$(top_srcdir)/misc
+AM_CPPFLAGS += -DLOCALEDIR="\"$(localedir)\""
+AM_CPPFLAGS += -DSYSCONFDIR="\"$(sysconfdir)\""
+AM_CPPFLAGS += -DLOCALSTATEDIR="\"$(localstatedir)\""
+AM_CPPFLAGS += -DLIBRPMALIAS_FILENAME="\"rpmpopt-${VERSION}\""
+if MSM
+AM_CPPFLAGS += @WITH_MSM_INCLUDE@
+endif
+AM_LDFLAGS = -avoid-version -module -shared
+
+pluginsdir = $(libdir)/rpm-plugins
+
+if MSM
+plugins_LTLIBRARIES = msm.la
+endif
+if MSM
+msm_la_SOURCES = security.h msm.h msm.c msmconfig.c msmmanifest.c
msmxattr.c msmmatch.c
+msm_la_LIBADD = $(top_builddir)/lib/librpm.la
$(top_builddir)/rpmio/librpmio.la  @WITH_MSM_LIB@
+endif



-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 7220 bytes
Desc: not available
URL: <http://lists.rpm.org/pipermail/rpm-maint/attachments/20111010/223f9db0/attachment-0001.p7s>


More information about the Rpm-maint mailing list