summaryrefslogtreecommitdiff
path: root/packaging
diff options
context:
space:
mode:
authorHyungKyu Song <hk76.song@samsung.com>2013-02-16 01:03:32 +0900
committerHyungKyu Song <hk76.song@samsung.com>2013-02-16 01:03:32 +0900
commit365d51246cf71556ecbb49f1fc6592262d4d4d77 (patch)
tree79d5c20a494622eb084de831a2a51530cd421e33 /packaging
parentb7a3bffb8e0341b7e4ef69def268bca3a7f279ff (diff)
downloadrpm-tizen_2.0.tar.gz
rpm-tizen_2.0.tar.bz2
rpm-tizen_2.0.zip
Diffstat (limited to 'packaging')
-rw-r--r--packaging/Makefile6
-rw-r--r--packaging/autodeps.diff261
-rw-r--r--packaging/beecrypt-4.1.2.diff46
-rw-r--r--packaging/beecrypt-4.1.2.tar.bz2bin0 -> 563414 bytes
-rw-r--r--packaging/build_pack_4.9.1_fix.patch39
-rw-r--r--packaging/buildidprov.diff54
-rw-r--r--packaging/db-4.8.30.tar.gzbin0 -> 22887305 bytes
-rw-r--r--packaging/db.diff82
-rw-r--r--packaging/debugsource-package.diff73
-rw-r--r--packaging/debugsubpkg.diff321
-rw-r--r--packaging/device-sec-policy48
-rw-r--r--packaging/disableperl.patch18
-rw-r--r--packaging/eu-strip.patch69
-rw-r--r--packaging/fileattrs.diff46
-rw-r--r--packaging/find-docs.sh32
-rw-r--r--packaging/finddebuginfo.diff119
-rw-r--r--packaging/firmware.diff37
-rw-r--r--packaging/fontprovides.diff50
-rw-r--r--packaging/lib_rpmdb_4.9.1_fix.patch78
-rw-r--r--packaging/libsymlink.attr4
-rw-r--r--packaging/macros312
-rw-r--r--packaging/mimetype.diff24
-rw-r--r--packaging/no_rep_autop.diff12
-rw-r--r--packaging/optflags.patch77
-rw-r--r--packaging/pythondeps.diff44
-rw-r--r--packaging/remove-translations.patch20
-rw-r--r--packaging/rpm-4.5.90-gstreamer-provides.patch16
-rw-r--r--packaging/rpm-4.5.90-pkgconfig-path.patch13
-rw-r--r--packaging/rpm-4.7.90-devel-autodep.patch157
-rw-r--r--packaging/rpm-4.8.0-tilde.patch61
-rw-r--r--packaging/rpm-4.9.0-tizen-arm.patch88
-rw-r--r--packaging/rpm-beecrypt.diff1725
-rw-r--r--packaging/rpm-gst-provides.patch14
-rw-r--r--packaging/rpm-macros.patch57
-rw-r--r--packaging/rpm-python.manifest5
-rw-r--r--packaging/rpm-python.spec78
-rw-r--r--packaging/rpm-shorten-changelog.patch92
-rw-r--r--packaging/rpm.changes117
-rw-r--r--packaging/rpm.manifest5
-rw-r--r--packaging/rpm.spec378
-rw-r--r--packaging/rpmbuild_4.9.1_fix.patch24
-rw-r--r--packaging/rpmbuild_rpmfc_4.9.1_fix.patch158
-rw-r--r--packaging/rpmio_base64_4.9.1_fix.patch48
-rw-r--r--packaging/rpmlib_format_value_4.9.1_fix.patch40
-rw-r--r--packaging/security_4.9.1.patch5575
45 files changed, 10523 insertions, 0 deletions
diff --git a/packaging/Makefile b/packaging/Makefile
new file mode 100644
index 0000000..f1f6486
--- /dev/null
+++ b/packaging/Makefile
@@ -0,0 +1,6 @@
+PKG_NAME := rpm
+SPECFILE = $(addsuffix .spec, $(PKG_NAME))
+YAMLFILE = $(addsuffix .yaml, $(PKG_NAME))
+
+include /usr/share/packaging-tools/Makefile.common
+
diff --git a/packaging/autodeps.diff b/packaging/autodeps.diff
new file mode 100644
index 0000000..bbe7715
--- /dev/null
+++ b/packaging/autodeps.diff
@@ -0,0 +1,261 @@
+--- ./autodeps/linux.prov.orig 2011-07-12 11:28:13.000000000 +0000
++++ ./autodeps/linux.prov 2011-07-18 16:47:39.000000000 +0000
+@@ -2,60 +2,72 @@
+
+ # This script reads filenames from STDIN and outputs any relevant provides
+ # information that needs to be included in the package.
++IFS=$'\n'
++filelist=($(cat))
+
+-filelist=`sed "s/['\"]/\\\&/g"`
+-
+-solist=$(echo $filelist | grep "\\.so" | grep -v "^/lib/ld.so" | \
+- xargs file -L 2>/dev/null | grep "ELF.*shared object" | cut -d: -f1)
++solist=($(printf "%s\n" "${filelist[@]}" | grep "\\.so" | grep -v "^/lib/ld.so" | \
++ tr '\n' '\0' | xargs -0 -r file -L | grep "ELF.*shared object" | \
++ cut -d: -f1))
+ pythonlist=
+ tcllist=
++monolist=($(printf "%s\n" "${filelist[@]}" | egrep "\\.(exe|dll)\$"))
+
+ #
+ # --- Alpha does not mark 64bit dependencies
+ case `uname -m` in
+- alpha*) mark64="" ;;
+- *) mark64="()(64bit)" ;;
++ alpha*) mark64=false ;;
++ *) mark64=true ;;
+ esac
+
+ #
+ # --- Library sonames and weak symbol versions (from glibc).
+-for f in $solist; do
+- soname=$(objdump -p $f | awk '/SONAME/ {print $2}')
++for f in "${solist[@]}"; do
++ soname=$(objdump -p "$f" | awk '/SONAME/ {print $2}')
++ [ -n "$soname" -a -L "$f" ] && continue
++ [ -z "$soname" ] && soname="${f##*/}"
+
+- lib64=`if file -L $f 2>/dev/null | \
+- grep "ELF 64-bit" >/dev/null; then echo "$mark64"; fi`
+- if [ "$soname" != "" ]; then
+- if [ ! -L $f ]; then
+- echo $soname$lib64
+- objdump -p $f | awk '
+- BEGIN { START=0 ; }
+- /Version definitions:/ { START=1; }
+- /^[0-9]/ && (START==1) { print $4; }
+- /^$/ { START=0; }
+- ' | \
+- grep -v $soname | \
+- while read symbol ; do
+- echo "$soname($symbol)`echo $lib64 | sed 's/()//'`"
+- done
+- fi
++ if $mark64 && file -L "$f" 2>/dev/null | grep "ELF 64-bit" >/dev/null; then
++ lib64="()(64bit)" slib64="(64bit)"
+ else
+- echo ${f##*/}$lib64
++ lib64= slib64=
+ fi
++ echo "$soname$lib64"
++ objdump -p "$f" | awk '
++ BEGIN { START=0 ; }
++ /Version definitions:/ { START=1; }
++ /^[0-9]/ && (START==1) { print $4; }
++ /^$/ { START=0; }
++ ' | \
++ while read symbol ; do
++ echo "$soname($symbol)$slib64"
++ done
+ done | sort -u
+
+ #
+ # --- Perl modules.
+ [ -x /usr/lib/rpm/perl.prov ] &&
+- echo $filelist | tr '[:blank:]' \\n | grep '\.pm$' | /usr/lib/rpm/perl.prov | sort -u
++ printf "%s\n" "${filelist[@]}" | grep '\.pm$' | /usr/lib/rpm/perl.prov | sort -u
+
+ #
+ # --- Python modules.
+ [ -x /usr/lib/rpm/python.prov -a -n "$pythonlist" ] &&
+- echo $pythonlist | tr '[:blank:]' \\n | /usr/lib/rpm/python.prov | sort -u
++ printf "%s\n" "${pythonlist[@]}" | /usr/lib/rpm/python.prov | sort -u
+
+ #
+ # --- Tcl modules.
+ [ -x /usr/lib/rpm/tcl.prov -a -n "$tcllist" ] &&
+- echo $tcllist | tr '[:blank:]' \\n | /usr/lib/rpm/tcl.prov | sort -u
++ printf "%s\n" "${tcllist[@]}" | /usr/lib/rpm/tcl.prov | sort -u
++
++#
++# --- Mono exes/dlls
++: ${MONO_PREFIX=/usr}
++if [ -x $MONO_PREFIX/bin/mono -a -n "$monolist" ] ; then
++ printf "%s\n" "${monolist[@]}" | MONO_PATH=$MONO_PREFIX/lib${MONO_PATH:+:$MONO_PATH} prefix=$MONO_PREFIX $MONO_PREFIX/bin/mono-find-provides || echo "WARNING: MONO RPM PROVIDES WERE NOT GENERATED FOR THIS BUILD!!" 1>&2
++fi
++
++#
++# --- Kernel module exported symbols
++[ -x /usr/lib/rpm/find-provides.ksyms ] &&
++ printf "%s\n" "${filelist[@]}" | /usr/lib/rpm/find-provides.ksyms "$@"
+
+ exit 0
+--- ./autodeps/linux.req.orig 2011-07-15 09:32:41.000000000 +0000
++++ ./autodeps/linux.req 2011-07-18 16:51:24.000000000 +0000
+@@ -18,20 +18,21 @@ fi
+
+ #
+ # --- Grab the file manifest and classify files.
+-#filelist=`sed "s/['\"]/\\\&/g"`
+-filelist=`sed "s/[]['\"*?{}]/\\\\\&/g"`
+-exelist=`echo $filelist | xargs -r file | \
++#filelist=`sed "s/[]['\"*?{}]/\\\\\&/g"`
++filelist=($(grep -Ev '/usr/doc/|/usr/share/doc/'))
++exelist=($(printf "%s\0" "${filelist[@]}" | xargs -0 -r file | \
+ grep -Ev ":.* (commands|script)[, ]" | \
+- grep ":.*executable" | cut -d: -f1`
+-scriptlist=`echo $filelist | xargs -r file | \
+- grep -E ":.* (commands|script)[, ]" | cut -d: -f1`
+-liblist=`echo $filelist | xargs -r file | \
+- grep ":.*shared object" | cut -d : -f1`
++ grep ":.*executable" | cut -d: -f1))
++scriptlist=($(printf "%s\0" "${filelist[@]}" | xargs -0 -r file | \
++ grep -E ":.* (commands|script)[, ]" | cut -d: -f1))
++liblist=($(printf "%s\0" "${filelist[@]}" | xargs -0 -r file | \
++ grep ":.*shared object" | cut -d : -f1))
+
+-interplist=
+-perllist=
+-pythonlist=
+-tcllist=
++interplist=()
++perllist=()
++pythonlist=()
++tcllist=()
++monolist=($(printf "%s\n" "${filelist[@]}" | egrep "\\.(exe|dll)(\\.config)?\$"))
+
+ #
+ # --- Alpha does not mark 64bit dependencies
+@@ -43,12 +44,12 @@ esac
+ if [ "$needed" -eq 0 ]; then
+ #
+ # --- Executable dependency sonames.
+- for f in $exelist; do
+- [ -r $f -a -x $f ] || continue
+- lib64=`if file -L $f 2>/dev/null | \
++ for f in "${exelist[@]}"; do
++ [ -r "$f" -a -x "$f" ] || continue
++ lib64=`if file -L "$f" 2>/dev/null | \
+ grep "ELF 64-bit" >/dev/null; then echo "$mark64"; fi`
+- ldd $f | awk '/=>/ {
+- if ($1 !~ /libNoVersion.so/ && $1 !~ /4[um]lib.so/ && $1 !~ /libredhat-kernel.so/) {
++ ldd "$f" | awk '/=>/ {
++ if ($1 !~ /libNoVersion.so/ && $1 !~ /4[um]lib.so/ && $1 !~ /linux-gate.so/) {
+ gsub(/'\''"/,"\\&",$1);
+ printf "%s'$lib64'\n", $1
+ }
+@@ -57,12 +58,12 @@ if [ "$needed" -eq 0 ]; then
+
+ #
+ # --- Library dependency sonames.
+- for f in $liblist; do
+- [ -r $f ] || continue
+- lib64=`if file -L $f 2>/dev/null | \
++ for f in "${liblist[@]}"; do
++ [ -r "$f" ] || continue
++ lib64=`if file -L "$f" 2>/dev/null | \
+ grep "ELF 64-bit" >/dev/null; then echo "$mark64"; fi`
+- ldd $f | awk '/=>/ {
+- if ($1 !~ /libNoVersion.so/ && $1 !~ /4[um]lib.so/ && $1 !~ /libredhat-kernel.so/) {
++ ldd "$f" | awk '/=>/ {
++ if ($1 !~ /libNoVersion.so/ && $1 !~ /4[um]lib.so/ && $1 !~ /linux-gate.so/) {
+ gsub(/'\''"/,"\\&",$1);
+ printf "%s'$lib64'\n", $1
+ }
+@@ -72,30 +73,30 @@ fi
+
+ #
+ # --- Script interpreters.
+-for f in $scriptlist; do
+- [ -r $f -a -x $f ] || continue
+- interp=`head -n 1 $f | sed -e 's/^\#\![ ]*//' | cut -d" " -f1`
+- interplist="$interplist $interp"
++for f in "${scriptlist[@]}"; do
++ [ -r "$f" -a -x "$f" ] || continue
++ interp=`head -n 1 "$f" | sed -ne 's/^\#\![ ]*//p' | cut -d" " -f1`
++ interplist=("${interplist[@]}" "$interp")
+ case $interp in
+- */perl) perllist="$perllist $f" ;;
++ */perl) perllist=("${perllist[@]}" "$f") ;;
+ esac
+ done
+-[ -n "$interplist" ] && { echo "$interplist" | tr '[:blank:]' \\n | sort -u ; }
++[ -n "$interplist" ] && { printf "%s\n" "${interplist[@]}" | sort -u ; }
+
+ #
+ # --- Add perl module files to perllist.
+-for f in $filelist; do
+- [ -r $f -a "${f%.pm}" != "${f}" ] && perllist="$perllist $f"
++for f in "${filelist[@]}"; do
++ [ -r "$f" -a "${f%.pm}" != "${f}" ] && perllist=("${perllist[@]}" "$f")
+ done
+
+ #
+ # --- Weak symbol versions (from glibc).
+ [ -n "$mark64" ] && mark64="(64bit)"
+-for f in $liblist $exelist ; do
+- [ -r $f ] || continue
+- lib64=`if file -L $f 2>/dev/null | \
++for f in "${liblist[@]}" "${exelist[@]}" ; do
++ [ -r "$f" ] || continue
++ lib64=`if file -L "$f" 2>/dev/null | \
+ grep "ELF 64-bit" >/dev/null; then echo "$mark64"; fi`
+- objdump -p $f | awk 'BEGIN { START=0; LIBNAME=""; needed='$needed'; }
++ objdump -p "$f" | awk 'BEGIN { START=0; LIBNAME=""; needed='$needed'; }
+ /^$/ { START=0; }
+ /^Dynamic Section:$/ { START=1; }
+ (START==1) && /NEEDED/ {
+@@ -112,7 +113,7 @@ for f in $liblist $exelist ; do
+ sub(/:/, "", $3);
+ LIBNAME=$3;
+ }
+- (START==2) && (LIBNAME!="") && ($4!="") && (($4~/^GLIBC_*/) || ($4~/^GCC_*/)) {
++ (START==2) && (LIBNAME!="") && ($4!="") {
+ print LIBNAME "(" $4 ")'$lib64'";
+ }
+ '
+@@ -120,17 +121,29 @@ done | sort -u
+
+ #
+ # --- Perl modules.
+-[ -x /usr/lib/rpm/perl.req -a -n "$perllist" ] && \
+- echo $perllist | tr '[:blank:]' \\n | /usr/lib/rpm/perl.req | sort -u
++#[ -x /usr/lib/rpm/perl.req -a -n "$perllist" ] && \
++# printf "%s\n" "${perllist[@]}" | /usr/lib/rpm/perl.req | sort -u
+
+ #
+ # --- Python modules.
+ [ -x /usr/lib/rpm/python.req -a -n "$pythonlist" ] && \
+- echo $pythonlist | tr '[:blank:]' \\n | /usr/lib/rpm/python.req | sort -u
++ printf "%s\n" "${pythonlist[@]}" | /usr/lib/rpm/python.req | sort -u
+
+ #
+ # --- Tcl modules.
+ [ -x /usr/lib/rpm/tcl.req -a -n "$tcllist" ] && \
+- echo $tcllist | tr '[:blank:]' \\n | /usr/lib/rpm/tcl.req | sort -u
++ printf "%s\n" "${tcllist[@]}" | /usr/lib/rpm/tcl.req | sort -u
++
++#
++# --- Mono exes/dlls
++: ${MONO_PREFIX=/usr}
++if [ -x $MONO_PREFIX/bin/mono -a -n "$monolist" ] ; then
++ printf "%s\n" "${monolist[@]}" | MONO_PATH=$MONO_PREFIX/lib${MONO_PATH:+:$MONO_PATH} prefix=$MONO_PREFIX $MONO_PREFIX/bin/mono-find-requires || echo "WARNING: MONO RPM REQUIRES WERE NOT GENERATED FOR THIS BUILD!!" 1>&2
++fi
++
++#
++# --- Kernel module imported symbols
++[ -x ${0%/*}/find-requires.ksyms ] &&
++ printf "%s\n" "${filelist[@]}" | ${0%/*}/find-requires.ksyms "$@"
+
+ exit 0
diff --git a/packaging/beecrypt-4.1.2.diff b/packaging/beecrypt-4.1.2.diff
new file mode 100644
index 0000000..6f9c261
--- /dev/null
+++ b/packaging/beecrypt-4.1.2.diff
@@ -0,0 +1,46 @@
+--- beecrypt-4.1.2/Makefile.am.orig 2004-12-22 07:06:31.000000000 +0000
++++ beecrypt-4.1.2/Makefile.am 2006-11-24 14:08:27.000000000 +0000
+@@ -49,7 +49,7 @@ libaltdir=$(prefix)/lib@LIBALT@
+
+ libalt_LTLIBRARIES = libbeecrypt.la
+
+-libbeecrypt_la_SOURCES = aes.c base64.c beecrypt.c blockmode.c blockpad.c blowfish.c dhaes.c dldp.c dlkp.c dlpk.c dlsvdp-dh.c dsa.c elgamal.c endianness.c entropy.c fips186.c hmac.c hmacmd5.c hmacsha1.c hmacsha256.c md5.c hmacsha384.c hmacsha512.c memchunk.c mp.c mpbarrett.c mpnumber.c mpprime.c mtprng.c pkcs1.c pkcs12.c rsa.c rsakp.c rsapk.c sha1.c sha256.c sha384.c sha512.c sha_k.c timestamp.c cppglue.cxx
++libbeecrypt_la_SOURCES = aes.c base64.c beecrypt.c blockmode.c blockpad.c blowfish.c dhaes.c dldp.c dlkp.c dlpk.c dlsvdp-dh.c dsa.c elgamal.c endianness.c entropy.c fips186.c hmac.c hmacmd5.c hmacsha1.c hmacsha256.c md5.c hmacsha384.c hmacsha512.c memchunk.c mp.c mpbarrett.c mpnumber.c mpprime.c mtprng.c pkcs1.c pkcs12.c rsa.c rsakp.c rsapk.c sha1.c sha256.c sha384.c sha512.c sha_k.c timestamp.c
+ libbeecrypt_la_DEPENDENCIES = $(BEECRYPT_OBJECTS)
+ libbeecrypt_la_LIBADD = aesopt.lo blowfishopt.lo mpopt.lo sha1opt.lo
+ libbeecrypt_la_LDFLAGS = -no-undefined -version-info $(LIBBEECRYPT_LT_CURRENT):$(LIBBEECRYPT_LT_REVISION):$(LIBBEECRYPT_LT_AGE)
+@@ -62,5 +62,11 @@ EXTRA_DIST = BENCHMARKS BUGS CONTRIBUTOR
+
+ DISTCLEANFILES = mpopt.s aesopt.s blowfishopt.s sha1opt.s
+
++BUILT_SOURCES = listobjs
++
++.PHONY: listobjs
++listobjs:
++ @echo $(libbeecrypt_la_OBJECTS) $(libbeecrypt_la_LIBADD) > $@
++
+ bench:
+ (cd tests && $(MAKE) $(AM_MAKEFLAGS) bench)
+--- beecrypt-4.1.2/base64.c.orig 2004-12-19 20:21:04.000000000 +0000
++++ beecrypt-4.1.2/base64.c 2006-11-24 14:08:27.000000000 +0000
+@@ -253,7 +253,6 @@ char* b64encode(const void* data, size_t
+ unsigned c;
+
+ if (s == NULL) return NULL;
+- if (*s == '\0') return calloc(1, sizeof(*t));
+
+ if (ns == 0) ns = strlen((const char*) s);
+ nt = ((ns + 2) / 3) * 4;
+--- beecrypt-4.1.2/c++/io/DataOutputStream.cxx.orig 2004-11-04 12:38:15.000000000 +0000
++++ beecrypt-4.1.2/c++/io/DataOutputStream.cxx 2006-11-24 14:09:35.000000000 +0000
+@@ -126,8 +126,8 @@ void DataOutputStream::writeLong(javalon
+ void DataOutputStream::writeChar(javaint v) throw (IOException)
+ {
+ _lock.lock();
+- out.write((v >> 8) && 0xff);
+- out.write((v ) && 0xff);
++ out.write((v >> 8) & 0xff);
++ out.write((v ) & 0xff);
+ written += 2;
+ _lock.unlock();
+ }
diff --git a/packaging/beecrypt-4.1.2.tar.bz2 b/packaging/beecrypt-4.1.2.tar.bz2
new file mode 100644
index 0000000..4a839bc
--- /dev/null
+++ b/packaging/beecrypt-4.1.2.tar.bz2
Binary files differ
diff --git a/packaging/build_pack_4.9.1_fix.patch b/packaging/build_pack_4.9.1_fix.patch
new file mode 100644
index 0000000..15eac53
--- /dev/null
+++ b/packaging/build_pack_4.9.1_fix.patch
@@ -0,0 +1,39 @@
+From 312524af520d725d65722006c88b75ac14d37ec4 Mon Sep 17 00:00:00 2001
+From: Elena, Reshetova <elena.reshetova@intel.com>
+Date: Mon, 20 Feb 2012 15:44:34 +0200
+Subject: [PATCH] Fix for build_pack functionality
+
+---
+ build/pack.c | 6 ++++--
+ 1 files changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/build/pack.c b/build/pack.c
+index 981a03e..34e260d 100644
+--- a/build/pack.c
++++ b/build/pack.c
+@@ -48,8 +48,10 @@ static rpmRC cpio_doio(FD_t fdo, Header h, CSA_t csa,
+ int xx, i;
+
+ { char *fmode = rpmExpand(fmodeMacro, NULL);
+- if (!(fmode && fmode[0] == 'w'))
++ if (!(fmode && fmode[0] == 'w')) {
++ if (fmode) free(fmode);
+ fmode = xstrdup("w9.gzdio");
++ }
+ (void) Fflush(fdo);
+ cfd = Fdopen(fdDup(Fileno(fdo)), fmode);
+ fmode = _free(fmode);
+@@ -142,9 +144,9 @@ static StringBuf addFileToTagAux(rpmSpec spec,
+ }
+ appendStringBuf(sb, buf);
+ }
+- (void) fclose(f);
+
+ exit:
++ if (f) fclose(f);
+ free(fn);
+
+ return sb;
+--
+1.7.4.1
+
diff --git a/packaging/buildidprov.diff b/packaging/buildidprov.diff
new file mode 100644
index 0000000..6674d50
--- /dev/null
+++ b/packaging/buildidprov.diff
@@ -0,0 +1,54 @@
+From: Jan Blunck <jblunck@suse.de>
+Subject: Let debuginfo packages provide the build-id
+
+This patch lets debuginfo packages provide build-id like follows:
+
+ debuginfo(build-id) = c63cb23876c5fa85f36beaff58f8557e1bf22517
+
+Users can therefore ask zypper to install the correct debuginfo package with:
+
+ zypper install -C "debuginfo(build-id) = c63cb23876c5fa85f36beaff58f8557e1bf22517"
+
+Index: autodeps/linux.prov
+===================================================================
+--- autodeps/linux.prov.orig
++++ autodeps/linux.prov
+@@ -5,6 +5,9 @@
+ IFS=$'\n'
+ filelist=($(cat))
+
++debuginfolist=($(printf "%s\n" "${filelist[@]}" | grep "/usr/lib/debug/"))
++filelist=($(printf "%s\n" "${filelist[@]}" | grep -v "/usr/lib/debug/"))
++
+ solist=($(printf "%s\n" "${filelist[@]}" | grep "\\.so" | grep -v "^/lib/ld.so" | \
+ tr '\n' '\0' | xargs -0 -r file -L | grep "ELF.*shared object" | \
+ cut -d: -f1))
+@@ -71,6 +74,11 @@ done | sort -u
+ printf "%s\n" "${firmwarelist[@]}" | /usr/lib/rpm/firmware.prov | sort -u
+
+ #
++# --- debuginfo files
++[ -x /usr/lib/rpm/debuginfo.prov -a -n "$debuginfolist" ] &&
++ printf "%s\n" "${debuginfolist[@]}" | /usr/lib/rpm/debuginfo.prov | sort -u
++
++#
+ # --- Mono exes/dlls
+ : ${MONO_PREFIX=/usr}
+ if [ -x $MONO_PREFIX/bin/mono -a -n "$monolist" ] ; then
+Index: scripts/debuginfo.prov
+===================================================================
+--- /dev/null
++++ scripts/debuginfo.prov
+@@ -0,0 +1,12 @@
++#!/bin/sh
++
++while read instfile ; do
++ case $instfile in
++ */usr/lib/debug/.build-id/*.debug)
++ if [ -f "$instfile" ] ; then
++ BUILDID=$(echo $instfile | sed -ne 's|.*/usr/lib/debug/.build-id/\([0-9a-f]*\)/\([0-9a-f]*\)\.debug|\1\2|p')
++ echo "debuginfo(build-id) = $BUILDID"
++ fi
++ ;;
++ esac
++done
diff --git a/packaging/db-4.8.30.tar.gz b/packaging/db-4.8.30.tar.gz
new file mode 100644
index 0000000..21a743f
--- /dev/null
+++ b/packaging/db-4.8.30.tar.gz
Binary files differ
diff --git a/packaging/db.diff b/packaging/db.diff
new file mode 100644
index 0000000..dbfb293
--- /dev/null
+++ b/packaging/db.diff
@@ -0,0 +1,82 @@
+--- db/db/db.c.orig 2010-04-12 20:25:22.000000000 +0000
++++ db/db/db.c 2011-05-12 11:38:59.000000000 +0000
+@@ -646,6 +646,8 @@ __env_mpool(dbp, fname, flags)
+ MAKE_INMEM(dbp);
+ return (ret);
+ }
++ if (LF_ISSET(DB_NOFSYNC) && mpf->mfp)
++ F_SET(mpf->mfp, MP_NOFSYNC);
+
+ /*
+ * Set the open flag. We use it to mean that the dbp has gone
+--- db/db/db_iface.c.orig 2010-04-12 20:25:22.000000000 +0000
++++ db/db/db_iface.c 2011-05-12 11:21:32.000000000 +0000
+@@ -1230,6 +1230,7 @@ __db_open_arg(dbp, txn, fname, dname, ty
+ #define OKFLAGS \
+ (DB_AUTO_COMMIT | DB_CREATE | DB_EXCL | DB_FCNTL_LOCKING | \
+ DB_MULTIVERSION | DB_NOMMAP | DB_NO_AUTO_COMMIT | DB_RDONLY | \
++ DB_NOFSYNC | \
+ DB_RDWRMASTER | DB_READ_UNCOMMITTED | DB_THREAD | DB_TRUNCATE)
+ if ((ret = __db_fchk(env, "DB->open", flags, OKFLAGS)) != 0)
+ return (ret);
+--- db/dbinc/mp.h.orig 2010-04-12 20:25:22.000000000 +0000
++++ db/dbinc/mp.h 2011-05-12 12:01:32.000000000 +0000
+@@ -467,6 +467,7 @@ struct __mpoolfile {
+ #define MP_FAKE_UOC 0x080 /* Unlink_on_close field: fake flag. */
+ #define MP_NOT_DURABLE 0x100 /* File is not durable. */
+ #define MP_TEMP 0x200 /* Backing file is a temporary. */
++#define MP_NOFSYNC 0x400 /* Don't fsync */
+ u_int32_t flags;
+ };
+
+--- db/dbinc_auto/api_flags.in.orig 2011-05-12 11:40:57.000000000 +0000
++++ db/dbinc_auto/api_flags.in 2011-05-12 11:55:10.000000000 +0000
+@@ -83,6 +83,7 @@
+ #define DB_NOORDERCHK 0x00000002
+ #define DB_NOPANIC 0x00000800
+ #define DB_NO_AUTO_COMMIT 0x00001000
++#define DB_NOFSYNC 0x00040000
+ #define DB_ODDFILESIZE 0x00000080
+ #define DB_ORDERCHKONLY 0x00000004
+ #define DB_OVERWRITE 0x00001000
+--- db/dist/s_config.orig 2010-04-12 20:25:23.000000000 +0000
++++ db/dist/s_config 2011-05-12 12:00:34.000000000 +0000
+@@ -8,7 +8,8 @@ trap 'rm -f aclocal.m4 ; exit 0' 0 1 2 3
+ . ./RELEASE
+
+ echo "autoconf: building aclocal.m4..."
+-cat aclocal/*.m4 aclocal_java/*.m4 > aclocal.m4
++cat aclocal/*.m4 aclocal_java/*.m4 > acinclude.m4
++aclocal
+
+ echo "autoconf: running autoheader to build config.hin..."
+ rm -f config.hin
+--- db/mp/mp_sync.c.orig 2010-04-12 20:25:34.000000000 +0000
++++ db/mp/mp_sync.c 2011-05-12 11:36:58.000000000 +0000
+@@ -578,7 +578,7 @@ done: /*
+ if (ret == 0 && required_write) {
+ if (dbmfp == NULL)
+ ret = __memp_sync_files(env);
+- else
++ else if (!F_ISSET(dbmfp->mfp, MP_NOFSYNC))
+ ret = __os_fsync(env, dbmfp->fhp);
+ }
+
+@@ -665,7 +665,7 @@ __memp_sync_file(env, mfp, argp, countp,
+ "%s: unable to flush", (char *)
+ R_ADDR(dbmp->reginfo, mfp->path_off));
+ }
+- } else
++ } else if (!F_ISSET(dbmfp->mfp, MP_NOFSYNC))
+ ret = __os_fsync(env, dbmfp->fhp);
+
+ /*
+@@ -801,6 +801,8 @@ __memp_mf_sync(dbmp, mfp, locked)
+ COMPQUIET(hp, NULL);
+ env = dbmp->env;
+
++ if (F_ISSET(mfp, MP_NOFSYNC))
++ return 0;
+ /*
+ * We need to be holding the hash lock: we're using the path name
+ * and __memp_nameop might try and rename the file.
diff --git a/packaging/debugsource-package.diff b/packaging/debugsource-package.diff
new file mode 100644
index 0000000..f8e2dfe
--- /dev/null
+++ b/packaging/debugsource-package.diff
@@ -0,0 +1,73 @@
+Subject: Split sources for debugging into separate -debugsource package
+
+At the moment the -debuginfo package also include the sources where used to
+build the binary. The patches moves them into a separate package -debugsource.
+
+Index: macros.in
+===================================================================
+--- macros.in.orig
++++ macros.in
+@@ -180,15 +180,27 @@
+ %debug_package \
+ %ifnarch noarch\
+ %global __debug_package 1\
+-%package debug\
++%package debuginfo\
+ Summary: Debug information for package %{name}\
+ Group: Development/Debug\
+ AutoReqProv: 0\
+-%description debug\
++%description debuginfo\
+ This package provides debug information for package %{name}.\
+ Debug information is useful when developing applications that use this\
+ package or when debugging this package.\
+-%files debug -f debugfiles.list\
++%files debuginfo -f debugfiles.list\
++%defattr(-,root,root)\
++\
++%package debugsource\
++Summary: Debug sources for package %{name}\
++Group: Development/Debug\
++AutoReqProv: 0\
++Requires: %{name}-debuginfo = %{version}-%{release}\
++%description debugsource\
++This package provides debug sources for package %{name}.\
++Debug sources are useful when developing applications that use this\
++package or when debugging this package.\
++%files debugsource -f debugsources.list\
+ %defattr(-,root,root)\
+ %endif\
+ %{nil}
+Index: scripts/find-debuginfo.sh
+===================================================================
+--- scripts/find-debuginfo.sh.orig
++++ scripts/find-debuginfo.sh
+@@ -187,8 +187,8 @@ set -o pipefail
+ strict_error=ERROR
+ $strict || strict_error=WARNING
+
+-# Strip ELF binaries
+-find $RPM_BUILD_ROOT ! -path "${debugdir}/*.debug" -type f \( -perm +111 -or -name "*.so*" -or -name "*.ko" \) -print 0 | sort -z |
++# Strip ELF binaries (and no static libraries)
++find $RPM_BUILD_ROOT ! -path "${debugdir}/*.debug" -type f \( -perm +111 -or -name "*.so*" -or -name "*.ko" \) ! -name "*.a" -print0 | sort -z |
+ xargs --no-run-if-empty -0 stat -c '%h %D_%i %n' |
+ while read nlinks inum f; do
+ case $(objdump -h $f 2>/dev/null | egrep -o '(debug[\.a-z_]*|gnu.version)') in
+@@ -300,10 +300,16 @@ if [ -d "${RPM_BUILD_ROOT}/usr/lib" -o -
+
+ (cd "${RPM_BUILD_ROOT}/usr"
+ test ! -d lib/debug || find lib/debug ! -type d
+- test ! -d src/debug || find src/debug -mindepth 1 -maxdepth 1
+ ) | sed 's,^,/usr/,' >> "$LISTFILE"
+ fi
+
++: > "$SOURCEFILE"
++if [ -d "${RPM_BUILD_ROOT}/usr/src" ]; then
++ (cd "${RPM_BUILD_ROOT}/usr"
++ test ! -d src/debug || find src/debug -mindepth 1 -maxdepth 1
++ ) | sed 's,^,/usr/,' >> "$SOURCEFILE"
++fi
++
+ # Append to $1 only the lines from stdin not already in the file.
+ append_uniq()
+ {
diff --git a/packaging/debugsubpkg.diff b/packaging/debugsubpkg.diff
new file mode 100644
index 0000000..3545fdb
--- /dev/null
+++ b/packaging/debugsubpkg.diff
@@ -0,0 +1,321 @@
+Create a debuginfo package for each subpackage.
+
+Index: build/files.c
+===================================================================
+--- build/files.c.orig
++++ build/files.c
+@@ -20,6 +20,10 @@
+ #include <rpm/rpmfileutil.h> /* rpmDoDigest() */
+ #include <rpm/rpmlog.h>
+
++#if HAVE_GELF_H
++#include <gelf.h>
++#endif
++
+ #include "rpmio/rpmio_internal.h" /* XXX rpmioSlurp */
+ #include "rpmio/base64.h"
+ #include "misc/fts.h"
+@@ -2105,13 +2109,237 @@ exit:
+ return rc;
+ }
+
++#if HAVE_GELF_H && HAVE_LIBELF
++/* Query the build-id from the ELF file NAME and store it in the newly
++ allocated *build_id array of size *build_id_size. Returns -1 on
++ error. */
++
++int
++getELFBuildId (const char *name,
++ unsigned char **id, size_t *id_size)
++{
++ int fd, i;
++ Elf *elf;
++ GElf_Ehdr ehdr;
++ Elf_Data *build_id = NULL;
++ size_t build_id_offset = 0, build_id_size = 0;
++
++ /* Now query the build-id of the file and add the
++ corresponding links in the .build-id tree.
++ The following code is based on tools/debugedit.c. */
++ fd = open (name, O_RDONLY);
++ if (fd < 0)
++ return -1;
++ elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
++ if (elf == NULL)
++ {
++ fprintf (stderr, "cannot open ELF file: %s",
++ elf_errmsg (-1));
++ close (fd);
++ return -1;
++ }
++ if (elf_kind (elf) != ELF_K_ELF
++ || gelf_getehdr (elf, &ehdr) == NULL
++ || (ehdr.e_type != ET_DYN
++ && ehdr.e_type != ET_EXEC
++ && ehdr.e_type != ET_REL))
++ {
++ elf_end (elf);
++ close (fd);
++ return -1;
++ }
++ for (i = 0; i < ehdr.e_shnum; ++i)
++ {
++ Elf_Scn *s = elf_getscn (elf, i);
++ GElf_Shdr shdr;
++ Elf_Data *data;
++ Elf32_Nhdr nh;
++ Elf_Data dst =
++ {
++ .d_version = EV_CURRENT, .d_type = ELF_T_NHDR,
++ .d_buf = &nh, .d_size = sizeof nh
++ };
++ Elf_Data src = dst;
++
++ gelf_getshdr (s, &shdr);
++ if (shdr.sh_type != SHT_NOTE
++ || !(shdr.sh_flags & SHF_ALLOC))
++ continue;
++
++ /* Look for a build-ID note here. */
++ data = elf_rawdata (s, NULL);
++ src.d_buf = data->d_buf;
++ assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr));
++ while (data->d_buf + data->d_size - src.d_buf > (int) sizeof nh
++ && elf32_xlatetom (&dst, &src, ehdr.e_ident[EI_DATA]))
++ {
++ Elf32_Word len = sizeof nh + nh.n_namesz;
++ len = (len + 3) & ~3;
++
++ if (nh.n_namesz == sizeof "GNU" && nh.n_type == 3
++ && !memcmp (src.d_buf + sizeof nh, "GNU", sizeof "GNU"))
++ {
++ build_id = data;
++ build_id_offset = src.d_buf + len - data->d_buf;
++ build_id_size = nh.n_descsz;
++ break;
++ }
++
++ len += nh.n_descsz;
++ len = (len + 3) & ~3;
++ src.d_buf += len;
++ }
++
++ if (build_id != NULL)
++ break;
++ }
++
++ if (build_id == NULL)
++ return -1;
++
++ *id = malloc (build_id_size);
++ *id_size = build_id_size;
++ memcpy (*id, build_id->d_buf + build_id_offset, build_id_size);
++
++ elf_end (elf);
++ close (fd);
++
++ return 0;
++}
++
++
++static rpmTag copyTagsForDebug[] = {
++ RPMTAG_EPOCH,
++ RPMTAG_VERSION,
++ RPMTAG_RELEASE,
++ RPMTAG_LICENSE,
++ RPMTAG_PACKAGER,
++ RPMTAG_DISTRIBUTION,
++ RPMTAG_DISTURL,
++ RPMTAG_VENDOR,
++ RPMTAG_ICON,
++ RPMTAG_URL,
++ RPMTAG_CHANGELOGTIME,
++ RPMTAG_CHANGELOGNAME,
++ RPMTAG_CHANGELOGTEXT,
++ RPMTAG_PREFIXES,
++ RPMTAG_RHNPLATFORM,
++ RPMTAG_OS,
++ RPMTAG_DISTTAG,
++ RPMTAG_CVSID,
++ RPMTAG_ARCH,
++ 0
++};
++
++static void addDebuginfoPackage(rpmSpec spec, Package pkg, char *buildroot)
++{
++ const char *a;
++
++ elf_version(EV_CURRENT);
++ a = headerGetString(pkg->header, RPMTAG_ARCH);
++ if (strcmp(a, "noarch") != 0 && strcmp(a, "src") != 0 && strcmp(a, "nosrc") != 0)
++ {
++ Package dbg;
++ rpmfi fi = pkg->cpioList;
++ char tmp[1024];
++ const char *name;
++ ARGV_t files = NULL;
++ int seen_build_id = 0;
++
++ /* Check if the current package has files with debug info
++ and record them. */
++ fi = rpmfiInit (fi, 0);
++ while (rpmfiNext (fi) >= 0)
++ {
++ const char *base;
++ int i;
++ unsigned char *build_id;
++ size_t build_id_size = 0;
++ struct stat sbuf;
++
++ name = rpmfiFN (fi);
++ /* Skip leading buildroot. */
++ base = name + strlen (buildroot);
++ /* Pre-pend %buildroot/usr/lib/debug and append .debug. */
++ snprintf (tmp, 1024, "%s/usr/lib/debug%s.debug",
++ buildroot, base);
++ /* If that file exists we have debug information for it. */
++ if (access (tmp, F_OK) != 0)
++ continue;
++
++ /* Append the file list preamble. */
++ if (!files)
++ {
++ argvAdd(&files, "%defattr(-,root,root)");
++ argvAdd(&files, "%dir /usr/lib/debug");
++ }
++ /* Add the files main debug-info file. */
++ snprintf (tmp, 1024, "/usr/lib/debug/%s.debug", base);
++ argvAdd(&files, tmp);
++
++ /* Do not bother to check build-ids for symbolic links.
++ We'll handle them for the link target. */
++ if (lstat (name, &sbuf) == -1
++ || S_ISLNK (sbuf.st_mode))
++ continue;
++
++ /* Try to gather the build-id from the binary. */
++ if (getELFBuildId (name, &build_id, &build_id_size) == -1)
++ continue;
++
++ /* If we see build-id links for the first time add the
++ directory. */
++ if (!seen_build_id)
++ argvAdd(&files, "%dir /usr/lib/debug/.build-id");
++
++ /* From the build-id construct the two links pointing back
++ to the debug information file and the binary. */
++ snprintf (tmp, 1024, "/usr/lib/debug/.build-id/%02x/",
++ build_id[0]);
++ for (i = 1; i < build_id_size; ++i)
++ sprintf (tmp + strlen (tmp), "%02x", build_id[i]);
++ argvAdd(&files, tmp);
++ sprintf (tmp + strlen (tmp), ".debug");
++ argvAdd(&files, tmp);
++
++ free (build_id);
++ }
++
++ /* If there are debuginfo files for this package add a
++ new debuginfo package. */
++ if (files)
++ {
++ dbg = newPackage (spec);
++ headerNVR (pkg->header, &name, NULL, NULL);
++ /* Set name, summary and group. */
++ snprintf (tmp, 1024, "%s-debuginfo", name);
++ headerPutString(dbg->header, RPMTAG_NAME, tmp);
++ snprintf (tmp, 1024, "Debug information for package %s", name);
++ headerPutString(dbg->header, RPMTAG_SUMMARY, tmp);
++ snprintf (tmp, 1024, "This package provides debug information for package %s.\n"
++ "Debug information is useful when developing applications that use this\n"
++ "package or when debugging this package.", name);
++ headerPutString(dbg->header, RPMTAG_DESCRIPTION, tmp);
++ headerPutString(dbg->header, RPMTAG_GROUP, "Development/Debug");
++ /* Inherit other tags from parent. */
++ headerCopyTags (pkg->header, dbg->header, copyTagsForDebug);
++
++ /* Build up the files list. */
++ dbg->fileList = files;
++ }
++ }
++}
++#endif
++
+ rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags,
+ int installSpecialDoc, int test)
+ {
+ Package pkg;
+ rpmRC rc = RPMRC_OK;
++ char *buildroot;
+
+ check_fileList = newStringBuf();
++ buildroot = rpmGenPath(spec->rootDir, spec->buildRoot, NULL);
+ genSourceRpmName(spec);
+
+ for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
+@@ -2127,8 +2355,12 @@ rpmRC processBinaryFiles(rpmSpec spec, r
+ rpmlog(RPMLOG_NOTICE, _("Processing files: %s\n"), nvr);
+ free(nvr);
+
+- if ((rc = processPackageFiles(spec, pkgFlags, pkg, installSpecialDoc, test)) != RPMRC_OK ||
+- (rc = rpmfcGenerateDepends(spec, pkg)) != RPMRC_OK)
++ if ((rc = processPackageFiles(spec, pkgFlags, pkg, installSpecialDoc, test)) != RPMRC_OK)
++ goto exit;
++#if HAVE_GELF_H && HAVE_LIBELF
++ addDebuginfoPackage(spec, pkg, buildroot);
++#endif
++ if ((rc = rpmfcGenerateDepends(spec, pkg)) != RPMRC_OK)
+ goto exit;
+
+ a = headerGetString(pkg->header, RPMTAG_ARCH);
+Index: scripts/find-debuginfo.sh
+===================================================================
+--- scripts/find-debuginfo.sh.orig
++++ scripts/find-debuginfo.sh
+@@ -267,19 +267,11 @@ while read nlinks inum f; do
+ fi
+ done || exit
+
+-# For each symlink whose target has a .debug file,
+-# make a .debug symlink to that file.
+-find $RPM_BUILD_ROOT ! -path "${debugdir}/*" -type l -print |
+-while read f
+-do
+- t=$(readlink -m "$f").debug
+- f=${f#$RPM_BUILD_ROOT}
+- t=${t#$RPM_BUILD_ROOT}
+- if [ -f "$debugdir$t" ]; then
+- echo "symlinked /usr/lib/debug$t to /usr/lib/debug${f}.debug"
+- debug_link "/usr/lib/debug$t" "${f}.debug"
+- fi
+-done
++# We used to make a .debug symlink for each symlink whose target
++# has a .debug file to that file. This is not necessary because
++# the debuglink section contains only the destination of those links.
++# Creating those links anyway results in debuginfo packages for
++# devel packages just because of the .so symlinks in them.
+
+ if [ -s "$SOURCEFILE" ]; then
+ mkdir -p "${RPM_BUILD_ROOT}/usr/src/debug"
+Index: macros.in
+===================================================================
+--- macros.in.orig
++++ macros.in
+@@ -180,17 +180,6 @@
+ %debug_package \
+ %ifnarch noarch\
+ %global __debug_package 1\
+-%package debuginfo\
+-Summary: Debug information for package %{name}\
+-Group: Development/Debug\
+-AutoReqProv: 0\
+-%description debuginfo\
+-This package provides debug information for package %{name}.\
+-Debug information is useful when developing applications that use this\
+-package or when debugging this package.\
+-%files debuginfo -f debugfiles.list\
+-%defattr(-,root,root)\
+-\
+ %package debugsource\
+ Summary: Debug sources for package %{name}\
+ Group: Development/Debug\
diff --git a/packaging/device-sec-policy b/packaging/device-sec-policy
new file mode 100644
index 0000000..626b905
--- /dev/null
+++ b/packaging/device-sec-policy
@@ -0,0 +1,48 @@
+<config>
+ <sw_source name="root" rankkey="/10020/10000.root">
+ <origin>
+ <keyinfo>
+mQENBE6MJTABCAC6pAFNW9tCbLQtgmwxzNf7ftSL5RrsjVTlPtpyeFLhxSmqmeHr
+KB10C6Co1zYB/fW8zvGXU613g3WEo4SKlS2lnOVBxviet0qn58zwCQASbdFYtckk
+thtkxiSInoKbj4n/Z+hHB9dvcyqcWqp2IFQEDDpxgP4KuzCvvj6W+e9EtYsdGt9P
+ZHsVjIAe0w+j7Hs4Q7FYWD+mdQAjgBsLlc16Ci8EPYnvBL/xdbJ3Ryfi59tTdfGG
+HnwpjM2J1WshooyvsOtHZU+T1nHtuegEzdRMVFo502Lkb60dJRsREE2iyPWFX2TE
+ZdaQqUMmkPaROUlWhGBSWIKbOVARwWBn94KDABEBAAG0CXJvb3QudGVzdIkBPgQT
+AQIAKAUCTowlMAIbAwUJA8JnAAYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQ
+TTk+Qq2l7P210wgApKVLpdve9jDsy/y//gSAGvfA4fXFuGhHkH5+QW7L+QkUAo0Z
+vv0KB0Pw5qZjV+k8jlq3Q3f/vcIEKxc40d0coa3m+bUlL2vy0+0gLSTiZ4MNFAk5
+LvJgEj+7ks75/qtJVWfCZeXo9NiugSoW9D+jNflmfstd8k2wT2ucH7IJHHzK1lGm
+vZHXeJeSULRHiibVyK5cG+NH/1Akuxkgo2jOzqhLjhp4/UiJlyAD0k/J4ULfmWp8
+C9/sIhWBoS5OcrtMVQtUMTx85I2dEC/01hnfLUk8mi5VscLu3xQoJ9hNrMEgji6H
+S+MmxcPGnVziEA0Z7VNN6DpuG/xZ1i9fgXXVfLkBDQROjCUwAQgA6fyD7eqaoah/
+za0X+Xv3o1y52UHmeHMmyzM/W4UlVsd01h7KzSHWyQKHi0i0pxRtUj+pkV+r+QjV
+BiAowq2HVpyXsmre29PEgAuIVv6/pZjfZEWFKjSDsvdXpS+mT+J6LjRxYh7ZbGvv
+SR3hMiMocWYENj13XDRw5USGhC0UxlmmMfjQfWJ6eHeQTiyZWW+CZUAJ2IbEkPVP
+nBDH/fTuVMfOo4g0HwqUSJmwV47BPLec1ArSaPG1YgKX1Y+UYoNfUvo/ieiF59At
+A8UbjQMzZggIfkvJsDL8U5n4ojFL8Rs/aMYuH76OlA4wuKPAnBSt+fVBnjaAAadf
+FCy/CHZt/wARAQABiQElBBgBAgAPBQJOjCUwAhsMBQkDwmcAAAoJEE05PkKtpez9
+S7IH/j44MxOP6dAycQAreWVAzdMiw82DjP7c6jMxYZj8ss1x++iO5GW82qm0WJ6h
+IOEdll+wBhPX0acKvE4KrlNzfsB2WzDRwOyiZfuSQI0J3Jrytj8zyCVKwHTsI8VC
+RkOzaMYsEqmPc+ve+wxxcwWXC0EtoyhMRjRZlMy55IeJcEfM8bcE4wcsyotsura6
+o1fmU223Xj1k5xXxDvXalPUoXnhvsev7kMBnIQRac194qkSkTzVXGLGu5Ng7Bfxl
+BMhf6RSk31+Q43ASbn4ralnswMhsHSatJIeasbHyvsTJzMnfEoSdpb8/dQI8KnHf
+tRrR5cbqmVr8tkFjS/QK6TWfNMM=
+</keyinfo>
+ </origin>
+ <package name="unknown-sw-source"/>
+ <package name="ac-domain-system">
+ <provide>
+ <ac_domain name="_" policy="shared"/>
+ <ac_domain name="*" policy="shared"/>
+ <ac_domain name="^" policy="shared"/>
+ <ac_domain name="Isolated"/>
+ </provide>
+ </package>
+ <package name="root"/>
+ <sw_source name="_default_" rankkey="/10020/11000/10000._default_">
+ <allow>
+ <ac_domain match="*"/>
+ </allow>
+ </sw_source>
+ </sw_source>
+</config>
diff --git a/packaging/disableperl.patch b/packaging/disableperl.patch
new file mode 100644
index 0000000..f5937b0
--- /dev/null
+++ b/packaging/disableperl.patch
@@ -0,0 +1,18 @@
+Index: rpm-4.9.1/fileattrs/perl.attr
+===================================================================
+--- rpm-4.9.1.orig/fileattrs/perl.attr
++++ rpm-4.9.1/fileattrs/perl.attr
+@@ -1,3 +1,3 @@
+-%__perl_requires %{_rpmconfigdir}/perl.req
++#%__perl_requires %{_rpmconfigdir}/perl.req
+ %__perl_magic ^.*perl .*$
+ %__perl_flags exeonly
+Index: rpm-4.9.1/fileattrs/perllib.attr
+===================================================================
+--- rpm-4.9.1.orig/fileattrs/perllib.attr
++++ rpm-4.9.1/fileattrs/perllib.attr
+@@ -1,3 +1,3 @@
+ %__perllib_provides %{_rpmconfigdir}/perl.prov
+-%__perllib_requires %{_rpmconfigdir}/perl.req
++#%__perllib_requires %{_rpmconfigdir}/perl.req
+ %__perllib_magic ^Perl[[:digit:]] module source.*
diff --git a/packaging/eu-strip.patch b/packaging/eu-strip.patch
new file mode 100644
index 0000000..bacef74
--- /dev/null
+++ b/packaging/eu-strip.patch
@@ -0,0 +1,69 @@
+Index: rpm-4.9.1/scripts/find-debuginfo.sh
+===================================================================
+--- rpm-4.9.1.orig/scripts/find-debuginfo.sh
++++ rpm-4.9.1/scripts/find-debuginfo.sh
+@@ -95,13 +95,18 @@ debugdir="${RPM_BUILD_ROOT}/usr/lib/debu
+
+ strip_to_debug()
+ {
+- local g=
+ local r=
+ $strip_r && r=--reloc-debug-sections
+- $strip_g && case "$(file -bi "$2")" in
+- application/x-sharedlib*) g=-g ;;
++ case $2 in
++ *.ko)
++ # don't attempt to create a minimal backtrace binary for
++ # kernel modules as this just causes the stripping process
++ # to be skipped entirely
++ eu-strip --remove-comment $r -f "$1" "$2" || exit
++ ;;
++ *)
++ eu-strip --remove-comment -g -f "$1" "$2" || exit
+ esac
+- eu-strip --remove-comment $r $g -f "$1" "$2" || exit
+ chmod 444 "$1" || exit
+ }
+
+@@ -229,8 +234,6 @@ while read nlinks inum f; do
+ fi
+
+ echo "extracting debug info from $f"
+- mode=$(stat -c %a "$f")
+- chmod +w "$f"
+ id=$($(DEBUGEDIT=$(which debugedit 2>/dev/null); \
+ echo ${DEBUGEDIT:-/usr/lib/rpm/debugedit}) -b "$RPM_BUILD_DIR" \
+ -d /usr/src/debug -i -l "$SOURCEFILE" "$f") || exit
+@@ -250,25 +253,13 @@ while read nlinks inum f; do
+ esac
+
+ mkdir -p "${debugdn}"
+- objcopy --only-keep-debug $f $debugfn || :
+- (
+- shopt -s extglob
+- strip_option="--strip-all"
+- case "$f" in
+- *.ko)
+- strip_option="--strip-debug" ;;
+- *$STRIP_KEEP_SYMTAB*)
+- if test -n "$STRIP_KEEP_SYMTAB"; then
+- strip_option="--strip-debug"
+- fi
+- ;;
+- esac
+- if test "$NO_DEBUGINFO_STRIP_DEBUG" = true ; then
+- strip_option=
+- fi
+- objcopy --add-gnu-debuglink=$debugfn -R .comment -R .GCC.command.line $strip_option $f
+- chmod $mode $f
+- ) || :
++ if test -w "$f"; then
++ strip_to_debug "${debugfn}" "$f"
++ else
++ chmod u+w "$f"
++ strip_to_debug "${debugfn}" "$f"
++ chmod u-w "$f"
++ fi
+
+ if [ -n "$id" ]; then
+ make_id_link "$id" "$dn/$(basename $f)"
diff --git a/packaging/fileattrs.diff b/packaging/fileattrs.diff
new file mode 100644
index 0000000..9b616ae
--- /dev/null
+++ b/packaging/fileattrs.diff
@@ -0,0 +1,46 @@
+--- ./fileattrs/Makefile.am.orig 2011-07-12 11:28:13.000000000 +0000
++++ ./fileattrs/Makefile.am 2011-07-18 17:29:11.000000000 +0000
+@@ -5,7 +5,8 @@ include $(top_srcdir)/rpm.am
+ fattrsdir = $(rpmconfigdir)/fileattrs
+
+ fattrs_DATA = \
+- desktop.attr elf.attr font.attr libtool.attr perl.attr perllib.attr \
+- pkgconfig.attr python.attr ocaml.attr script.attr mono.attr
++ elf.attr font.attr libtool.attr perl.attr perllib.attr \
++ pkgconfig.attr python.attr ocaml.attr script.attr mono.attr \
++ debuginfo.attr elflib.attr firmware.attr ksyms.attr
+
+ EXTRA_DIST = $(fattrs_DATA)
+--- ./fileattrs/debuginfo.attr.orig 2011-07-18 17:29:11.000000000 +0000
++++ ./fileattrs/debuginfo.attr 2011-07-18 17:29:11.000000000 +0000
+@@ -0,0 +1,2 @@
++%__debuginfo_provides %{_rpmconfigdir}/debuginfo.prov
++%__debuginfo_path ^/usr/lib/debug/
+--- ./fileattrs/elf.attr.orig 2011-07-15 09:32:41.000000000 +0000
++++ ./fileattrs/elf.attr 2011-07-18 17:31:52.000000000 +0000
+@@ -1,4 +1,5 @@
+ %__elf_provides %{_rpmconfigdir}/elfdeps --provides %{?__filter_GLIBC_PRIVATE:--filter-private}
+ %__elf_requires %{_rpmconfigdir}/elfdeps --requires %{?__filter_GLIBC_PRIVATE:--filter-private}
+-%__elf_magic ^(sticky )?ELF (32|64)-bit.*$
++%__elf_magic ^(setuid )?(setgid )?(sticky )?ELF (32|64)-bit.*executable
+ %__elf_flags exeonly
++%__elf_exclude_path ^/usr/lib/debug/
+--- ./fileattrs/elflib.attr.orig 2011-07-18 17:29:11.000000000 +0000
++++ ./fileattrs/elflib.attr 2011-07-18 17:32:28.000000000 +0000
+@@ -0,0 +1,4 @@
++%__elflib_provides %{_rpmconfigdir}/elfdeps --assume-exec --provides %{?__filter_GLIBC_PRIVATE:--filter-private}
++%__elflib_requires %{_rpmconfigdir}/elfdeps --assume-exec --requires %{?__filter_GLIBC_PRIVATE:--filter-private}
++%__elflib_magic ^(setuid )?(setgid )?(sticky )?ELF (32|64)-bit.*shared object
++%__elflib_exclude_path ^/usr/lib/debug/
+--- ./fileattrs/firmware.attr.orig 2011-07-18 17:29:11.000000000 +0000
++++ ./fileattrs/firmware.attr 2011-07-18 17:29:11.000000000 +0000
+@@ -0,0 +1,2 @@
++%__firmware_provides %{_rpmconfigdir}/firmware.prov
++%__firmware_path /lib/firmware/
+--- ./fileattrs/ksyms.attr.orig 2011-07-18 17:29:11.000000000 +0000
++++ ./fileattrs/ksyms.attr 2011-07-18 17:29:11.000000000 +0000
+@@ -0,0 +1,4 @@
++%__ksyms_provides %{_rpmconfigdir}/find-provides.ksyms %name
++%__ksyms_requires %{_rpmconfigdir}/find-requires.ksyms %name
++%__ksyms_supplements %{_rpmconfigdir}/find-supplements.ksyms %name
++%__ksyms_path (/lib/modules/.*\.ko(\.gz)?)|(/boot/vmlinu[xz].*)$
diff --git a/packaging/find-docs.sh b/packaging/find-docs.sh
new file mode 100644
index 0000000..c1dd130
--- /dev/null
+++ b/packaging/find-docs.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+usage () {
+cat << EOF
+Usage: $0 TOP_DIR
+
+EOF
+exit 1
+}
+
+if [ -z "$1" ] ; then usage
+elif [ $1 = / ] ; then echo $0: expects non-/ argument for '$1' 1>&2
+elif [ ! -d $1 ] ; then
+ echo $0: $1: no such directory
+ exit 1
+else TOP_DIR="`echo $1|sed -e 's:/$::'`"
+fi
+shift
+
+DOC_NAME=documentation.list
+touch $DOC_NAME
+
+find $TOP_DIR -type f -o -type l | sed '
+s:'"$TOP_DIR"'::
+s:\(.*/man/man./.*\.[0-9]\):%doc \1:
+s:\(.*/gtk-doc/html/.*\):%doc \1:
+s:\(.*/info/.*\info.*\):%doc \1:
+s:^\([^%].*\)::
+/^$/d' >> $DOC_NAME
+
+
+exit 0
diff --git a/packaging/finddebuginfo.diff b/packaging/finddebuginfo.diff
new file mode 100644
index 0000000..3d1245e
--- /dev/null
+++ b/packaging/finddebuginfo.diff
@@ -0,0 +1,119 @@
+--- ./scripts/find-debuginfo.sh.orig 2010-12-03 12:11:57.000000000 +0000
++++ ./scripts/find-debuginfo.sh 2011-05-11 14:46:18.000000000 +0000
+@@ -127,6 +127,20 @@ debug_link()
+ link_relative "$t" "$l" "$RPM_BUILD_ROOT"
+ }
+
++# Compare two binaries but ignore the .note.gnu.build-id section
++elfcmp()
++{
++ local tmp1=$(mktemp -t ${1##*/}.XXXXXX)
++ local tmp2=$(mktemp -t ${2##*/}.XXXXXX)
++
++ objcopy -R .note.gnu.build-id -R .gnu_debuglink $1 $tmp1
++ objcopy -R .note.gnu.build-id -R .gnu_debuglink $2 $tmp2
++ cmp -s $tmp1 $tmp2
++ local res=$?
++ rm -f $tmp1 $tmp2
++ return $res
++}
++
+ # Make a build-id symlink for id $1 with suffix $3 to file $2.
+ make_id_link()
+ {
+@@ -145,7 +159,7 @@ make_id_link()
+ local other=$(readlink -m "$root_idfile")
+ other=${other#$RPM_BUILD_ROOT}
+ if cmp -s "$root_idfile" "$RPM_BUILD_ROOT$file" ||
+- eu-elfcmp -q "$root_idfile" "$RPM_BUILD_ROOT$file" 2> /dev/null; then
++ elfcmp "$root_idfile" "$RPM_BUILD_ROOT$file" ; then
+ # Two copies. Maybe one has to be setuid or something.
+ echo >&2 "*** WARNING: identical binaries are copied, not linked:"
+ echo >&2 " $file"
+@@ -174,12 +188,18 @@ strict_error=ERROR
+ $strict || strict_error=WARNING
+
+ # Strip ELF binaries
+-find "$RPM_BUILD_ROOT" ! -path "${debugdir}/*.debug" -type f \
+- \( -perm -0100 -or -perm -0010 -or -perm -0001 \) \
+- -print |
+-file -N -f - | sed -n -e 's/^\(.*\):[ ]*.*ELF.*, not stripped/\1/p' |
+-xargs --no-run-if-empty stat -c '%h %D_%i %n' |
++find $RPM_BUILD_ROOT ! -path "${debugdir}/*.debug" -type f \( -perm +111 -or -name "*.so*" -or -name "*.ko" \) -print 0 | sort -z |
++xargs --no-run-if-empty -0 stat -c '%h %D_%i %n' |
+ while read nlinks inum f; do
++ case $(objdump -h $f 2>/dev/null | egrep -o '(debug[\.a-z_]*|gnu.version)') in
++ *debuglink*) continue ;;
++ *debug*) ;;
++ *gnu.version*)
++ echo "WARNING: "`echo $f | sed -e "s,^$RPM_BUILD_ROOT/*,/,"`" is already stripped!"
++ continue
++ ;;
++ *) continue ;;
++ esac
+ get_debugfn "$f"
+ [ -f "${debugfn}" ] && continue
+
+@@ -200,8 +220,11 @@ while read nlinks inum f; do
+ fi
+
+ echo "extracting debug info from $f"
+- id=$(/usr/lib/rpm/debugedit -b "$RPM_BUILD_DIR" -d /usr/src/debug \
+- -i -l "$SOURCEFILE" "$f") || exit
++ mode=$(stat -c %a "$f")
++ chmod +w "$f"
++ id=$($(DEBUGEDIT=$(which debugedit 2>/dev/null); \
++ echo ${DEBUGEDIT:-/usr/lib/rpm/debugedit}) -b "$RPM_BUILD_DIR" \
++ -d /usr/src/debug -i -l "$SOURCEFILE" "$f") || exit
+ if [ -z "$id" ]; then
+ echo >&2 "*** ${strict_error}: No build ID note found in $f"
+ $strict && exit 2
+@@ -218,13 +241,25 @@ while read nlinks inum f; do
+ esac
+
+ mkdir -p "${debugdn}"
+- if test -w "$f"; then
+- strip_to_debug "${debugfn}" "$f"
+- else
+- chmod u+w "$f"
+- strip_to_debug "${debugfn}" "$f"
+- chmod u-w "$f"
+- fi
++ objcopy --only-keep-debug $f $debugfn || :
++ (
++ shopt -s extglob
++ strip_option="--strip-all"
++ case "$f" in
++ *.ko)
++ strip_option="--strip-debug" ;;
++ *$STRIP_KEEP_SYMTAB*)
++ if test -n "$STRIP_KEEP_SYMTAB"; then
++ strip_option="--strip-debug"
++ fi
++ ;;
++ esac
++ if test "$NO_DEBUGINFO_STRIP_DEBUG" = true ; then
++ strip_option=
++ fi
++ objcopy --add-gnu-debuglink=$debugfn -R .comment -R .GCC.command.line $strip_option $f
++ chmod $mode $f
++ ) || :
+
+ if [ -n "$id" ]; then
+ make_id_link "$id" "$dn/$(basename $f)"
+@@ -253,12 +288,14 @@ if [ -s "$SOURCEFILE" ]; then
+ # stupid cpio creates new directories in mode 0700, fixup
+ find "${RPM_BUILD_ROOT}/usr/src/debug" -type d -print0 |
+ xargs --no-run-if-empty -0 chmod a+rx
++ find "${RPM_BUILD_ROOT}/usr/src/debug" -type f -print0 |
++ xargs --no-run-if-empty -0 chmod a+r
+ fi
+
+ if [ -d "${RPM_BUILD_ROOT}/usr/lib" -o -d "${RPM_BUILD_ROOT}/usr/src" ]; then
+ ((nout > 0)) ||
+ test ! -d "${RPM_BUILD_ROOT}/usr/lib" ||
+- (cd "${RPM_BUILD_ROOT}/usr/lib"; find debug -type d) |
++ (cd "${RPM_BUILD_ROOT}/usr/lib"; test ! -d debug || find debug -type d) |
+ sed 's,^,%dir /usr/lib/,' >> "$LISTFILE"
+
+ (cd "${RPM_BUILD_ROOT}/usr"
diff --git a/packaging/firmware.diff b/packaging/firmware.diff
new file mode 100644
index 0000000..aa35bb3
--- /dev/null
+++ b/packaging/firmware.diff
@@ -0,0 +1,37 @@
+Index: autodeps/linux.prov
+===================================================================
+--- autodeps/linux.prov.orig
++++ autodeps/linux.prov
+@@ -12,6 +12,7 @@ pythonlist=
+ tcllist=
+ monolist=($(printf "%s\n" "${filelist[@]}" | egrep "\\.(exe|dll)\$"))
+ mimetypelist=($(printf "%s\n" "${filelist[@]}" | egrep "\\.(desktop)\$"))
++firmwarelist=($(printf "%s\n" "${filelist[@]}" | grep "/lib/firmware/"))
+
+ #
+ # --- Alpha does not mark 64bit dependencies
+@@ -65,6 +66,11 @@ done | sort -u
+ printf "%s\n" "${mimetypelist[@]}" | /usr/lib/rpm/mimetypes.prov | sort -u
+
+ #
++# --- firmware files
++[ -x /usr/lib/rpm/firmware.prov -a -n "$firmwarelist" ] &&
++ printf "%s\n" "${firmwarelist[@]}" | /usr/lib/rpm/firmware.prov | sort -u
++
++#
+ # --- Mono exes/dlls
+ : ${MONO_PREFIX=/usr}
+ if [ -x $MONO_PREFIX/bin/mono -a -n "$monolist" ] ; then
+Index: scripts/firmware.prov
+===================================================================
+--- /dev/null
++++ scripts/firmware.prov
+@@ -0,0 +1,8 @@
++#!/bin/sh
++# Add firmware files in /lib/firmware into RPM provides
++
++while read instfile ; do
++ case $instfile in
++ */lib/firmware/*) test -f "$instfile" && echo "firmware(${instfile##*/lib/firmware/})" ;;
++ esac
++done
diff --git a/packaging/fontprovides.diff b/packaging/fontprovides.diff
new file mode 100644
index 0000000..a8ceade
--- /dev/null
+++ b/packaging/fontprovides.diff
@@ -0,0 +1,50 @@
+--- ./autodeps/linux.prov.orig 2011-05-11 16:39:09.000000000 +0000
++++ ./autodeps/linux.prov 2011-05-11 16:40:49.000000000 +0000
+@@ -16,6 +16,8 @@ tcllist=
+ monolist=($(printf "%s\n" "${filelist[@]}" | egrep "\\.(exe|dll)\$"))
+ mimetypelist=($(printf "%s\n" "${filelist[@]}" | egrep "\\.(desktop)\$"))
+ firmwarelist=($(printf "%s\n" "${filelist[@]}" | grep "/lib/firmware/"))
++pkgconfiglist=($(printf "%s\n" "${filelist[@]}" | egrep '\.pc$'))
++fontlist=($(printf "%s\n" "${filelist[@]}" | egrep -i "/usr/share/fonts/.*\.(ttf|otf|pfa)$"))
+
+ #
+ # --- Alpha does not mark 64bit dependencies
+@@ -86,6 +88,16 @@ if [ -x $MONO_PREFIX/bin/mono -a -n "$mo
+ fi
+
+ #
++# --- pkgconfig provides
++[ -x /usr/lib/rpm/pkgconfigdeps.sh -a -n "$pkgconfiglist" ] &&
++ printf "%s\n" "${pkgconfiglist[@]}" | /usr/lib/rpm/pkgconfigdeps.sh -P | sort -u
++
++#
++# --- font provides
++[ -x /usr/lib/rpm/fontconfig.prov -a -n "$fontlist" ] &&
++ printf "%s\n" "${fontlist[@]}" | /usr/lib/rpm/fontconfig.prov | sort -u
++
++#
+ # --- Kernel module exported symbols
+ [ -x /usr/lib/rpm/find-provides.ksyms ] &&
+ printf "%s\n" "${filelist[@]}" | /usr/lib/rpm/find-provides.ksyms "$@"
+--- ./autodeps/linux.req.orig 2011-05-11 16:39:09.000000000 +0000
++++ ./autodeps/linux.req 2011-05-11 16:40:49.000000000 +0000
+@@ -34,6 +34,7 @@ perllist=()
+ pythonlist=($(printf "%s\n" "${filelist[@]}" | egrep '/usr/lib[^/]*/python.\..'))
+ tcllist=()
+ monolist=($(printf "%s\n" "${filelist[@]}" | egrep "\\.(exe|dll)(\\.config)?\$"))
++pkgconfiglist=($(printf "%s\n" "${filelist[@]}" | egrep '\.pc$'))
+
+ #
+ # --- Alpha does not mark 64bit dependencies
+@@ -143,6 +144,11 @@ if [ -x $MONO_PREFIX/bin/mono -a -n "$mo
+ fi
+
+ #
++# --- pkgconfig requires
++[ -x /usr/lib/rpm/pkgconfigdeps.sh -a -n "$pkgconfiglist" ] &&
++ printf "%s\n" "${pkgconfiglist[@]}" | /usr/lib/rpm/pkgconfigdeps.sh -R | sort -u
++
++#
+ # --- Kernel module imported symbols
+ [ -x ${0%/*}/find-requires.ksyms ] &&
+ printf "%s\n" "${filelist[@]}" | ${0%/*}/find-requires.ksyms "$@"
diff --git a/packaging/lib_rpmdb_4.9.1_fix.patch b/packaging/lib_rpmdb_4.9.1_fix.patch
new file mode 100644
index 0000000..4d151b4
--- /dev/null
+++ b/packaging/lib_rpmdb_4.9.1_fix.patch
@@ -0,0 +1,78 @@
+From 653849e098fa3b8e30fc93e12a57fb75b958fa1a Mon Sep 17 00:00:00 2001
+From: Elena, Reshetova <elena.reshetova@intel.com>
+Date: Mon, 20 Feb 2012 15:47:41 +0200
+Subject: [PATCH] Fix for lib rpmdb functionality
+
+---
+ lib/rpmdb.c | 13 ++++++++-----
+ 1 files changed, 8 insertions(+), 5 deletions(-)
+
+diff --git a/lib/rpmdb.c b/lib/rpmdb.c
+index 50bb6b1..74cbfef 100644
+--- a/lib/rpmdb.c
++++ b/lib/rpmdb.c
+@@ -225,7 +225,7 @@ static inline void dbiGrowSet(dbiIndexSet set, unsigned int nrecs)
+ */
+ static int dbt2set(dbiIndex dbi, DBT * data, dbiIndexSet * setp)
+ {
+- int _dbbyteswapped = dbiByteSwapped(dbi);
++ int _dbbyteswapped;
+ const char * sdbir;
+ dbiIndexSet set;
+ unsigned int i;
+@@ -239,6 +239,8 @@ static int dbt2set(dbiIndex dbi, DBT * data, dbiIndexSet * setp)
+ return 0;
+ }
+
++ _dbbyteswapped = dbiByteSwapped(dbi);
++
+ set = xcalloc(1, sizeof(*set));
+ dbiGrowSet(set, data->size / itype);
+ set->count = data->size / itype;
+@@ -288,7 +290,7 @@ static int dbt2set(dbiIndex dbi, DBT * data, dbiIndexSet * setp)
+ */
+ static int set2dbt(dbiIndex dbi, DBT * data, dbiIndexSet set)
+ {
+- int _dbbyteswapped = dbiByteSwapped(dbi);
++ int _dbbyteswapped;
+ char * tdbir;
+ unsigned int i;
+ dbiIndexType itype = dbiType(dbi);
+@@ -303,6 +305,8 @@ static int set2dbt(dbiIndex dbi, DBT * data, dbiIndexSet set)
+ }
+ tdbir = data->data = xmalloc(data->size);
+
++ _dbbyteswapped = dbiByteSwapped(dbi);
++
+ switch (itype) {
+ default:
+ case DBI_SECONDARY:
+@@ -1650,7 +1654,7 @@ static rpmRC miVerifyHeader(rpmdbMatchIterator mi, const void *uh, size_t uhlen)
+ return rpmrc;
+
+ /* Don't bother re-checking a previously read header. */
+- if (mi->mi_db->db_checked) {
++ if (mi->mi_db && mi->mi_db->db_checked) {
+ if (intHashHasEntry(mi->mi_db->db_checked, mi->mi_offset))
+ rpmrc = RPMRC_OK;
+ }
+@@ -1686,6 +1690,7 @@ Header rpmdbNextIterator(rpmdbMatchIterator mi)
+ size_t keylen;
+ int rc;
+ int xx;
++ union _dbswap mi_offset;
+
+ if (mi == NULL)
+ return NULL;
+@@ -1711,8 +1716,6 @@ top:
+ uhlen = 0;
+
+ do {
+- union _dbswap mi_offset;
+-
+ if (mi->mi_set) {
+ if (!(mi->mi_setx < mi->mi_set->count))
+ return NULL;
+--
+1.7.4.1
+
diff --git a/packaging/libsymlink.attr b/packaging/libsymlink.attr
new file mode 100644
index 0000000..8bb6404
--- /dev/null
+++ b/packaging/libsymlink.attr
@@ -0,0 +1,4 @@
+# Make libfoo.so symlinks require the soname-provide of the target library
+%__libsymlink_requires %{_rpmconfigdir}/elfdeps --provides --soname-only
+%__libsymlink_magic ^symbolic link to `.*lib.*\.so\..*'$
+%__libsymlink_exclude_path ^.*[[:digit:]]$
diff --git a/packaging/macros b/packaging/macros
new file mode 100644
index 0000000..0592502
--- /dev/null
+++ b/packaging/macros
@@ -0,0 +1,312 @@
+# Per-platform rpm configuration file.
+
+#==============================================================================
+# ---- per-platform macros.
+#
+%_vendor tizen
+%_os linux
+%_target_platform %{_target_cpu}-%{_vendor}-%{_target_os}%{?_gnu}
+
+###_enable_debug_packages 1
+
+# Default fuzz level for %patch in spec file.
+%_default_patch_fuzz 2
+%_enable_debug_packages 1
+
+#==============================================================================
+# ---- configure and makeinstall.
+#
+%configure \
+ CFLAGS="${CFLAGS:-%optflags}" ; export CFLAGS ; \
+ CXXFLAGS="${CXXFLAGS:-%optflags}" ; export CXXFLAGS ; \
+ FFLAGS="${FFLAGS:-%optflags -I%_fmoddir}" ; export FFLAGS ; \
+ ./configure --build=%{_build} --host=%{_host} \\\
+ --target=%{_target_platform} \\\
+ --program-prefix=%{?_program_prefix} \\\
+ --prefix=%{_prefix} \\\
+ --exec-prefix=%{_exec_prefix} \\\
+ --bindir=%{_bindir} \\\
+ --sbindir=%{_sbindir} \\\
+ --sysconfdir=%{_sysconfdir} \\\
+ --datadir=%{_datadir} \\\
+ --includedir=%{_includedir} \\\
+ --libdir=%{_libdir} \\\
+ --libexecdir=%{_libexecdir} \\\
+ --localstatedir=%{_localstatedir} \\\
+ --sharedstatedir=%{_sharedstatedir} \\\
+ --mandir=%{_mandir} \\\
+ --infodir=%{_infodir}
+
+
+%reconfigure \
+ CFLAGS="${CFLAGS:-%optflags}" ; export CFLAGS ; \
+ CXXFLAGS="${CXXFLAGS:-%optflags}" ; export CXXFLAGS ; \
+ FFLAGS="${FFLAGS:-%optflags -I%_fmoddir}" ; export FFLAGS ; \
+ autoreconf -v --install --force || exit 1 \
+ ./configure --build=%{_build} --host=%{_host} \\\
+ --target=%{_target_platform} \\\
+ --program-prefix=%{?_program_prefix} \\\
+ --prefix=%{_prefix} \\\
+ --exec-prefix=%{_exec_prefix} \\\
+ --bindir=%{_bindir} \\\
+ --sbindir=%{_sbindir} \\\
+ --sysconfdir=%{_sysconfdir} \\\
+ --datadir=%{_datadir} \\\
+ --includedir=%{_includedir} \\\
+ --libdir=%{_libdir} \\\
+ --libexecdir=%{_libexecdir} \\\
+ --localstatedir=%{_localstatedir} \\\
+ --sharedstatedir=%{_sharedstatedir} \\\
+ --mandir=%{_mandir} \\\
+ --infodir=%{_infodir}
+
+%autogen \
+ CFLAGS="${CFLAGS:-%optflags}" ; export CFLAGS ; \
+ CXXFLAGS="${CXXFLAGS:-%optflags}" ; export CXXFLAGS ; \
+ FFLAGS="${FFLAGS:-%optflags -I%_fmoddir}" ; export FFLAGS ; \
+ ./autogen.sh --build=%{_build} --host=%{_host} \\\
+ --target=%{_target_platform} \\\
+ --program-prefix=%{?_program_prefix} \\\
+ --prefix=%{_prefix} \\\
+ --exec-prefix=%{_exec_prefix} \\\
+ --bindir=%{_bindir} \\\
+ --sbindir=%{_sbindir} \\\
+ --sysconfdir=%{_sysconfdir} \\\
+ --datadir=%{_datadir} \\\
+ --includedir=%{_includedir} \\\
+ --libdir=%{_libdir} \\\
+ --libexecdir=%{_libexecdir} \\\
+ --localstatedir=%{_localstatedir} \\\
+ --sharedstatedir=%{_sharedstatedir} \\\
+ --mandir=%{_mandir} \\\
+ --infodir=%{_infodir}
+
+
+%makeinstall \
+ %{__make} \\\
+ prefix=%{?buildroot:%{buildroot}}%{_prefix} \\\
+ exec_prefix=%{?buildroot:%{buildroot}}%{_exec_prefix} \\\
+ bindir=%{?buildroot:%{buildroot}}%{_bindir} \\\
+ sbindir=%{?buildroot:%{buildroot}}%{_sbindir} \\\
+ sysconfdir=%{?buildroot:%{buildroot}}%{_sysconfdir} \\\
+ datadir=%{?buildroot:%{buildroot}}%{_datadir} \\\
+ includedir=%{?buildroot:%{buildroot}}%{_includedir} \\\
+ libdir=%{?buildroot:%{buildroot}}%{_libdir} \\\
+ libexecdir=%{?buildroot:%{buildroot}}%{_libexecdir} \\\
+ localstatedir=%{?buildroot:%{buildroot}}%{_localstatedir} \\\
+ sharedstatedir=%{?buildroot:%{buildroot}}%{_sharedstatedir} \\\
+ mandir=%{?buildroot:%{buildroot}}%{_mandir} \\\
+ infodir=%{?buildroot:%{buildroot}}%{_infodir} \\\
+ install
+
+%make_install \
+ %{__make} \\\
+ DESTDIR=%{?buildroot:%{buildroot}} \\\
+ INSTALL_ROOT=%{?buildroot:%{buildroot}} \\\
+ install \
+ rm -f %{?buildroot:%{buildroot}}%{_infodir}/dir \
+ find %{?buildroot:%{buildroot}} -regex ".*\\.la$" | xargs rm -f -- \
+ %{!?keepstatic:find %{?buildroot:%{buildroot}} -regex ".*\\.a$" | xargs rm -f --}
+
+%_smp_mflags %([ -z "$RPM_BUILD_NCPUS" ] \\\
+ && RPM_BUILD_NCPUS="`/usr/bin/getconf _NPROCESSORS_ONLN`"; \\\
+ [ "$RPM_BUILD_NCPUS" -gt 1 ] && echo "-j$RPM_BUILD_NCPUS")
+
+
+%install_info(:-:) \
+ ALL_ARGS=(%{**}) \
+ NUM_ARGS=${#ALL_ARGS[@]} \
+ if test -x sbin/install-info ; then \
+ if test -e "${ALL_ARGS[$((NUM_ARGS-1))]}" ; then \
+ sbin/install-info "${ALL_ARGS[@]}" \
+ fi \
+ fi ;
+
+%install_info_delete(:-:) \
+ ALL_ARGS=(%{**}) \
+ NUM_ARGS=${#ALL_ARGS[@]} \
+ if test -x sbin/install-info ; then \
+ if ! test -e "${ALL_ARGS[$((NUM_ARGS-1))]}" ; then \
+ sbin/install-info --quiet --delete "${ALL_ARGS[@]}" \
+ fi ; \
+ fi ;
+
+#==============================================================================
+# ---- Build policy macros.
+#
+#---------------------------------------------------------------------
+# Expanded at end of %install scriptlet.
+#
+
+%__arch_install_post /usr/lib/rpm/check-buildroot
+
+%__os_install_post \
+ /usr/lib/rpm//brp-compress \
+ %{!?__debug_package:/usr/lib/rpm/brp-strip %{__strip}} \
+ /usr/lib/rpm/brp-strip-static-archive %{__strip} \
+ /usr/lib/rpm/brp-strip-comment-note %{__strip} %{__objdump} \
+ /usr/lib/rpm/brp-python-bytecompile \
+ /usr/lib/rpm/brp-python-hardlink \
+ %{!?disable_docs_package:/usr/lib/rpm/tizen/find-docs.sh %{buildroot}} \
+%{nil}
+
+# /usr/lib/rpm/tizen/brp-implant-ident-static
+
+%__spec_install_post\
+ %{?__debug_package:%{__debug_install_post}}\
+ %{__arch_install_post}\
+ %{__os_install_post}\
+%{nil}
+
+
+%lang_package \
+%package locale \
+Summary: Translations and Locale for package %{name}\
+Group: Translations\
+AutoReqProv: 0\
+%description locale\
+This package provides translations for package %{name}.\
+%files locale -f %{name}.lang\
+%defattr(-,root,root,-)\
+%{nil}
+
+
+%docs_package \
+%package docs \
+Summary: Documentation for package %{name}\
+Group: Documentation\
+AutoReqProv: 0\
+%description docs\
+This package provides documentation for package %{name}.\
+%files docs -f documentation.list\
+%defattr(-,root,root,-)\
+%{nil}
+
+
+
+# Bad hack to set $LANG to C during all RPM builds
+%prep \
+%%prep\
+LANG=C\
+export LANG\
+unset DISPLAY\
+%{nil}
+
+%build %%build\
+LANG=C\
+export LANG\
+unset DISPLAY\
+CFLAGS="%optflags" ; export CFLAGS ; \
+CXXFLAGS="${CXXFLAGS:-%optflags}" ; export CXXFLAGS ; \
+FFLAGS="${FFLAGS:-%optflags -I%_fmoddir}" ; export FFLAGS ; \
+LD_AS_NEEDED=1; export LD_AS_NEEDED ; \
+%{nil}
+
+%install %{?_enable_debug_packages:%{?buildsubdir:%{debug_package}}}\
+%%install\
+LANG=C\
+export LANG\
+unset DISPLAY\
+rm -rf %{?buildroot:%{buildroot}} \
+mkdir -p %{?buildroot:%{buildroot}} \
+%{nil}
+
+%check %%check\
+unset DISPLAY\
+%{nil}
+
+%clean %%clean\
+rm -rf %{?buildroot:%{buildroot}} \
+%{nil}
+
+%find_lang /usr/lib/rpm/find-lang.sh %{buildroot}
+%find_docs /usr/lib/rpm/tizen/find-docs.sh %{buildroot}
+
+#
+# use internal dep generator?
+%_use_internal_dependency_generator 1
+
+#
+# Should missing %doc files terminate a build?
+%_missing_doc_files_terminate_build 1
+#
+# Should missing buildids terminate a build?
+%_missing_build_ids_terminate_build 1
+
+#
+# Should unpackaged files in a build root terminate a build?
+%_unpackaged_files_terminate_build 1
+
+%__global_cflags -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security
+
+# Disable lookups
+%_hkp_keyserver %{nil}
+
+
+#==============================================================================
+# ---- default icons directories as per the icon theme freedesktop spec
+
+%_iconstheme hicolor
+%_iconsbasedir %{_datadir}/icons/%{_iconstheme}
+
+#
+# The following is a bit heavy and will be removed
+#
+%_icons16dir %{_iconsbasedir}/16x16/apps
+%_icons22dir %{_iconsbasedir}/22x22/apps
+%_icons48dir %{_iconsbasedir}/48x48/apps
+%_icons64dir %{_iconsbasedir}/64x64/apps
+%_icons96dir %{_iconsbasedir}/96x96/apps
+%_icons192dir %{_iconsbasedir}/192x192/apps
+%_iconsscaldir %{_iconsbasedir}/scalable/apps
+
+
+#
+# Tizen icons
+#
+# %1 the name of the icon (typically the name of the package). RedHat
+# requires 3 icons sizes (48, 32, 16), all should be present.
+%tizen_icons() \
+install -D -m 644 %1-48.png $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/48x48/apps/%{name}.png\
+install -D -m 644 %1-32.png $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/32x32/apps/%{name}.png\
+install -D -m 644 %1-16.png $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/16x16/apps/%{name}.png\
+%{nil}
+
+
+#==============================================================================
+# ---- default .desktop directories per the desktop-entry freedesktop.org spec
+
+%_desktopdir %{_datadir}/applications
+
+#==============================================================================
+# ---- Generic auto req/prov filtering macros
+#
+# http://fedoraproject.org/wiki/PackagingDrafts/AutoProvidesAndRequiresFiltering
+
+# prevent anything matching from being scanned for provides
+%filter_provides_in(P) %{expand: \
+%global __filter_prov_cmd %{?__filter_prov_cmd} %{__grep} -v %{-P} '%*' | \
+}
+
+# prevent anything matching from being scanned for requires
+%filter_requires_in(P) %{expand: \
+%global __filter_req_cmd %{?__filter_req_cmd} %{__grep} -v %{-P} '%*' | \
+}
+
+# filter anything matching out of the provides stream
+%filter_from_provides() %{expand: \
+%global __filter_from_prov %{?__filter_from_prov} | %{__sed} -e '%*' \
+}
+
+# filter anything matching out of the requires stream
+%filter_from_requires() %{expand: \
+%global __filter_from_req %{?__filter_from_req} | %{__sed} -e '%*' \
+}
+
+# actually set up the filtering bits
+%filter_setup %{expand: \
+%global _use_internal_dependency_generator 0 \
+%global __deploop() while read FILE; do /usr/lib/rpm/rpmdeps -%{1} ${FILE}; done | /bin/sort -u \
+%global __find_provides /bin/sh -c "%{?__filter_prov_cmd} %{__deploop P} %{?__filter_from_prov}" \
+%global __find_requires /bin/sh -c "%{?__filter_req_cmd} %{__deploop R} %{?__filter_from_req}" \
+}
diff --git a/packaging/mimetype.diff b/packaging/mimetype.diff
new file mode 100644
index 0000000..ff1fd96
--- /dev/null
+++ b/packaging/mimetype.diff
@@ -0,0 +1,24 @@
+Index: autodeps/linux.prov
+===================================================================
+--- autodeps/linux.prov.orig
++++ autodeps/linux.prov
+@@ -11,6 +11,7 @@ solist=($(printf "%s\n" "${filelist[@]}"
+ pythonlist=
+ tcllist=
+ monolist=($(printf "%s\n" "${filelist[@]}" | egrep "\\.(exe|dll)\$"))
++mimetypelist=($(printf "%s\n" "${filelist[@]}" | egrep "\\.(desktop)\$"))
+
+ #
+ # --- Alpha does not mark 64bit dependencies
+@@ -59,6 +60,11 @@ done | sort -u
+ printf "%s\n" "${tcllist[@]}" | /usr/lib/rpm/tcl.prov | sort -u
+
+ #
++# --- mimetypes in .desktop files
++[ -x /usr/lib/rpm/mimetypes.prov -a -n "$mimetypelist" ] &&
++ printf "%s\n" "${mimetypelist[@]}" | /usr/lib/rpm/mimetypes.prov | sort -u
++
++#
+ # --- Mono exes/dlls
+ : ${MONO_PREFIX=/usr}
+ if [ -x $MONO_PREFIX/bin/mono -a -n "$monolist" ] ; then
diff --git a/packaging/no_rep_autop.diff b/packaging/no_rep_autop.diff
new file mode 100644
index 0000000..3211173
--- /dev/null
+++ b/packaging/no_rep_autop.diff
@@ -0,0 +1,12 @@
+It seems to be gone...
+
+--- lib/Makefile.am.orig 2011-05-12 12:59:42.000000000 +0000
++++ lib/Makefile.am 2011-05-12 12:59:59.000000000 +0000
+@@ -126,7 +126,6 @@ rpmdb_printlog_LDADD = \
+ $(top_builddir)/db3/fileops_autop.o \
+ $(top_builddir)/db3/hash_autop.o \
+ $(top_builddir)/db3/qam_autop.o \
+- $(top_builddir)/db3/rep_autop.o \
+ $(top_builddir)/db3/txn_autop.o \
+ $(top_builddir)/db3/util_sig.o \
+ librpm.la
diff --git a/packaging/optflags.patch b/packaging/optflags.patch
new file mode 100644
index 0000000..98f8c1c
--- /dev/null
+++ b/packaging/optflags.patch
@@ -0,0 +1,77 @@
+Index: rpm-4.9.1/rpmrc.in
+===================================================================
+--- rpm-4.9.1.orig/rpmrc.in
++++ rpm-4.9.1/rpmrc.in
+@@ -12,10 +12,10 @@
+ # "fat" binary with both archs, for Darwin
+ optflags: fat -O2 -g -arch i386 -arch ppc
+
+-optflags: i386 -O2 -g -march=i386 -mtune=i686
+-optflags: i486 -O2 -g -march=i486
+-optflags: i586 -O2 -g -march=i586
+-optflags: i686 -O2 -g -march=i686
++Optflags: i386 %{__global_cflags} -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables
++Optflags: i486 %{__global_cflags} -m32 -march=i486 -fasynchronous-unwind-tables
++Optflags: i586 %{__global_cflags} -m32 -march=core2 -mssse3 -mtune=atom -mfpmath=sse -fasynchronous-unwind-tables -fno-omit-frame-pointer
++Optflags: i686 %{__global_cflags} -m32 -march=core2 -mssse3 -mtune=atom -mfpmath=sse -fasynchronous-unwind-tables -fno-omit-frame-pointer
+ optflags: pentium3 -O2 -g -march=pentium3
+ optflags: pentium4 -O2 -g -march=pentium4
+ optflags: athlon -O2 -g -march=athlon
+@@ -58,18 +58,19 @@ optflags: hppa2.0 -O2 -g -mpa-risc-1-0
+ optflags: mips -O2 -g
+ optflags: mipsel -O2 -g
+
+-optflags: armv3l -O2 -g -march=armv3
+-optflags: armv4b -O2 -g -march=armv4
+-optflags: armv4l -O2 -g -march=armv4
+-optflags: armv4tl -O2 -g -march=armv4t
+-optflags: armv5tel -O2 -g -march=armv5te
+-optflags: armv5tejl -O2 -g -march=armv5te
+-optflags: armv6l -O2 -g -march=armv6
+-optflags: armv7l -O2 -g -march=armv7
+-optflags: armv7hl -O2 -g -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16 -mno-thumb
+-optflags: armv7nhl -O2 -g -march=armv7-a -mfloat-abi=hard -mfpu=neon -mno-thumb
+-optflags: armv7thl -O2 -g -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16 -mthumb
+-optflags: armv7tnhl -O2 -g -march=armv7-a -mfloat-abi=hard -mfpu=neon -mthumb
++optflags: armv3l %{__global_cflags} -fsigned-char -march=armv3
++optflags: armv4b %{__global_cflags} -fsigned-char -march=armv4
++optflags: armv4l %{__global_cflags} -fsigned-char -march=armv4
++optflags: armv4tl %{__global_cflags} -march=armv4t
++optflags: armv5tejl %{__global_cflags} -march=armv5te
++Optflags: armv5tel %{__global_cflags} -fmessage-length=0 -march=armv5te -mlittle-endian
++Optflags: armv6l %{__global_cflags} -fmessage-length=0 -march=armv6 -mlittle-endian -mfpu=vfp -mfloat-abi=softfp -D__SOFTFP__
++Optflags: armv7l %{__global_cflags} -fmessage-length=0 -march=armv7-a -mtune=cortex-a8 -mlittle-endian -mfpu=vfpv3 -mfloat-abi=softfp -D__SOFTFP__ -mthumb -Wa,-mimplicit-it=thumb
++optflags: armv7hl %{__global_cflags} -fmessage-length=0 -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16 -mno-thumb
++optflags: armv7nhl %{__global_cflags} -fmessage-length=0 -march=armv7-a -mfloat-abi=hard -mfpu=neon -mno-thumb
++optflags: armv7thl %{__global_cflags} -fmessage-length=0 -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16 -mthumb
++optflags: armv7tnhl %{__global_cflags} -fmessage-length=0 -march=armv7-a -mfloat-abi=hard -mfpu=neon -mthumb
++
+
+ optflags: atarist -O2 -g -fomit-frame-pointer
+ optflags: atariste -O2 -g -fomit-frame-pointer
+@@ -209,17 +210,17 @@ os_canon: MacOSX: macosx 21
+ #############################################################
+ # For a given uname().machine, the default build arch
+
+-buildarchtranslate: osfmach3_i686: i386
+-buildarchtranslate: osfmach3_i586: i386
++buildarchtranslate: osfmach3_i686: i586
++buildarchtranslate: osfmach3_i586: i586
+ buildarchtranslate: osfmach3_i486: i386
+ buildarchtranslate: osfmach3_i386: i386
+
+-buildarchtranslate: athlon: i386
+-buildarchtranslate: geode: i386
+-buildarchtranslate: pentium4: i386
+-buildarchtranslate: pentium3: i386
+-buildarchtranslate: i686: i386
+-buildarchtranslate: i586: i386
++buildarchtranslate: athlon: i586
++buildarchtranslate: geode: i586
++buildarchtranslate: pentium4: i586
++buildarchtranslate: pentium3: i586
++buildarchtranslate: i686: i586
++buildarchtranslate: i586: i586
+ buildarchtranslate: i486: i386
+ buildarchtranslate: i386: i386
+
diff --git a/packaging/pythondeps.diff b/packaging/pythondeps.diff
new file mode 100644
index 0000000..90bf61f
--- /dev/null
+++ b/packaging/pythondeps.diff
@@ -0,0 +1,44 @@
+--- ./autodeps/linux.prov.orig 2011-05-11 15:59:31.000000000 +0000
++++ ./autodeps/linux.prov 2011-05-11 16:39:09.000000000 +0000
+@@ -11,7 +11,7 @@ filelist=($(printf "%s\n" "${filelist[@]
+ solist=($(printf "%s\n" "${filelist[@]}" | grep "\\.so" | grep -v "^/lib/ld.so" | \
+ tr '\n' '\0' | xargs -0 -r file -L | grep "ELF.*shared object" | \
+ cut -d: -f1))
+-pythonlist=
++pythonlist=($(printf "%s\n" "${filelist[@]}" | egrep '/usr/bin/python.\..$'))
+ tcllist=
+ monolist=($(printf "%s\n" "${filelist[@]}" | egrep "\\.(exe|dll)\$"))
+ mimetypelist=($(printf "%s\n" "${filelist[@]}" | egrep "\\.(desktop)\$"))
+@@ -55,8 +55,8 @@ done | sort -u
+
+ #
+ # --- Python modules.
+-[ -x /usr/lib/rpm/python.prov -a -n "$pythonlist" ] &&
+- printf "%s\n" "${pythonlist[@]}" | /usr/lib/rpm/python.prov | sort -u
++[ -x /usr/lib/rpm/pythondeps.sh -a -n "$pythonlist" ] &&
++ printf "%s\n" "${pythonlist[@]}" | /usr/lib/rpm/pythondeps.sh -P | sort -u
+
+ #
+ # --- Tcl modules.
+--- ./autodeps/linux.req.orig 2011-05-11 14:28:45.000000000 +0000
++++ ./autodeps/linux.req 2011-05-11 16:39:09.000000000 +0000
+@@ -31,7 +31,7 @@ liblist=($(printf "%s\0" "${filelist[@]}
+
+ interplist=()
+ perllist=()
+-pythonlist=()
++pythonlist=($(printf "%s\n" "${filelist[@]}" | egrep '/usr/lib[^/]*/python.\..'))
+ tcllist=()
+ monolist=($(printf "%s\n" "${filelist[@]}" | egrep "\\.(exe|dll)(\\.config)?\$"))
+
+@@ -127,8 +127,8 @@ done | sort -u
+
+ #
+ # --- Python modules.
+-[ -x /usr/lib/rpm/python.req -a -n "$pythonlist" ] && \
+- printf "%s\n" "${pythonlist[@]}" | /usr/lib/rpm/python.req | sort -u
++[ -x /usr/lib/rpm/pythondeps.sh -a -n "$pythonlist" ] && \
++ printf "%s\n" "${pythonlist[@]}" | /usr/lib/rpm/pythondeps.sh -R | sort -u
+
+ #
+ # --- Tcl modules.
diff --git a/packaging/remove-translations.patch b/packaging/remove-translations.patch
new file mode 100644
index 0000000..6555226
--- /dev/null
+++ b/packaging/remove-translations.patch
@@ -0,0 +1,20 @@
+--- ./scripts/find-lang.sh.orig 2011-05-11 16:45:30.000000000 +0000
++++ ./scripts/find-lang.sh 2011-05-11 16:55:14.000000000 +0000
+@@ -122,6 +122,17 @@ fi
+ MO_NAME_NEW=$MO_NAME.tmp.$$
+ rm -f $MO_NAME_NEW
+
++# remove languages we do not yet support - but give out statistics
++find $TOP_DIR/usr/share/locale/ -maxdepth 1 -type d | sed 's:'"$TOP_DIR"/usr/share/locale/'::; /^$/d' | while read dir; do
++ if ! rpm -ql filesystem | egrep -q "/usr/share/locale/$dir"$; then
++ find $TOP_DIR/usr/share/locale/$dir -name *.mo | sed 's:'"$TOP_DIR"'::' | while read file; do
++ echo -n "removing translation $file: "
++ msgunfmt "$TOP_DIR/$file" | msgfmt --statistics -o /dev/null -
++ done
++ rm -rf $TOP_DIR/usr/share/locale/$dir
++ fi
++done
++
+ find $TOP_DIR -type f -o -type l|sed '
+ s:'"$TOP_DIR"'::
+ '"$ALL_NAME$MO"'s:\(.*/locale/\)\([^/_]\+\)\(.*\.mo$\):%lang(\2) %doc \1\2\3:
diff --git a/packaging/rpm-4.5.90-gstreamer-provides.patch b/packaging/rpm-4.5.90-gstreamer-provides.patch
new file mode 100644
index 0000000..a9ebfe2
--- /dev/null
+++ b/packaging/rpm-4.5.90-gstreamer-provides.patch
@@ -0,0 +1,16 @@
+diff --git a/build/rpmfc.c b/build/rpmfc.c
+index 94fb68e..525915b 100644
+--- a/build/rpmfc.c
++++ b/build/rpmfc.c
+@@ -1093,6 +1093,11 @@ assert(s != NULL);
+ free(buf);
+ }
+
++ /* Add possible GStreamer provides */
++ if (!fc->skipProv && isDSO) {
++ xx = rpmfcHelper(fc, 'P', "gstreamer");
++ }
++
+ exit:
+ soname = _free(soname);
+ if (elf) (void) elf_end(elf);
diff --git a/packaging/rpm-4.5.90-pkgconfig-path.patch b/packaging/rpm-4.5.90-pkgconfig-path.patch
new file mode 100644
index 0000000..07ce123
--- /dev/null
+++ b/packaging/rpm-4.5.90-pkgconfig-path.patch
@@ -0,0 +1,13 @@
+diff --git a/macros.in b/macros.in
+index 830072a..bdce7f4 100644
+--- a/macros.in
++++ b/macros.in
+@@ -805,6 +805,8 @@ print (t)\
+ export RPM_BUILD_ROOT}\
+ %{?_javaclasspath:CLASSPATH=\"%{_javaclasspath}\"\
+ export CLASSPATH}\
++ PKG_CONFIG_PATH=\"%{_libdir}/pkgconfig:%{_datadir}/pkgconfig\"\
++ export PKG_CONFIG_PATH\
+ \
+ %{verbose:set -x}%{!verbose:exec > /dev/null}\
+ umask 022\
diff --git a/packaging/rpm-4.7.90-devel-autodep.patch b/packaging/rpm-4.7.90-devel-autodep.patch
new file mode 100644
index 0000000..84e5cee
--- /dev/null
+++ b/packaging/rpm-4.7.90-devel-autodep.patch
@@ -0,0 +1,157 @@
+diff -up rpm-4.7.90.git9278/build/rpmfc.c.devel-autodep rpm-4.7.90.git9278/build/rpmfc.c
+--- rpm-4.7.90.git9278/build/rpmfc.c.devel-autodep 2009-09-01 10:45:07.000000000 +0300
++++ rpm-4.7.90.git9278/build/rpmfc.c 2009-09-01 11:00:15.000000000 +0300
+@@ -501,7 +501,7 @@ static const struct rpmfcTokens_s const
+ { "GLS_BINARY_LSB_FIRST", RPMFC_WHITE|RPMFC_INCLUDE },
+ { " DB ", RPMFC_WHITE|RPMFC_INCLUDE },
+
+- { "symbolic link to", RPMFC_SYMLINK },
++ { "symbolic link to", RPMFC_SYMLINK|RPMFC_INCLUDE },
+ { "socket", RPMFC_DEVICE },
+ { "special", RPMFC_DEVICE },
+ { " text", RPMFC_TEXT|RPMFC_INCLUDE },
+@@ -663,6 +663,105 @@ rpmds rpmfcRequires(rpmfc fc)
+
+
+ /**
++ * Ensure that symlinks for shared libs generate a dep on the shared lib
++ * @param fc file classifier
++ * @return 0 on success
++ */
++static int rpmfcSYMLINK(rpmfc fc)
++{
++ const char * fn = fc->fn[fc->ix];
++ struct stat sb;
++ int fdno;
++
++ if (fc->skipReq)
++ return 0;
++
++ if (stat(fn, &sb) < 0)
++ return -1;
++ if (S_ISLNK(sb.st_mode))
++ return -1;
++
++ fdno = open(fn, O_RDONLY);
++ if (fdno < 0) {
++ return fdno;
++ }
++
++#if HAVE_GELF_H && HAVE_LIBELF
++ Elf * elf = NULL;
++ GElf_Ehdr ehdr_mem, * ehdr;
++ int isElf64 = 0;
++ int i, cnt;
++ char * soname = NULL;
++ rpmds ds;
++
++ (void) elf_version(EV_CURRENT);
++ elf = NULL;
++ if ((elf = elf_begin (fdno, ELF_C_READ_MMAP, NULL)) == NULL
++ || elf_kind(elf) != ELF_K_ELF
++ || (ehdr = gelf_getehdr(elf, &ehdr_mem)) == NULL
++ || ehdr->e_type != ET_DYN)
++ goto exit;
++
++/* alpha uses /lib, not /lib64 so don't add (64bit) deps */
++#if !defined(__alpha__)
++ isElf64 = ehdr->e_ident[EI_CLASS] == ELFCLASS64;
++#endif
++
++ for (i = 0; i < ehdr->e_phnum; ++i) {
++ GElf_Phdr phdr_mem;
++ GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
++ GElf_Shdr shdr_mem;
++ Elf_Data * data = NULL;
++ Elf_Scn * scn;
++ GElf_Shdr *shdr;
++
++ if (phdr == NULL || phdr->p_type != PT_DYNAMIC)
++ continue;
++
++ scn = gelf_offscn(elf, phdr->p_offset);
++ shdr = gelf_getshdr(scn, &shdr_mem);
++
++ if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
++ data = elf_getdata (scn, NULL);
++ if (data == NULL)
++ continue;
++
++ for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt) {
++ GElf_Dyn dynmem;
++ GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem);
++ char *depname = NULL;
++
++ if (dyn == NULL)
++ break;
++ if (dyn->d_tag != DT_SONAME)
++ continue;
++
++ /* add the soname to package deps */
++ soname = elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val);
++ if (soname == NULL)
++ break;
++
++ rasprintf(&depname, "%s%s", soname, isElf64 ? "()(64bit)" : "");
++ /* Add to package dependencies. */
++ ds = rpmdsSingle(RPMTAG_REQUIRENAME, depname, "",
++ RPMSENSE_FIND_REQUIRES);
++ free(depname);
++
++ rpmdsMerge(&fc->requires, ds);
++ rpmfcAddFileDep(&fc->ddict, fc->ix, ds);
++ ds = rpmdsFree(ds);
++ break;
++ }
++ }
++exit:
++ if (elf) (void) elf_end(elf);
++ close(fdno);
++ return 0;
++#endif
++ return -1;
++}
++
++/**
+ * Extract script dependencies.
+ * @param fc file classifier
+ * @return 0 on success
+@@ -1118,6 +1217,7 @@ static const struct rpmfcApplyTbl_s cons
+ RPMFC_PERL|RPMFC_PYTHON|RPMFC_MONO|RPMFC_OCAML|
+ RPMFC_PKGCONFIG|RPMFC_LIBTOOL) },
+ { rpmfcMISC, RPMFC_FONT|RPMFC_TEXT },
++ { rpmfcSYMLINK, RPMFC_SYMLINK },
+ { NULL, 0 }
+ };
+
+@@ -1138,6 +1238,7 @@ rpmRC rpmfcApply(rpmfc fc)
+ int ix;
+ int i;
+ int xx;
++ int skipping = 0;
+
+ /* Generate package and per-file dependencies. */
+ for (fc->ix = 0; fc->fn[fc->ix] != NULL; fc->ix++) {
+@@ -1192,11 +1293,13 @@ rpmRC rpmfcApply(rpmfc fc)
+ default:
+ break;
+ case 'P':
++ skipping = fc->skipProv;
+ ds = rpmdsSingle(RPMTAG_PROVIDENAME, N, EVR, Flags);
+ dix = rpmdsFind(fc->provides, ds);
+ ds = rpmdsFree(ds);
+ break;
+ case 'R':
++ skipping = fc->skipReq;
+ ds = rpmdsSingle(RPMTAG_REQUIRENAME, N, EVR, Flags);
+ dix = rpmdsFind(fc->requires, ds);
+ ds = rpmdsFree(ds);
+@@ -1218,7 +1321,7 @@ assert(dix >= 0);
+ previx = ix;
+ xx = argiAdd(&fc->fddictx, ix, argiCount(fc->ddictx)-1);
+ }
+- if (fc->fddictn && fc->fddictn->vals)
++ if (fc->fddictn && fc->fddictn->vals && !skipping)
+ fc->fddictn->vals[ix]++;
+ }
+
diff --git a/packaging/rpm-4.8.0-tilde.patch b/packaging/rpm-4.8.0-tilde.patch
new file mode 100644
index 0000000..1132c37
--- /dev/null
+++ b/packaging/rpm-4.8.0-tilde.patch
@@ -0,0 +1,61 @@
+Index: rpm-4.8.0-beta1/lib/rpmvercmp.c
+===================================================================
+--- rpm-4.8.0-beta1.orig/lib/rpmvercmp.c
++++ rpm-4.8.0-beta1/lib/rpmvercmp.c
+@@ -33,12 +33,16 @@ int rpmvercmp(const char * a, const char
+
+ /* loop through each version segment of str1 and str2 and compare them */
+ while (*one && *two) {
+- while (*one && !risalnum(*one)) one++;
+- while (*two && !risalnum(*two)) two++;
++ while (*one && !risalnum(*one) && *one != '~') one++;
++ while (*two && !risalnum(*two) && *two != '~') two++;
+
+ /* If we ran to the end of either, we are finished with the loop */
+ if (!(*one && *two)) break;
+
++ /* If exactly one side has a tilde, it is decided. */
++ if ((*one == '~') ^ (*two == '~'))
++ break;
++
+ str1 = one;
+ str2 = two;
+
+@@ -103,6 +107,11 @@ int rpmvercmp(const char * a, const char
+ /* this catches the case where all numeric and alpha segments have */
+ /* compared identically but the segment sepparating characters were */
+ /* different */
++ if (*two == '~')
++ return 1;
++ else if (*one == '~')
++ return -1;
++
+ if ((!*one) && (!*two)) return 0;
+
+ /* whichever version still has characters left over wins */
+Index: rpm-4.8.0-beta1/build/parsePreamble.c
+===================================================================
+--- rpm-4.8.0-beta1.orig/build/parsePreamble.c
++++ rpm-4.8.0-beta1/build/parsePreamble.c
+@@ -523,7 +523,7 @@ static int handlePreambleTag(rpmSpec spe
+ case RPMTAG_VERSION:
+ case RPMTAG_RELEASE:
+ SINGLE_TOKEN_ONLY;
+- if (rpmCharCheck(spec, field, strlen(field), "._+%{}") != RPMRC_OK) return RPMRC_FAIL;
++ if (rpmCharCheck(spec, field, strlen(field), "~._+%{}") != RPMRC_OK) return RPMRC_FAIL;
+ headerPutString(pkg->header, tag, field);
+ break;
+ case RPMTAG_URL:
+Index: rpm-4.8.0-beta1/build/parseReqs.c
+===================================================================
+--- rpm-4.8.0-beta1.orig/build/parseReqs.c
++++ rpm-4.8.0-beta1/build/parseReqs.c
+@@ -168,7 +168,7 @@ rpmRC parseRCPOT(rpmSpec spec, Package p
+ }
+ EVR = xmalloc((ve-v) + 1);
+ rstrlcpy(EVR, v, (ve-v) + 1);
+- if (rpmCharCheck(spec, EVR, ve-v, ".-_+:%{}")) goto exit;
++ if (rpmCharCheck(spec, EVR, ve-v, "~.-_+:%{}")) goto exit;
+ re = ve; /* ==> next token after EVR string starts here */
+ } else
+ EVR = NULL;
diff --git a/packaging/rpm-4.9.0-tizen-arm.patch b/packaging/rpm-4.9.0-tizen-arm.patch
new file mode 100644
index 0000000..fb1dfbc
--- /dev/null
+++ b/packaging/rpm-4.9.0-tizen-arm.patch
@@ -0,0 +1,88 @@
+Index: rpm-4.9.0/macros.in
+===================================================================
+--- rpm-4.9.0.orig/macros.in
++++ rpm-4.9.0/macros.in
+@@ -1032,7 +1032,7 @@ done \
+
+ #------------------------------------------------------------------------------
+ # arch macro for all supported ARM processors
+-%arm armv3l armv4b armv4l armv4tl armv5tel armv5tejl armv6l armv7l
++%arm armv3l armv4b armv4l armv4tl armv5tel armv5tejl armv6l armv7l armv7hl armv7nhl armv7tnhl armv7thl
+
+ #------------------------------------------------------------------------------
+ # arch macro for all supported Sparc processors
+Index: rpm-4.9.0/rpmrc.in
+===================================================================
+--- rpm-4.9.0.orig/rpmrc.in
++++ rpm-4.9.0/rpmrc.in
+@@ -66,6 +66,10 @@ optflags: armv5tel -O2 -g -march=armv5te
+ optflags: armv5tejl -O2 -g -march=armv5te
+ optflags: armv6l -O2 -g -march=armv6
+ optflags: armv7l -O2 -g -march=armv7
++optflags: armv7hl -O2 -g -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16 -mno-thumb
++optflags: armv7nhl -O2 -g -march=armv7-a -mfloat-abi=hard -mfpu=neon -mno-thumb
++optflags: armv7thl -O2 -g -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16 -mthumb
++optflags: armv7tnhl -O2 -g -march=armv7-a -mfloat-abi=hard -mfpu=neon -mthumb
+
+ optflags: atarist -O2 -g -fomit-frame-pointer
+ optflags: atariste -O2 -g -fomit-frame-pointer
+@@ -140,6 +144,11 @@ arch_canon: armv5tel: armv5tel 12
+ arch_canon: armv5tejl: armv5tejl 12
+ arch_canon: armv6l: armv6l 12
+ arch_canon: armv7l: armv7l 12
++arch_canon: armv7hl: armv7hl 12
++arch_canon: armv7nhl: armv7nhl 12
++arch_canon: armv7thl: armv7thl 12
++arch_canon: armv7tnhl: armv7tnhl 12
++
+
+ arch_canon: m68kmint: m68kmint 13
+ arch_canon: atarist: m68kmint 13
+@@ -248,6 +257,10 @@ buildarchtranslate: armv5tel: armv5tel
+ buildarchtranslate: armv5tejl: armv5tejl
+ buildarchtranslate: armv6l: armv6l
+ buildarchtranslate: armv7l: armv7l
++buildarchtranslate: armv7hl: armv7hl
++buildarchtranslate: armv7nhl: armv7nhl
++buildarchtranslate: armv7thl: armv7thl
++buildarchtranslate: armv7tnhl: armv7tnhl
+
+ buildarchtranslate: atarist: m68kmint
+ buildarchtranslate: atariste: m68kmint
+@@ -336,6 +349,10 @@ arch_compat: armv5tel: armv4tl
+ arch_compat: armv4tl: armv4l
+ arch_compat: armv4l: armv3l
+ arch_compat: armv3l: noarch
++arch_compat: armv7tnhl: armv7nhl armv7thl
++arch_compat: armv7nhl: armv7hl
++arch_compat: armv7thl: armv7hl
++arch_compat: armv7hl: noarch
+
+ arch_compat: atarist: m68kmint noarch
+ arch_compat: atariste: m68kmint noarch
+@@ -441,6 +458,11 @@ buildarch_compat: armv4tl: armv4l
+ buildarch_compat: armv4l: armv3l
+ buildarch_compat: armv3l: noarch
+
++buildarch_compat: armv7tnhl: armv7nhl armv7thl
++buildarch_compat: armv7nhl: armv7hl
++buildarch_compat: armv7thl: armv7hl
++buildarch_compat: armv7hl: noarch
++
+ buildarch_compat: hppa2.0: hppa1.2
+ buildarch_compat: hppa1.2: hppa1.1
+ buildarch_compat: hppa1.1: hppa1.0
+Index: rpm-4.9.0/installplatform
+===================================================================
+--- rpm-4.9.0.orig/installplatform
++++ rpm-4.9.0/installplatform
+@@ -19,7 +19,8 @@ RPMRC_GNU="`$RPM --eval '%{_gnu}'`"
+ case "$arch" in
+ i[3456]86|pentium[34]|athlon|geode) SUBSTS='s_i386_i386_ s_i386_i486_ s_i386_i586_ s_i386_i686_ s_i386_pentium3_ s_i386_pentium4_ s_i386_athlon_ s_i386_geode_' ;;
+ alpha*) SUBSTS='s_alpha_alpha_ s_alpha_alphaev5_ s_alpha_alphaev56_ s_alpha_alphapca56_ s_alpha_alphaev6_ s_alpha_alphaev67_' ;;
+- arm*) SUBSTS='s_arm_arm_ s_arm_armv3l_ s_arm_armv4l_ s_arm_armv4tl_ s_arm_armv5tel_ s_arm_armv5tejl_ s_arm_armv6l_ s_arm_armv7l_' ;;
++ arm*) SUBSTS='s_arm_arm_ s_arm_armv3l_ s_arm_armv4l_ s_arm_armv4tl_ s_arm_armv5tel_ s_arm_armv5tejl_ s_arm_armv6l_ s_arm_armv7l_ s_arm_armv7hl_ s_arm_armv7nhl_ s_arm_armv7tnhl
++ _ s_arm_armv7thl_' ;;
+ sh4*) SUBSTS='s_sh4_sh4_ s_sh4_sh4a_' ;;
+ sparc*) SUBSTS='s_sparc\(64\|64v\|v9v\|v9\)_sparc_ s_sparc64_sparcv9_;s_sparc\([^v]\|$\)_sparcv9\1_ s_sparcv9_sparc64_;s_sparc\([^6]\|$\)_sparc64\1_' ;;
+ powerpc*|ppc*) SUBSTS='s_ppc64_ppc_ s_ppc\([^6ip]\|$\)_ppc64\1_ s_ppc\([^6ip]\|$\)_ppciseries_ s_ppc\([^6ip]\|$\)_ppcpseries_ s_ppc\([^6ip]\|$\)_ppc64iseries_ s_ppc\([^6ip]\|$\)_ppc64pseries_' ;;
diff --git a/packaging/rpm-beecrypt.diff b/packaging/rpm-beecrypt.diff
new file mode 100644
index 0000000..55036f7
--- /dev/null
+++ b/packaging/rpm-beecrypt.diff
@@ -0,0 +1,1725 @@
+--- ./config.h.in.orig 2011-07-15 09:37:41.000000000 +0000
++++ ./config.h.in 2011-07-18 16:34:29.000000000 +0000
+@@ -13,6 +13,9 @@
+ /* Define to 1 if you have the `basename' function. */
+ #undef HAVE_BASENAME
+
++/* Define to 1 if you have the <beecrypt/api.h> header file. */
++#undef HAVE_BEECRYPT_API_H
++
+ /* Define as 1 if you bzip2 1.0 */
+ #undef HAVE_BZ2_1_0
+
+@@ -77,7 +80,7 @@
+ /* Define as 1 if your zlib has gzseek() */
+ #undef HAVE_GZSEEK
+
+-/* Define if you have the iconv() function. */
++/* Define if you have the iconv() function and it works. */
+ #undef HAVE_ICONV
+
+ /* Define to 1 if you have the <inttypes.h> header file. */
+@@ -227,6 +230,10 @@
+ */
+ #undef LT_OBJDIR
+
++/* Define to the sub-directory in which libtool stores uninstalled libraries.
++ */
++#undef LT_OBJDIR
++
+ /* Define to 1 if `major', `minor', and `makedev' are declared in <mkdev.h>.
+ */
+ #undef MAJOR_IN_MKDEV
+@@ -311,6 +318,9 @@
+ /* Build with acl support? */
+ #undef WITH_ACL
+
++/* Build with beecrypt instead of nss3 support? */
++#undef WITH_BEECRYPT
++
+ /* Build with capability support? */
+ #undef WITH_CAP
+
+--- ./configure.ac.orig 2011-07-15 09:37:20.000000000 +0000
++++ ./configure.ac 2011-07-18 16:34:29.000000000 +0000
+@@ -252,12 +252,43 @@ AC_CHECK_HEADERS([dwarf.h], [
+ AM_CONDITIONAL(LIBDWARF,[test "$WITH_LIBDWARF" = yes])
+
+ #=================
++# Check for beecrypt library if requested.
++AC_ARG_WITH(beecrypt, [ --with-beecrypt build with beecrypt support ],,[with_beecrypt=yes])
++AC_ARG_WITH(internal_beecrypt, [ --with-internal-beecrypt build with internal beecrypt library ],,[with_internal_beecrypt=yes])
++AM_CONDITIONAL([WITH_INTERNAL_BEECRYPT],[test "$with_internal_beecrypt" = yes])
++if test "$with_internal_beecrypt" = yes ; then
++ with_beecrypt=yes
++fi
++AM_CONDITIONAL([WITH_BEECRYPT],[test "$with_beecrypt" = yes])
++
++WITH_BEECRYPT_INCLUDE=
++WITH_BEECRYPT_LIB=
++if test "$with_beecrypt" = yes ; then
++ AC_DEFINE(WITH_BEECRYPT, 1, [Build with beecrypt instead of nss3 support?])
++ if test "$with_internal_beecrypt" = yes ; then
++ WITH_BEECRYPT_INCLUDE="-I\$(top_srcdir)/beecrypt"
++ AC_DEFINE(HAVE_BEECRYPT_API_H, 1, [Define to 1 if you have the <beecrypt/api.h> header file.])
++ else
++ AC_CHECK_LIB(beecrypt, mpfprintln, [
++ WITH_BEECRYPT_LIB="-lbeecrypt"
++ ],[
++ AC_MSG_ERROR([missing required library 'beecrypt'])
++ ])
++ AC_CHECK_HEADER([beecrypt/api.h], [AC_DEFINE(HAVE_BEECRYPT_API_H, 1, [Define to 1 if you have the <beecrypt/api.h> header file.])
++ ])
++ fi
++fi
++AC_SUBST(WITH_BEECRYPT_LIB)
++AC_SUBST(WITH_BEECRYPT_INCLUDE)
++
++#=================
+ # Check for NSS library.
+ # We need nss.h from NSS which needs nspr.h. Unfortunately both glibc and NSS
+ # have a header named nss.h... so make extra check for NSS's sechash.h
+ # which we use too and hopefully is slightly more unique to NSS.
+ WITH_NSS_INCLUDE=
+ WITH_NSS_LIB=
++if test "$with_beecrypt" != yes ; then
+ AC_CHECK_HEADERS([nspr.h nss.h sechash.h], [], [
+ AC_MSG_ERROR([missing required NSPR / NSS header])
+ ])
+@@ -266,6 +297,7 @@ AC_CHECK_LIB(nss3, NSS_NoDB_Init, [
+ ], [
+ AC_MSG_ERROR([missing required NSS library 'nss3'])
+ ])
++fi
+ AC_SUBST(WITH_NSS_INCLUDE)
+ AC_SUBST(WITH_NSS_LIB)
+
+--- ./rpmio/Makefile.am.orig 2011-07-15 09:36:33.000000000 +0000
++++ ./rpmio/Makefile.am 2011-07-18 16:36:35.000000000 +0000
+@@ -2,6 +2,7 @@
+
+ AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir) -I$(top_builddir)/include/
+ AM_CPPFLAGS += @WITH_NSS_INCLUDE@
++AM_CPPFLAGS += @WITH_BEECRYPT_INCLUDE@
+ AM_CPPFLAGS += @WITH_POPT_INCLUDE@
+ AM_CPPFLAGS += -I$(top_srcdir)/misc
+ AM_CPPFLAGS += -DRPMCONFIGDIR="\"@RPMCONFIGDIR@\""
+@@ -17,10 +18,17 @@ librpmio_la_SOURCES = \
+ rpmstring.c rpmfileutil.c \
+ rpmkeyring.c
+
++if WITH_BEECRYPT
++librpmio_la_SOURCES += digest_beecrypt.c
++else
++librpmio_la_SOURCES += digest_nss.c
++endif
++
+ librpmio_la_LDFLAGS = -version-info 2:1:0
+ librpmio_la_LIBADD = \
+ ../misc/libmisc.la \
+ @WITH_NSS_LIB@ \
++ @WITH_BEECRYPT_LIB@ \
+ @WITH_BZ2_LIB@ \
+ @WITH_ZLIB_LIB@ \
+ @WITH_LIBELF_LIB@ \
+@@ -28,6 +36,15 @@ librpmio_la_LIBADD = \
+ @WITH_LZMA_LIB@ \
+ -lpthread
+
++if WITH_INTERNAL_BEECRYPT
++librpmio_la_LIBADD += $(libbeecrypt_la)
++
++libbeecrypt_la = $(top_builddir)/beecrypt/libbeecrypt_nolibdir.la
++
++$(top_builddir)/beecrypt/libbeecrypt_nolibdir.la: $(top_builddir)/beecrypt/libbeecrypt.la
++ sed -e 's/libdir=.*/libdir=/' < $(top_builddir)/beecrypt/libbeecrypt.la > $(top_builddir)/beecrypt/libbeecrypt_nolibdir.la
++endif
++
+ if WITH_LUA
+ AM_CPPFLAGS += -I$(top_srcdir)/luaext/
+ AM_CPPFLAGS += @LUA_CFLAGS@
+--- ./rpmio/base64.c.orig 2011-07-12 11:28:13.000000000 +0000
++++ ./rpmio/base64.c 2011-07-18 16:34:29.000000000 +0000
+@@ -4,8 +4,11 @@
+ #include <arpa/inet.h>
+ #include <stdlib.h>
+
++#include "system.h"
++
+ #include "rpmio/base64.h"
+
++#ifndef WITH_BEECRYPT
+
+ static char base64_encode_value(char value_in)
+ {
+@@ -253,3 +256,4 @@ int main(int argc, char *argv[])
+ }
+ #endif
+
++#endif /* WITH_BEECRYPT */
+--- ./rpmio/digest.c.orig 2011-07-12 11:28:13.000000000 +0000
++++ ./rpmio/digest.c 2011-07-18 16:34:29.000000000 +0000
+@@ -4,25 +4,12 @@
+
+ #include "system.h"
+
++#include <rpm/rpmpgp.h>
+ #include "rpmio/digest.h"
++#include "rpmio/rpmio_internal.h"
+
+ #include "debug.h"
+
+-#ifdef SHA_DEBUG
+-#define DPRINTF(_a) fprintf _a
+-#else
+-#define DPRINTF(_a)
+-#endif
+-
+-
+-/**
+- * MD5/SHA1 digest private data.
+- */
+-struct DIGEST_CTX_s {
+- rpmDigestFlags flags; /*!< Bit(s) to control digest operation. */
+- HASHContext *hashctx; /*!< Internal NSS hash context. */
+- int algo; /*!< Used hash algorithm */
+-};
+
+ #define DIGESTS_MAX 11
+ struct rpmDigestBundle_s {
+@@ -109,138 +96,3 @@ DIGEST_CTX rpmDigestBundleDupCtx(rpmDige
+ return dup;
+ }
+
+-DIGEST_CTX
+-rpmDigestDup(DIGEST_CTX octx)
+-{
+- DIGEST_CTX nctx = NULL;
+- if (octx) {
+- HASHContext *hctx = HASH_Clone(octx->hashctx);
+- if (hctx) {
+- nctx = memcpy(xcalloc(1, sizeof(*nctx)), octx, sizeof(*nctx));
+- nctx->hashctx = hctx;
+- }
+- }
+- return nctx;
+-}
+-
+-RPM_GNUC_PURE
+-static HASH_HashType getHashType(int hashalgo)
+-{
+- switch (hashalgo) {
+- case PGPHASHALGO_MD5:
+- return HASH_AlgMD5;
+- break;
+- case PGPHASHALGO_MD2:
+- return HASH_AlgMD2;
+- break;
+- case PGPHASHALGO_SHA1:
+- return HASH_AlgSHA1;
+- break;
+- case PGPHASHALGO_SHA256:
+- return HASH_AlgSHA256;
+- break;
+- case PGPHASHALGO_SHA384:
+- return HASH_AlgSHA384;
+- break;
+- case PGPHASHALGO_SHA512:
+- return HASH_AlgSHA512;
+- break;
+- case PGPHASHALGO_RIPEMD160:
+- case PGPHASHALGO_TIGER192:
+- case PGPHASHALGO_HAVAL_5_160:
+- default:
+- return HASH_AlgNULL;
+- break;
+- }
+-}
+-
+-size_t
+-rpmDigestLength(int hashalgo)
+-{
+- return HASH_ResultLen(getHashType(hashalgo));
+-}
+-
+-DIGEST_CTX
+-rpmDigestInit(int hashalgo, rpmDigestFlags flags)
+-{
+- HASH_HashType type = getHashType(hashalgo);
+- HASHContext *hashctx = NULL;
+- DIGEST_CTX ctx = NULL;
+-
+- if (type == HASH_AlgNULL || rpmInitCrypto() < 0)
+- goto exit;
+-
+- if ((hashctx = HASH_Create(type)) != NULL) {
+- ctx = xcalloc(1, sizeof(*ctx));
+- ctx->flags = flags;
+- ctx->algo = hashalgo;
+- ctx->hashctx = hashctx;
+- HASH_Begin(ctx->hashctx);
+- }
+-
+-DPRINTF((stderr, "*** Init(%x) ctx %p hashctx %p\n", flags, ctx, ctx->hashctx));
+-exit:
+- return ctx;
+-}
+-
+-int
+-rpmDigestUpdate(DIGEST_CTX ctx, const void * data, size_t len)
+-{
+- size_t partlen;
+- const unsigned char *ptr = data;
+-
+- if (ctx == NULL)
+- return -1;
+-
+-DPRINTF((stderr, "*** Update(%p,%p,%zd) hashctx %p \"%s\"\n", ctx, data, len, ctx->hashctx, ((char *)data)));
+- partlen = ~(unsigned int)0xFF;
+- while (len > 0) {
+- if (len < partlen) {
+- partlen = len;
+- }
+- HASH_Update(ctx->hashctx, ptr, partlen);
+- ptr += partlen;
+- len -= partlen;
+- }
+- return 0;
+-}
+-
+-int
+-rpmDigestFinal(DIGEST_CTX ctx, void ** datap, size_t *lenp, int asAscii)
+-{
+- unsigned char * digest;
+- unsigned int digestlen;
+-
+- if (ctx == NULL)
+- return -1;
+- digestlen = HASH_ResultLenContext(ctx->hashctx);
+- digest = xmalloc(digestlen);
+-
+-DPRINTF((stderr, "*** Final(%p,%p,%p,%zd) hashctx %p digest %p\n", ctx, datap, lenp, asAscii, ctx->hashctx, digest));
+-/* FIX: check rc */
+- HASH_End(ctx->hashctx, digest, (unsigned int *) &digestlen, digestlen);
+-
+- /* Return final digest. */
+- if (!asAscii) {
+- if (lenp) *lenp = digestlen;
+- if (datap) {
+- *datap = digest;
+- digest = NULL;
+- }
+- } else {
+- if (lenp) *lenp = (2*digestlen) + 1;
+- if (datap) {
+- const uint8_t * s = (const uint8_t *) digest;
+- *datap = pgpHexStr(s, digestlen);
+- }
+- }
+- if (digest) {
+- memset(digest, 0, digestlen); /* In case it's sensitive */
+- free(digest);
+- }
+- HASH_Destroy(ctx->hashctx);
+- memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
+- free(ctx);
+- return 0;
+-}
+-
+--- ./rpmio/digest.h.orig 2011-07-12 11:28:13.000000000 +0000
++++ ./rpmio/digest.h 2011-07-18 16:34:29.000000000 +0000
+@@ -1,11 +1,6 @@
+ #ifndef _RPMDIGEST_H
+ #define _RPMDIGEST_H
+
+-#include <nss.h>
+-#include <sechash.h>
+-#include <keyhi.h>
+-#include <cryptohi.h>
+-
+ #include <rpm/rpmpgp.h>
+ #include "rpmio/base64.h"
+
+@@ -42,8 +37,18 @@ struct pgpDig_s {
+ struct pgpDigParams_s pubkey;
+
+ /* DSA/RSA parameters */
+- SECKEYPublicKey *keydata;
+- SECItem *sigdata;
++ void *keydata;
++ void *sigdata;
+ };
+
++void pgpCleanRSADSA(pgpDig dig);
++
++int pgpSetSigMpiRSA(pgpDig dig, int num, const uint8_t *p);
++int pgpSetPubMpiRSA(pgpDig dig, int num, const uint8_t *p);
++int pgpVerifyRSA(pgpDig dig, uint8_t *hash, size_t hashlen);
++
++int pgpSetSigMpiDSA(pgpDig dig, int num, const uint8_t *p);
++int pgpSetPubMpiDSA(pgpDig dig, int num, const uint8_t *p);
++int pgpVerifyDSA(pgpDig dig, uint8_t *hash, size_t hashlen);
++
+ #endif /* _RPMDIGEST_H */
+--- ./rpmio/digest_beecrypt.c.orig 2011-07-18 16:34:29.000000000 +0000
++++ ./rpmio/digest_beecrypt.c 2011-07-18 16:34:29.000000000 +0000
+@@ -0,0 +1,493 @@
++#include "system.h"
++
++#include <beecrypt.h>
++#include <dsa.h>
++#include <endianness.h>
++#include <md5.h>
++#include <mp.h>
++#include <rsa.h>
++#include <rsapk.h>
++#include <sha1.h>
++#if HAVE_BEECRYPT_API_H
++#include <sha256.h>
++#include <sha384.h>
++#include <sha512.h>
++#endif
++
++#include <rpm/rpmpgp.h>
++#include "rpmio/digest.h"
++#include "rpmio/rpmio_internal.h"
++
++#include "debug.h"
++
++/* interface to beecrpyt crypto framework */
++
++/**************************** init ************************************/
++
++int rpmInitCrypto(void) {
++ return 0;
++}
++
++int rpmFreeCrypto(void) {
++ return 0;
++}
++
++/**************************** helpers ************************************/
++
++static inline unsigned int pgpMpiBits(const uint8_t *p)
++{
++ return ((p[0] << 8) | p[1]);
++}
++
++static inline size_t pgpMpiLen(const uint8_t *p)
++{
++ return (2 + ((pgpMpiBits(p)+7)>>3));
++}
++
++static inline char * pgpHexCvt(char *t, const byte *s, int nbytes)
++ /*@modifies *t @*/
++{
++ static char hex[] = "0123456789abcdef";
++ while (nbytes-- > 0) {
++ unsigned int i;
++ i = *s++;
++ *t++ = hex[ (i >> 4) & 0xf ];
++ *t++ = hex[ (i ) & 0xf ];
++ }
++ *t = '\0';
++ return t;
++}
++
++static const char * pgpMpiHex(const byte *p)
++{
++ static char prbuf[2048];
++ char *t = prbuf;
++ t = pgpHexCvt(t, p+2, pgpMpiLen(p)-2);
++ return prbuf;
++}
++
++static int pgpHexSet(int lbits, mpnumber * mpn, const byte * p)
++{
++ unsigned int mbits = pgpMpiBits(p);
++ unsigned int nbits;
++ unsigned int nbytes;
++ char *t;
++ unsigned int ix;
++
++ nbits = (lbits > mbits ? lbits : mbits);
++ nbytes = ((nbits + 7) >> 3);
++ t = xmalloc(2*nbytes+1);
++ ix = 2 * ((nbits - mbits) >> 3);
++
++ if (ix > 0) memset(t, (int)'0', ix);
++ strcpy(t+ix, pgpMpiHex(p));
++ (void) mpnsethex(mpn, t);
++ t = _free(t);
++ return 0;
++}
++
++void pgpCleanRSADSA(pgpDig dig)
++{
++ if (!dig)
++ return;
++ if (dig->keydata) {
++ dig->keydata= _free(dig->keydata);
++ }
++ if (dig->sigdata) {
++ dig->sigdata = _free(dig->sigdata);
++ }
++}
++
++
++/****************************** RSA **************************************/
++
++struct pgpDigSigRSA_s {
++ mpnumber c;
++};
++
++struct pgpDigPubRSA_s {
++ rsapk rsa_pk;
++};
++
++int
++pgpSetSigMpiRSA(pgpDig dig, int num, const uint8_t *p)
++{
++ struct pgpDigSigRSA_s *sig;
++ if (num != 0)
++ return 1;
++ if (!dig->sigdata)
++ dig->sigdata = xcalloc(1, sizeof(*sig));
++ sig = dig->sigdata;
++ if (!sig)
++ return 1;
++ (void) mpnsethex(&sig->c, pgpMpiHex(p));
++ return 0;
++}
++
++int
++pgpSetPubMpiRSA(pgpDig dig, int num, const uint8_t *p)
++{
++ struct pgpDigPubRSA_s *pub;
++
++ if (!dig->keydata)
++ dig->keydata = xcalloc(1, sizeof(*pub));
++ pub = dig->keydata;
++ if (!pub)
++ return 1;
++ switch(num) {
++ case 0:
++ (void) mpbsethex(&pub->rsa_pk.n, pgpMpiHex(p));
++ return 0;
++ case 1:
++ (void) mpnsethex(&pub->rsa_pk.e, pgpMpiHex(p));
++ return 0;
++ default:
++ return 1;
++ }
++}
++
++static inline unsigned char nibble(char c)
++{
++ if (c >= '0' && c <= '9')
++ return (c - '0');
++ if (c >= 'A' && c <= 'F')
++ return (c - 'A') + 10;
++ if (c >= 'a' && c <= 'f')
++ return (c - 'a') + 10;
++ return 0;
++}
++
++int pgpVerifyRSA(pgpDig dig, uint8_t *hash, size_t hashlen)
++{
++ const char * prefix = NULL;
++ int res;
++ mpnumber rsahm;
++ struct pgpDigSigRSA_s *sig;
++ struct pgpDigPubRSA_s *pub;
++
++ sig = dig->sigdata;
++ pub = dig->keydata;
++ if (!sig || !pub)
++ return 1;
++
++ switch (dig->signature.hash_algo) {
++ case PGPHASHALGO_MD5:
++ prefix = "3020300c06082a864886f70d020505000410";
++ break;
++ case PGPHASHALGO_SHA1:
++ prefix = "3021300906052b0e03021a05000414";
++ break;
++ case PGPHASHALGO_MD2:
++ prefix = "3020300c06082a864886f70d020205000410";
++ break;
++ case PGPHASHALGO_SHA256:
++ prefix = "3031300d060960864801650304020105000420";
++ break;
++ case PGPHASHALGO_SHA384:
++ prefix = "3041300d060960864801650304020205000430";
++ break;
++ case PGPHASHALGO_SHA512:
++ prefix = "3051300d060960864801650304020305000440";
++ break;
++ /* fallthrough for unsupported / unknown types */
++ default:
++ return 1;
++ }
++
++ /* Generate RSA modulus parameter. */
++ { unsigned int nbits = MP_WORDS_TO_BITS(sig->c.size);
++ unsigned int nb = (nbits + 7) >> 3;
++ byte *buf, *bp;
++
++ if (nb < 3)
++ return 1;
++ buf = xmalloc(nb);
++ memset(buf, 0xff, nb);
++ buf[0] = 0x00;
++ buf[1] = 0x01;
++ bp = buf + nb - strlen(prefix)/2 - hashlen - 1;
++ if (bp < buf)
++ return 1;
++ *bp++ = 0;
++ for (; *prefix; prefix += 2)
++ *bp++ = (nibble(prefix[0]) << 4) | nibble(prefix[1]);
++ memcpy(bp, hash, hashlen);
++ mpnzero(&rsahm);
++ (void) mpnsetbin(&rsahm, buf, nb);
++ buf = _free(buf);
++ }
++#if HAVE_BEECRYPT_API_H
++ res = rsavrfy(&pub->rsa_pk.n, &pub->rsa_pk.e, &sig->c, &rsahm) == 1 ? 0 : 1;
++#else
++ res = rsavrfy(&pub->rsa_pk, &rsahm, &sig->c) == 1 ? 0 : 1;
++#endif
++ mpnfree(&rsahm);
++ return res;
++}
++
++
++/****************************** DSA **************************************/
++
++struct pgpDigSigDSA_s {
++ mpnumber r;
++ mpnumber s;
++};
++
++struct pgpDigPubDSA_s {
++ mpbarrett p;
++ mpbarrett q;
++ mpnumber g;
++ mpnumber y;
++};
++
++int
++pgpSetSigMpiDSA(pgpDig dig, int num, const uint8_t *p)
++{
++ struct pgpDigSigDSA_s *sig;
++
++ if (!dig->sigdata)
++ dig->sigdata = xcalloc(1, sizeof(*sig));
++ sig = dig->sigdata;
++ if (!sig)
++ return 1;
++ switch(num) {
++ case 0:
++ return pgpHexSet(160, &sig->r, p);
++ case 1:
++ return pgpHexSet(160, &sig->s, p);
++ default:
++ return 1;
++ }
++}
++
++int
++pgpSetPubMpiDSA(pgpDig dig, int num, const uint8_t *p)
++{
++ struct pgpDigPubDSA_s *pub;
++
++ if (!dig->keydata)
++ dig->keydata = xcalloc(1, sizeof(*pub));
++ pub = dig->keydata;
++ if (!pub)
++ return 1;
++ switch(num) {
++ case 0:
++ mpbsethex(&pub->p, pgpMpiHex(p));
++ return 0;
++ case 1:
++ mpbsethex(&pub->q, pgpMpiHex(p));
++ return 0;
++ case 2:
++ mpnsethex(&pub->g, pgpMpiHex(p));
++ return 0;
++ case 3:
++ mpnsethex(&pub->y, pgpMpiHex(p));
++ return 0;
++ default:
++ return 1;
++ }
++}
++
++int pgpVerifyDSA(pgpDig dig, uint8_t *hash, size_t hashlen)
++{
++ struct pgpDigSigDSA_s *sig;
++ struct pgpDigPubDSA_s *pub;
++ mpnumber hm;
++ int res;
++
++ sig = dig->sigdata;
++ pub = dig->keydata;
++ if (!sig || !pub)
++ return 1;
++ mpnzero(&hm);
++ mpnsetbin(&hm, hash, hashlen);
++ res = dsavrfy(&pub->p, &pub->q, &pub->g, &hm, &pub->y, &sig->r, &sig->s) == 1 ? 0 : 1;
++ mpnfree(&hm);
++ return res;
++}
++
++/**************************** digest ************************************/
++
++#ifdef SHA_DEBUG
++#define DPRINTF(_a) fprintf _a
++#else
++#define DPRINTF(_a)
++#endif
++
++/**
++ * MD5/SHA1 digest private data.
++ */
++struct DIGEST_CTX_s {
++ rpmDigestFlags flags; /*!< Bit(s) to control digest operation. */
++ int algo; /*!< Used hash algorithm */
++ uint32_t datalen; /*!< No. bytes in block of plaintext data. */
++ uint32_t paramlen; /*!< No. bytes of digest parameters. */
++ uint32_t digestlen; /*!< No. bytes of digest. */
++ void * param; /*!< Digest parameters. */
++ int (*Reset) (void * param)
++ /*@modifies param @*/; /*!< Digest initialize. */
++ int (*Update) (void * param, const byte * data, size_t size)
++ /*@modifies param @*/; /*!< Digest transform. */
++ int (*Digest) (void * param, /*@out@*/ byte * digest)
++ /*@modifies param, digest @*/; /*!< Digest finish. */
++};
++
++DIGEST_CTX
++rpmDigestDup(DIGEST_CTX octx)
++{
++ DIGEST_CTX nctx;
++ nctx = memcpy(xcalloc(1, sizeof(*nctx)), octx, sizeof(*nctx));
++ nctx->param = memcpy(xcalloc(1, nctx->paramlen), octx->param, nctx->paramlen);
++ return nctx;
++}
++
++size_t
++rpmDigestLength(int hashalgo)
++{
++ switch (hashalgo) {
++ case PGPHASHALGO_MD5:
++ return 16;
++ case PGPHASHALGO_SHA1:
++ return 20;
++#if HAVE_BEECRYPT_API_H
++ case PGPHASHALGO_SHA256:
++ return 32;
++ case PGPHASHALGO_SHA384:
++ return 48;
++ case PGPHASHALGO_SHA512:
++ return 64;
++#endif
++ default:
++ return 0;
++ }
++}
++
++DIGEST_CTX
++rpmDigestInit(int hashalgo, rpmDigestFlags flags)
++{
++ DIGEST_CTX ctx = xcalloc(1, sizeof(*ctx));
++ int xx;
++
++ ctx->flags = flags;
++ ctx->algo = hashalgo;
++
++ switch (hashalgo) {
++ case PGPHASHALGO_MD5:
++ ctx->digestlen = 16;
++ ctx->datalen = 64;
++ ctx->paramlen = sizeof(md5Param);
++ ctx->param = xcalloc(1, ctx->paramlen);
++ ctx->Reset = (void *) md5Reset;
++ ctx->Update = (void *) md5Update;
++ ctx->Digest = (void *) md5Digest;
++ break;
++ case PGPHASHALGO_SHA1:
++ ctx->digestlen = 20;
++ ctx->datalen = 64;
++ ctx->paramlen = sizeof(sha1Param);
++ ctx->param = xcalloc(1, ctx->paramlen);
++ ctx->Reset = (void *) sha1Reset;
++ ctx->Update = (void *) sha1Update;
++ ctx->Digest = (void *) sha1Digest;
++ break;
++#if HAVE_BEECRYPT_API_H
++ case PGPHASHALGO_SHA256:
++ ctx->digestlen = 32;
++ ctx->datalen = 64;
++ ctx->paramlen = sizeof(sha256Param);
++ ctx->param = xcalloc(1, ctx->paramlen);
++ ctx->Reset = (void *) sha256Reset;
++ ctx->Update = (void *) sha256Update;
++ ctx->Digest = (void *) sha256Digest;
++ break;
++ case PGPHASHALGO_SHA384:
++ ctx->digestlen = 48;
++ ctx->datalen = 128;
++ ctx->paramlen = sizeof(sha384Param);
++ ctx->param = xcalloc(1, ctx->paramlen);
++ ctx->Reset = (void *) sha384Reset;
++ ctx->Update = (void *) sha384Update;
++ ctx->Digest = (void *) sha384Digest;
++ break;
++ case PGPHASHALGO_SHA512:
++ ctx->digestlen = 64;
++ ctx->datalen = 128;
++ ctx->paramlen = sizeof(sha512Param);
++ ctx->param = xcalloc(1, ctx->paramlen);
++ ctx->Reset = (void *) sha512Reset;
++ ctx->Update = (void *) sha512Update;
++ ctx->Digest = (void *) sha512Digest;
++ break;
++#endif
++ case PGPHASHALGO_RIPEMD160:
++ case PGPHASHALGO_MD2:
++ case PGPHASHALGO_TIGER192:
++ case PGPHASHALGO_HAVAL_5_160:
++ default:
++ free(ctx);
++ return NULL;
++ }
++
++ xx = (*ctx->Reset) (ctx->param);
++
++DPRINTF((stderr, "*** Init(%x) ctx %p param %p\n", flags, ctx, ctx->param));
++ return ctx;
++}
++
++/* LCL: ctx->param may be modified, but ctx is abstract @*/
++int
++rpmDigestUpdate(DIGEST_CTX ctx, const void * data, size_t len)
++{
++ if (ctx == NULL)
++ return -1;
++
++DPRINTF((stderr, "*** Update(%p,%p,%d) param %p \"%s\"\n", ctx, data, len, ctx->param, ((char *)data)));
++ return (*ctx->Update) (ctx->param, data, len);
++}
++
++int
++rpmDigestFinal(DIGEST_CTX ctx, void ** datap, size_t *lenp, int asAscii)
++{
++ byte * digest;
++ char * t;
++ int i;
++
++ if (ctx == NULL)
++ return -1;
++ digest = xmalloc(ctx->digestlen);
++
++DPRINTF((stderr, "*** Final(%p,%p,%p,%d) param %p digest %p\n", ctx, datap, lenp, asAscii, ctx->param, digest));
++ /* FIX: check rc */
++ (void) (*ctx->Digest) (ctx->param, digest);
++
++ /* Return final digest. */
++ if (!asAscii) {
++ if (lenp) *lenp = ctx->digestlen;
++ if (datap) {
++ *datap = digest;
++ digest = NULL;
++ }
++ } else {
++ if (lenp) *lenp = (2*ctx->digestlen) + 1;
++ if (datap) {
++ const byte * s = (const byte *) digest;
++ static const char hex[] = "0123456789abcdef";
++
++ *datap = t = xmalloc((2*ctx->digestlen) + 1);
++ for (i = 0 ; i < ctx->digestlen; i++) {
++ *t++ = hex[ (unsigned)((*s >> 4) & 0x0f) ];
++ *t++ = hex[ (unsigned)((*s++ ) & 0x0f) ];
++ }
++ *t = '\0';
++ }
++ }
++ if (digest) {
++ memset(digest, 0, ctx->digestlen); /* In case it's sensitive */
++ free(digest);
++ }
++ memset(ctx->param, 0, ctx->paramlen); /* In case it's sensitive */
++ free(ctx->param);
++ memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
++ free(ctx);
++ return 0;
++}
+--- ./rpmio/digest_nss.c.orig 2011-07-18 16:34:29.000000000 +0000
++++ ./rpmio/digest_nss.c 2011-07-18 16:34:29.000000000 +0000
+@@ -0,0 +1,500 @@
++#include <nss.h>
++#include <sechash.h>
++#include <keyhi.h>
++#include <cryptohi.h>
++
++#include "system.h"
++
++#include <rpm/rpmpgp.h>
++#include "rpmio/rpmio_internal.h"
++#include "rpmio/digest.h"
++
++#include "debug.h"
++
++/* interface to nss crypto framework */
++
++/**************************** init ************************************/
++
++static int _crypto_initialized = 0;
++static int _new_process = 1;
++
++/*
++ * Only flag for re-initialization here, in the common case the child
++ * exec()'s something else shutting down NSS here would be waste of time.
++ */
++static void at_forkchild(void) {
++ _new_process = 1;
++}
++
++int rpmInitCrypto(void) {
++ int rc = 0;
++
++ /* Lazy NSS shutdown for re-initialization after fork() */
++ if (_new_process && _crypto_initialized) {
++ rpmFreeCrypto();
++ }
++
++ /* Initialize NSS if not already done */
++ if (!_crypto_initialized) {
++ if (NSS_NoDB_Init(NULL) != SECSuccess) {
++ rc = -1;
++ } else {
++ _crypto_initialized = 1;
++ }
++ }
++
++ /* Register one post-fork handler per process */
++ if (_new_process) {
++ if (pthread_atfork(NULL, NULL, at_forkchild) != 0) {
++ rpmlog(RPMLOG_WARNING, _("Failed to register fork handler: %m\n"));
++ }
++ _new_process = 0;
++ }
++ return rc;
++}
++
++int rpmInitCrypto(void) {
++ int rc = 0;
++
++ if (!_crypto_initialized) {
++ if (NSS_NoDB_Init(NULL) != SECSuccess) {
++ rc = -1;
++ } else {
++ _crypto_initialized = 1;
++ }
++ }
++ return rc;
++}
++
++int rpmFreeCrypto(void)
++{
++ int rc = 0;
++ if (_crypto_initialized) {
++ rc = (NSS_Shutdown() != SECSuccess);
++ _crypto_initialized = 0;
++ }
++ return rc;
++}
++
++/**************************** helpers ************************************/
++
++static SECKEYPublicKey *pgpNewPublicKey(KeyType type)
++{
++ PRArenaPool *arena;
++ SECKEYPublicKey *key;
++
++ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
++ if (arena == NULL)
++ return NULL;
++
++ key = PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
++
++ if (key == NULL) {
++ PORT_FreeArena(arena, PR_FALSE);
++ return NULL;
++ }
++
++ key->keyType = type;
++ key->pkcs11ID = CK_INVALID_HANDLE;
++ key->pkcs11Slot = NULL;
++ key->arena = arena;
++ return key;
++}
++
++static SECItem *pgpMpiItem(PRArenaPool *arena, SECItem *item, const uint8_t *p)
++{
++ size_t nbytes = pgpMpiLen(p)-2;
++
++ if (item == NULL) {
++ if ((item=SECITEM_AllocItem(arena, item, nbytes)) == NULL)
++ return item;
++ } else {
++ if (arena != NULL)
++ item->data = PORT_ArenaGrow(arena, item->data, item->len, nbytes);
++ else
++ item->data = PORT_Realloc(item->data, nbytes);
++
++ if (item->data == NULL) {
++ if (arena == NULL)
++ SECITEM_FreeItem(item, PR_TRUE);
++ return NULL;
++ }
++ }
++
++ memcpy(item->data, p+2, nbytes);
++ item->len = nbytes;
++ return item;
++}
++
++static int pgpMpiSet(unsigned int lbits,
++ void *dest, const uint8_t * p, const uint8_t * pend)
++{
++ unsigned int mbits = pgpMpiBits(p);
++ unsigned int nbits;
++ size_t nbytes;
++ char *t = dest;
++ unsigned int ix;
++
++ if ((p + ((mbits+7) >> 3)) > pend)
++ return 1;
++
++ if (mbits > lbits)
++ return 1;
++
++ nbits = (lbits > mbits ? lbits : mbits);
++ nbytes = ((nbits + 7) >> 3);
++ ix = (nbits - mbits) >> 3;
++
++ if (ix > 0) memset(t, '\0', ix);
++ memcpy(t+ix, p+2, nbytes-ix);
++
++ return 0;
++}
++
++void pgpCleanRSADSA(pgpDig dig)
++{
++ if (!dig)
++ return;
++ if (dig->keydata) {
++ SECKEY_DestroyPublicKey(dig->keydata);
++ dig->keydata = NULL;
++ }
++ if (dig->sigdata) {
++ SECITEM_ZfreeItem(dig->sigdata, PR_TRUE);
++ dig->sigdata = NULL;
++ }
++}
++
++/****************************** RSA **************************************/
++
++int
++pgpSetSigMpiRSA(struct pgpDig_s *dig, int num, const uint8_t *p, const uint8_t *pend)
++{
++ SECItem *sig;
++
++ if (num != 0)
++ return 1;
++ sig = dig->rsasigdata;
++ sig = pgpMpiItem(NULL, sig, p);
++ dig->rsasigdata = sig;
++ if (sig == NULL)
++ return 1;
++ return 0;
++}
++
++int
++pgpSetPubMpiRSA(struct pgpDig_s *dig, int num, const uint8_t *p, const uint8_t *pend)
++{
++ SECKEYPublicKey *pub;
++
++ if (!dig->keydata)
++ dig->keydata = pgpNewPublicKey(rsaKey);
++ pub = dig->keydata;
++ if (!pub)
++ return 1;
++ switch(num) {
++ case 0:
++ pgpMpiItem(pub->arena, &pub->u.rsa.modulus, p);
++ return 0;
++ case 1:
++ pgpMpiItem(pub->arena, &pub->u.rsa.publicExponent, p);
++ return 0;
++ default:
++ return 1;
++ }
++}
++
++int pgpVerifyRSA(pgpDig dig, uint8_t *hash, size_t hashlen)
++{
++ SECOidTag sigalg;
++ SECItem digest;
++ SECKEYPublicKey *pub;
++ SECItem *sig;
++ SECItem *newsig = NULL;
++ size_t siglen;
++ int res;
++
++ switch (dig->hash_algo) {
++ case PGPHASHALGO_MD5:
++ sigalg = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
++ break;
++ case PGPHASHALGO_SHA1:
++ sigalg = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
++ break;
++ case PGPHASHALGO_MD2:
++ sigalg = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
++ break;
++ case PGPHASHALGO_SHA256:
++ sigalg = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
++ break;
++ case PGPHASHALGO_SHA384:
++ sigalg = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
++ break;
++ case PGPHASHALGO_SHA512:
++ sigalg = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
++ break;
++ /* fallthrough for unsupported / unknown types */
++ default:
++ sigalg = SEC_OID_UNKNOWN;
++ break;
++ }
++ digest.type = siBuffer;
++ digest.data = hash;
++ digest.len = hashlen;
++
++ pub = dig->keydata;
++ sig = dig->sigdata;
++ siglen = SECKEY_SignatureLen(dig->keydata);
++
++ /* Zero-pad signature data up to expected size if necessary */
++ if (siglen > sig->len) {
++ size_t pad = siglen - sig->len;
++ if ((newsig = SECITEM_AllocItem(NULL, NULL, siglen)) == NULL) {
++ return 1;
++ }
++ memset(newsig->data, 0, pad);
++ memcpy(newsig->data+pad, sig->data, sig->len);
++ sig = newsig;
++ }
++
++ if (VFY_VerifyDigest(&digest, pub, sig, sigalg, NULL) == SECSuccess)
++ res = 0;
++ else
++ res = 1;
++
++ if (newsig) {
++ SECITEM_ZfreeItem(newsig, 1);
++ }
++ return res;
++}
++
++
++/****************************** DSA **************************************/
++
++int
++pgpSetSigMpiDSA(struct pgpDig_s *dig, int num, const uint8_t *p, const uint8_t *pend)
++{
++ SECItem *sig, *new;
++
++ switch(num) {
++ case 0:
++ sig = SECITEM_AllocItem(NULL, NULL, 2*DSA_SUBPRIME_LEN);
++ dig->sigdata = sig;
++ memset(sig->data, 0, 2*DSA_SUBPRIME_LEN);
++ pgpMpiSet(DSA_SUBPRIME_LEN*8, sig->data, p, pend);
++ return 0;
++ case 1:
++ sig = dig->sigdata;
++ if (!sig)
++ return 1;
++ pgpMpiSet(DSA_SUBPRIME_LEN*8, sig->data + DSA_SUBPRIME_LEN, p, pend);
++ new = SECITEM_AllocItem(NULL, NULL, 0);
++ if (!new)
++ return 1;
++ if (DSAU_EncodeDerSig(new, sig) != SECSuccess)
++ return 1;
++ SECITEM_FreeItem(sig, PR_TRUE);
++ dig->sigdata = new;
++ return 0;
++ default:
++ return 1;
++ }
++}
++
++int
++pgpSetPubMpiDSA(struct pgpDig_s *dig, int num, const uint8_t *p, const uint8_t *pend)
++{
++ SECKEYPublicKey *pub;
++
++ if (!dig->keydata)
++ dig->keydata = pgpNewPublicKey(dsaKey);
++ pub = dig->keydata;
++ if (!pub)
++ return 1;
++ switch(num) {
++ case 0:
++ pgpMpiItem(pub->arena, &pub->u.dsa.params.prime, p);
++ return 0;
++ case 1:
++ pgpMpiItem(pub->arena, &pub->u.dsa.params.subPrime, p);
++ return 0;
++ case 2:
++ pgpMpiItem(pub->arena, &pub->u.dsa.params.base, p);
++ return 0;
++ case 3:
++ pgpMpiItem(pub->arena, &pub->u.dsa.publicValue, p);
++ return 0;
++ default:
++ return 1;
++ }
++}
++
++int pgpVerifyDSA(pgpDig dig, uint8_t *hash, size_t hashlen)
++{
++ SECItem digest;
++ SECKEYPublicKey *pub;
++ SECItem *sig;
++
++ sig = dig->sigdata;
++ pub = dig->keydata;
++ digest.type = siBuffer;
++ digest.data = hash;
++ digest.len = hashlen;
++ if (VFY_VerifyDigest(&digest, pub, sig, SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST, NULL) == SECSuccess)
++ return 0;
++ else
++ return 1;
++}
++
++
++/**************************** digest ************************************/
++
++
++#ifdef SHA_DEBUG
++#define DPRINTF(_a) fprintf _a
++#else
++#define DPRINTF(_a)
++#endif
++
++
++/**
++ * MD5/SHA1 digest private data.
++ */
++struct DIGEST_CTX_s {
++ rpmDigestFlags flags; /*!< Bit(s) to control digest operation. */
++ HASHContext *hashctx; /*!< Internal NSS hash context. */
++ int algo; /*!< Used hash algorithm */
++};
++
++DIGEST_CTX
++rpmDigestDup(DIGEST_CTX octx)
++{
++ DIGEST_CTX nctx;
++ nctx = memcpy(xcalloc(1, sizeof(*nctx)), octx, sizeof(*nctx));
++ nctx->hashctx = HASH_Clone(octx->hashctx);
++ if (nctx->hashctx == NULL) {
++ fprintf(stderr, "HASH_Clone failed\n");
++ exit(EXIT_FAILURE); /* FIX: callers do not bother checking error return */
++ }
++ return nctx;
++}
++
++RPM_GNUC_PURE
++static HASH_HashType getHashType(int hashalgo)
++{
++ switch (hashalgo) {
++ case PGPHASHALGO_MD5:
++ return HASH_AlgMD5;
++ break;
++ case PGPHASHALGO_MD2:
++ return HASH_AlgMD2;
++ break;
++ case PGPHASHALGO_SHA1:
++ return HASH_AlgSHA1;
++ break;
++ case PGPHASHALGO_SHA256:
++ return HASH_AlgSHA256;
++ break;
++ case PGPHASHALGO_SHA384:
++ return HASH_AlgSHA384;
++ break;
++ case PGPHASHALGO_SHA512:
++ return HASH_AlgSHA512;
++ break;
++ case PGPHASHALGO_RIPEMD160:
++ case PGPHASHALGO_TIGER192:
++ case PGPHASHALGO_HAVAL_5_160:
++ default:
++ return HASH_AlgNULL;
++ break;
++ }
++}
++
++size_t
++rpmDigestLength(int hashalgo)
++{
++ return HASH_ResultLen(getHashType(hashalgo));
++}
++
++DIGEST_CTX
++rpmDigestInit(int hashalgo, rpmDigestFlags flags)
++{
++ HASH_HashType type;
++ HASHContext *hashctx = NULL;
++ DIGEST_CTX ctx = NULL;
++
++ if (type == HASH_AlgNULL || rpmInitCrypto() < 0)
++ return NULL;
++
++ if ((hashctx = HASH_Create(type)) == NULL)
++ return NULL;
++ ctx = xcalloc(1, sizeof(*ctx));
++ ctx->flags = flags;
++ ctx->algo = hashalgo;
++ ctx->hashctx = hashctx;
++ HASH_Begin(ctx->hashctx);
++
++DPRINTF((stderr, "*** Init(%x) ctx %p hashctx %p\n", flags, ctx, ctx->hashctx));
++ return ctx;
++}
++
++int
++rpmDigestUpdate(DIGEST_CTX ctx, const void * data, size_t len)
++{
++ size_t partlen;
++ const unsigned char *ptr = data;
++
++ if (ctx == NULL)
++ return -1;
++
++DPRINTF((stderr, "*** Update(%p,%p,%zd) hashctx %p \"%s\"\n", ctx, data, len, ctx->hashctx, ((char *)data)));
++ partlen = ~(unsigned int)0xFF;
++ while (len > 0) {
++ if (len < partlen) {
++ partlen = len;
++ }
++ HASH_Update(ctx->hashctx, ptr, partlen);
++ ptr += partlen;
++ len -= partlen;
++ }
++ return 0;
++}
++
++int
++rpmDigestFinal(DIGEST_CTX ctx, void ** datap, size_t *lenp, int asAscii)
++{
++ unsigned char * digest;
++ unsigned int digestlen;
++
++ if (ctx == NULL)
++ return -1;
++ digestlen = HASH_ResultLenContext(ctx->hashctx);
++ digest = xmalloc(digestlen);
++
++DPRINTF((stderr, "*** Final(%p,%p,%p,%zd) hashctx %p digest %p\n", ctx, datap, lenp, asAscii, ctx->hashctx, digest));
++/* FIX: check rc */
++ HASH_End(ctx->hashctx, digest, (unsigned int *) &digestlen, digestlen);
++
++ /* Return final digest. */
++ if (!asAscii) {
++ if (lenp) *lenp = digestlen;
++ if (datap) {
++ *datap = digest;
++ digest = NULL;
++ }
++ } else {
++ if (lenp) *lenp = (2*digestlen) + 1;
++ if (datap) {
++ const uint8_t * s = (const uint8_t *) digest;
++ *datap = pgpHexStr(s, digestlen);
++ }
++ }
++ if (digest) {
++ memset(digest, 0, digestlen); /* In case it's sensitive */
++ free(digest);
++ }
++ HASH_Destroy(ctx->hashctx);
++ memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
++ free(ctx);
++ return 0;
++}
+--- ./rpmio/rpmpgp.c.orig 2011-07-15 09:32:41.000000000 +0000
++++ ./rpmio/rpmpgp.c 2011-07-18 16:42:25.000000000 +0000
+@@ -20,9 +20,6 @@ static int _debug = 0;
+
+ static int _print = 0;
+
+-static int _crypto_initialized = 0;
+-static int _new_process = 1;
+-
+ typedef const struct pgpValTbl_s {
+ int val;
+ char const * const str;
+@@ -315,89 +312,6 @@ int pgpValTok(pgpValTbl vs, const char *
+ } while ((++vs)->val != -1);
+ return vs->val;
+ }
+-/**
+- * @return 0 on success
+- */
+-static int pgpMpiSet(const char * pre, unsigned int lbits,
+- uint8_t *dest, const uint8_t * p, const uint8_t * pend)
+-{
+- unsigned int mbits = pgpMpiBits(p);
+- unsigned int nbits;
+- size_t nbytes;
+- uint8_t *t = dest;
+- unsigned int ix;
+-
+- if ((p + ((mbits+7) >> 3)) > pend)
+- return 1;
+-
+- if (mbits > lbits)
+- return 1;
+-
+- nbits = (lbits > mbits ? lbits : mbits);
+- nbytes = ((nbits + 7) >> 3);
+- ix = (nbits - mbits) >> 3;
+-
+-if (_debug)
+-fprintf(stderr, "*** mbits %u nbits %u nbytes %zu ix %u\n", mbits, nbits, nbytes, ix);
+- if (ix > 0) memset(t, '\0', ix);
+- memcpy(t+ix, p+2, nbytes-ix);
+-if (_debug)
+-fprintf(stderr, "*** %s %s\n", pre, pgpHexStr(dest, nbytes));
+-
+- return 0;
+-}
+-
+-/**
+- * @return NULL on error
+- */
+-static SECItem *pgpMpiItem(PRArenaPool *arena, SECItem *item, const uint8_t *p)
+-{
+- size_t nbytes = pgpMpiLen(p)-2;
+-
+- if (item == NULL) {
+- if ((item=SECITEM_AllocItem(arena, item, nbytes)) == NULL)
+- return item;
+- } else {
+- if (arena != NULL)
+- item->data = PORT_ArenaGrow(arena, item->data, item->len, nbytes);
+- else
+- item->data = PORT_Realloc(item->data, nbytes);
+-
+- if (item->data == NULL) {
+- if (arena == NULL)
+- SECITEM_FreeItem(item, PR_TRUE);
+- return NULL;
+- }
+- }
+-
+- memcpy(item->data, p+2, nbytes);
+- item->len = nbytes;
+- return item;
+-}
+-/*@=boundswrite@*/
+-
+-static SECKEYPublicKey *pgpNewPublicKey(KeyType type)
+-{
+- PRArenaPool *arena;
+- SECKEYPublicKey *key;
+-
+- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+- if (arena == NULL)
+- return NULL;
+-
+- key = PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
+-
+- if (key == NULL) {
+- PORT_FreeArena(arena, PR_FALSE);
+- return NULL;
+- }
+-
+- key->keyType = type;
+- key->pkcs11ID = CK_INVALID_HANDLE;
+- key->pkcs11Slot = NULL;
+- key->arena = arena;
+- return key;
+-}
+
+ /** \ingroup rpmpgp
+ * Is buffer at beginning of an OpenPGP packet?
+@@ -593,29 +507,16 @@ static int pgpPrtSigParams(pgpTag tag, u
+ {
+ const uint8_t * pend = h + hlen;
+ size_t i;
+- SECItem dsaraw;
+- unsigned char dsabuf[2*DSA_SUBPRIME_LEN];
+ char *mpi;
+
+- dsaraw.type = 0;
+- dsaraw.data = dsabuf;
+- dsaraw.len = sizeof(dsabuf);
+-
+ for (i = 0; p < pend; i++, p += pgpMpiLen(p)) {
+ if (pubkey_algo == PGPPUBKEYALGO_RSA) {
+ if (i >= 1) break;
+ if (_dig &&
+ (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT))
+ {
+- switch (i) {
+- case 0: /* m**d */
+- _dig->sigdata = pgpMpiItem(NULL, _dig->sigdata, p);
+- if (_dig->sigdata == NULL)
+- return 1;
+- break;
+- default:
+- break;
+- }
++ if (pgpSetSigMpiRSA(_dig, i, p))
++ return 1;
+ }
+ pgpPrtStr("", pgpSigRSA[i]);
+ } else if (pubkey_algo == PGPPUBKEYALGO_DSA) {
+@@ -623,30 +524,8 @@ static int pgpPrtSigParams(pgpTag tag, u
+ if (_dig &&
+ (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT))
+ {
+- int xx;
+- xx = 0;
+- switch (i) {
+- case 0:
+- memset(dsaraw.data, '\0', 2*DSA_SUBPRIME_LEN);
+- /* r */
+- xx = pgpMpiSet(pgpSigDSA[i], DSA_SUBPRIME_LEN*8, dsaraw.data, p, pend);
+- break;
+- case 1: /* s */
+- xx = pgpMpiSet(pgpSigDSA[i], DSA_SUBPRIME_LEN*8, dsaraw.data + DSA_SUBPRIME_LEN, p, pend);
+- if (_dig->sigdata != NULL)
+- SECITEM_FreeItem(_dig->sigdata, PR_FALSE);
+- else if ((_dig->sigdata=SECITEM_AllocItem(NULL, NULL, 0)) == NULL) {
+- xx = 1;
+- break;
+- }
+- if (DSAU_EncodeDerSig(_dig->sigdata, &dsaraw) != SECSuccess)
+- xx = 1;
+- break;
+- default:
+- xx = 1;
+- break;
+- }
+- if (xx) return xx;
++ if (pgpSetSigMpiDSA(_dig, i, p))
++ return 1;
+ }
+ pgpPrtStr("", pgpSigDSA[i]);
+ } else {
+@@ -842,49 +721,11 @@ static const uint8_t * pgpPrtPubkeyParam
+ char * mpi;
+ if (pubkey_algo == PGPPUBKEYALGO_RSA) {
+ if (i >= 2) break;
+- if (_dig) {
+- if (_dig->keydata == NULL) {
+- _dig->keydata = pgpNewPublicKey(rsaKey);
+- if (_dig->keydata == NULL)
+- return NULL;
+- }
+- switch (i) {
+- case 0: /* n */
+- pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.rsa.modulus, p);
+- break;
+- case 1: /* e */
+- pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.rsa.publicExponent, p);
+- break;
+- default:
+- break;
+- }
+- }
++ pgpSetPubMpiRSA(_dig, i, p);
+ pgpPrtStr("", pgpPublicRSA[i]);
+ } else if (pubkey_algo == PGPPUBKEYALGO_DSA) {
+ if (i >= 4) break;
+- if (_dig) {
+- if (_dig->keydata == NULL) {
+- _dig->keydata = pgpNewPublicKey(dsaKey);
+- if (_dig->keydata == NULL)
+- return NULL;
+- }
+- switch (i) {
+- case 0: /* p */
+- pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.dsa.params.prime, p);
+- break;
+- case 1: /* q */
+- pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.dsa.params.subPrime, p);
+- break;
+- case 2: /* g */
+- pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.dsa.params.base, p);
+- break;
+- case 3: /* y */
+- pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.dsa.publicValue, p);
+- break;
+- default:
+- break;
+- }
+- }
++ pgpSetPubMpiDSA(_dig, i, p);
+ pgpPrtStr("", pgpPublicDSA[i]);
+ } else if (pubkey_algo == PGPPUBKEYALGO_ELGAMAL_ENCRYPT) {
+ if (i >= 3) break;
+@@ -1269,15 +1110,7 @@ void pgpCleanDig(pgpDig dig)
+ memset(&dig->signature, 0, sizeof(dig->signature));
+ memset(&dig->pubkey, 0, sizeof(dig->pubkey));
+
+- if (dig->keydata != NULL) {
+- SECKEY_DestroyPublicKey(dig->keydata);
+- dig->keydata = NULL;
+- }
+-
+- if (dig->sigdata != NULL) {
+- SECITEM_ZfreeItem(dig->sigdata, PR_TRUE);
+- dig->sigdata = NULL;
+- }
++ pgpCleanRSADSA(dig);
+ }
+ return;
+ }
+@@ -1319,39 +1152,6 @@ int pgpPrtPkts(const uint8_t * pkts, siz
+ return 0;
+ }
+
+-static SECOidTag getSigAlg(pgpDigParams sigp)
+-{
+- SECOidTag sigalg = SEC_OID_UNKNOWN;
+- if (sigp->pubkey_algo == PGPPUBKEYALGO_DSA) {
+- /* assume SHA1 for now, NSS doesn't have SECOID's for other types */
+- sigalg = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
+- } else if (sigp->pubkey_algo == PGPPUBKEYALGO_RSA) {
+- switch (sigp->hash_algo) {
+- case PGPHASHALGO_MD5:
+- sigalg = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
+- break;
+- case PGPHASHALGO_MD2:
+- sigalg = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
+- break;
+- case PGPHASHALGO_SHA1:
+- sigalg = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
+- break;
+- case PGPHASHALGO_SHA256:
+- sigalg = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
+- break;
+- case PGPHASHALGO_SHA384:
+- sigalg = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
+- break;
+- case PGPHASHALGO_SHA512:
+- sigalg = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
+- break;
+- default:
+- break;
+- }
+- }
+- return sigalg;
+-}
+-
+ char *pgpIdentItem(pgpDigParams digp)
+ {
+ char *id = NULL;
+@@ -1409,30 +1209,12 @@ rpmRC pgpVerifySig(pgpDig dig, DIGEST_CT
+ if (dig->keydata == NULL) {
+ res = RPMRC_NOKEY;
+ } else {
+- SECItem digest = { .type = siBuffer, .data = hash, .len = hashlen };
+- SECItem *sig = dig->sigdata;
+-
+- /* Zero-pad RSA signature to expected size if necessary */
+ if (sigp->pubkey_algo == PGPPUBKEYALGO_RSA) {
+- size_t siglen = SECKEY_SignatureLen(dig->keydata);
+- if (siglen > sig->len) {
+- size_t pad = siglen - sig->len;
+- if ((sig = SECITEM_AllocItem(NULL, NULL, siglen)) == NULL) {
+- goto exit;
+- }
+- memset(sig->data, 0, pad);
+- memcpy(sig->data+pad, dig->sigdata->data, dig->sigdata->len);
+- }
+- }
+-
+- /* XXX VFY_VerifyDigest() is deprecated in NSS 3.12 */
+- if (VFY_VerifyDigest(&digest, dig->keydata, sig,
+- getSigAlg(sigp), NULL) == SECSuccess) {
+- res = RPMRC_OK;
+- }
+-
+- if (sig != dig->sigdata) {
+- SECITEM_ZfreeItem(sig, 1);
++ if (!pgpVerifyRSA(dig, hash, hashlen))
++ res = RPMRC_OK;
++ } else if (sigp->pubkey_algo == PGPPUBKEYALGO_DSA) {
++ if (!pgpVerifyDSA(dig, hash, hashlen))
++ res = RPMRC_OK;
+ }
+ }
+
+@@ -1620,50 +1402,3 @@ char * pgpArmorWrap(int atype, const uns
+ return val;
+ }
+
+-/*
+- * Only flag for re-initialization here, in the common case the child
+- * exec()'s something else shutting down NSS here would be waste of time.
+- */
+-static void at_forkchild(void)
+-{
+- _new_process = 1;
+-}
+-
+-int rpmInitCrypto(void) {
+- int rc = 0;
+-
+- /* Lazy NSS shutdown for re-initialization after fork() */
+- if (_new_process && _crypto_initialized) {
+- rpmFreeCrypto();
+- }
+-
+- /* Initialize NSS if not already done */
+- if (!_crypto_initialized) {
+- if (NSS_NoDB_Init(NULL) != SECSuccess) {
+- rc = -1;
+- } else {
+- _crypto_initialized = 1;
+- }
+- }
+-
+- /* Register one post-fork handler per process */
+- if (_new_process) {
+- if (pthread_atfork(NULL, NULL, at_forkchild) != 0) {
+- rpmlog(RPMLOG_WARNING, _("Failed to register fork handler: %m\n"));
+- }
+- _new_process = 0;
+- }
+- return rc;
+-}
+-
+-int rpmFreeCrypto(void)
+-{
+- int rc = 0;
+- if (_crypto_initialized) {
+- rc = (NSS_Shutdown() != SECSuccess);
+- _crypto_initialized = 0;
+- }
+- return rc;
+-}
+-
+-
diff --git a/packaging/rpm-gst-provides.patch b/packaging/rpm-gst-provides.patch
new file mode 100644
index 0000000..afbc2a6
--- /dev/null
+++ b/packaging/rpm-gst-provides.patch
@@ -0,0 +1,14 @@
+Index: ./autodeps/linux.prov
+===================================================================
+--- ./autodeps/linux.prov
++++ ./autodeps/linux.prov
+@@ -102,4 +102,9 @@ fi
+ [ -x /usr/lib/rpm/find-provides.ksyms ] &&
+ printf "%s\n" "${filelist[@]}" | /usr/lib/rpm/find-provides.ksyms "$@"
+
++#
++# --- GStreamer provides, codecs
++[ -x /usr/lib/rpm/gstreamer-provides ] &&
++ printf "%s\n" "${filelist[@]}" | /usr/lib/rpm/gstreamer-provides | sort -u
++
+ exit 0
diff --git a/packaging/rpm-macros.patch b/packaging/rpm-macros.patch
new file mode 100644
index 0000000..8f3e1a2
--- /dev/null
+++ b/packaging/rpm-macros.patch
@@ -0,0 +1,57 @@
+Index: rpm-4.9.0/configure.ac
+===================================================================
+--- rpm-4.9.0.orig/configure.ac
++++ rpm-4.9.0/configure.ac
+@@ -831,6 +831,7 @@ unknown|pc|ibm|redhat|pld|mandrake|conec
+ test -f /etc/redhat-release && RPMCANONVENDOR=redhat
+ test -f /etc/SuSE-release && RPMCANONVENDOR=suse
+ test -f /etc/pld-release && RPMCANONVENDOR=pld
++ test -f /etc/tizen-release && RPMCANONVENDOR=tizen
+ test -f /etc/mandrake-release && RPMCANONVENDOR=mandrake
+ test -f /etc/conectiva-release && RPMCANONVENDOR=conectiva
+ test -f /etc/lvr-release && RPMCANONVENDOR=lvr
+Index: rpm-4.9.0/platform.in
+===================================================================
+--- rpm-4.9.0.orig/platform.in
++++ rpm-4.9.0/platform.in
+@@ -76,6 +76,26 @@
+ @redhat@#%defattr(-,root,root,-)\
+ @redhat@#%{nil}
+
++@tizen@#---------------------------------------------------------------------
++@tizen@# Expanded at end of %prep
++@tizen@#
++@tizen@%__id_u @__ID_U@
++@tizen@%__chown_Rhf @__CHOWN_RHF@
++@tizen@%__chgrp_Rhf @__CHGRP_RHF@
++@tizen@%_fixperms %{__chmod} -Rf @FIXPERMS@
++@tizen@%__os_install_post \
++@tizen@ %{_rpmconfigdir}/brp-compress \
++@tizen@ %{_rpmconfigdir}/brp-strip %{__strip} \
++@tizen@ %{_rpmconfigdir}/brp-strip-static-archive %{__strip} \
++@tizen@ %{_rpmconfigdir}/brp-strip-comment-note %{__strip} %{__objdump} \
++@tizen@ %{_rpmconfigdir}/tizen/find-docs.sh %{buildroot}\
++@tizen@%{nil}
++@tizen@#---------------------------------------------------------------------
++@tizen@# Always use %defattr(-,root,root) in %files (added in rpm-4.0.4)
++@tizen@#
++@tizen@#%files(n:f:) %%files%{?-f: -f %{-f*}}%{?-n: -n %{-n*}} %{?1}\
++@tizen@#%defattr(-,root,root,-)\
++@tizen@#%{nil}
+
+ @apple@#---------------------------------------------------------------------
+ @apple@# Apple Darwin vendor specific macros
+Index: rpm-4.9.0/installplatform
+===================================================================
+--- rpm-4.9.0.orig/installplatform
++++ rpm-4.9.0/installplatform
+@@ -126,6 +126,9 @@ for SUBST in $SUBSTS ; do
+ redhat)
+ VENDORSED='-e s,^@redhat@,,'
+ ;;
++ tizen)
++ VENDORSED='-e s,^@tizen@,,'
++ ;;
+ apple)
+ VENDORSED='-e s,^@apple@,,'
+ ;;
diff --git a/packaging/rpm-python.manifest b/packaging/rpm-python.manifest
new file mode 100644
index 0000000..017d22d
--- /dev/null
+++ b/packaging/rpm-python.manifest
@@ -0,0 +1,5 @@
+<manifest>
+ <request>
+ <domain name="_"/>
+ </request>
+</manifest>
diff --git a/packaging/rpm-python.spec b/packaging/rpm-python.spec
new file mode 100644
index 0000000..a55899a
--- /dev/null
+++ b/packaging/rpm-python.spec
@@ -0,0 +1,78 @@
+# build against xz?
+%bcond_without xz
+# build against python
+%bcond_without python
+# sqlite backend is pretty useless
+%bcond_with sqlite
+# just for giggles, option to build with internal Berkeley DB
+%bcond_with int_bdb
+
+%define rpmhome /usr/lib/rpm
+
+%define rpmver 4.9.1
+
+
+Summary: The RPM package management system
+Name: rpm-python
+Version: %{rpmver}
+Release: 1
+BuildRequires: python-devel
+%{expand:%(sed -n -e '/^Source1001:/d' -e '/^Source0:/,/^##PYTHON##/p' <%_sourcedir/rpm.spec)}
+Source100: rpm.spec
+Source1001: packaging/rpm-python.manifest
+Requires: popt >= 1.10.2.1
+Requires: curl
+Requires: rpm = %{version}
+BuildRequires: db4-devel
+
+
+# XXX generally assumed to be installed but make it explicit as rpm
+# is a bit special...
+BuildRequires: gawk
+BuildRequires: elfutils-devel >= 0.112
+BuildRequires: elfutils-libelf-devel
+BuildRequires: readline-devel zlib-devel
+BuildRequires: nss-devel
+# The popt version here just documents an older known-good version
+BuildRequires: popt-devel >= 1.10.2
+BuildRequires: libfile-devel
+BuildRequires: gettext-devel
+BuildRequires: ncurses-devel
+BuildRequires: bzip2-devel >= 0.9.0c-2
+BuildRequires: liblua-devel >= 5.1
+BuildRequires: libcap-devel
+BuildRequires: xz-devel >= 4.999.8
+BuildRequires: uthash-devel
+BuildRequires: libxml2-devel
+BuildRequires: libattr-devel
+BuildRequires: pkgconfig(libsmack)
+
+
+%description
+The RPM Package Manager (RPM) is a powerful command line driven
+package management system capable of installing, uninstalling,
+verifying, querying, and updating software packages. Each software
+package consists of an archive of files along with information about
+the package like its version, a description, etc.
+
+%prep
+%{expand:%(sed -n -e '/^%%prep/,/^%%install/p' <%_sourcedir/rpm.spec | sed -e '1d' -e '$d')}
+%install
+rm -rf $RPM_BUILD_ROOT
+
+make DESTDIR="$RPM_BUILD_ROOT" install
+find "%{buildroot}" -not -type d -and -not -path %{buildroot}%{_libdir}/python%{py_ver}/site-packages/rpm/\* -print0 | xargs -0 rm
+pushd $RPM_BUILD_ROOT/%py_sitedir/rpm
+rm -f _rpmmodule.a _rpmmodule.la
+python %py_libdir/py_compile.py *.py
+python -O %py_libdir/py_compile.py *.py
+popd
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%manifest rpm-python.manifest
+%defattr(-,root,root)
+%{_libdir}/python*
+
diff --git a/packaging/rpm-shorten-changelog.patch b/packaging/rpm-shorten-changelog.patch
new file mode 100644
index 0000000..b5f20b2
--- /dev/null
+++ b/packaging/rpm-shorten-changelog.patch
@@ -0,0 +1,92 @@
+Index: rpm-4.9.0/build/pack.c
+===================================================================
+--- rpm-4.9.0.orig/build/pack.c
++++ rpm-4.9.0/build/pack.c
+@@ -671,6 +671,63 @@ static rpmRC checkPackages(char *pkgchec
+ return RPMRC_OK;
+ }
+
++static void trimChangelog(Header h)
++{
++ static int oneshot;
++ static int cuttime, minnum, maxnum;
++ int * times;
++ char ** names = 0, ** texts = 0;
++ int i, keep, count = 0;
++
++ if (!oneshot) {
++ char *binarychangelogtrim = rpmExpand("%{?_binarychangelogtrim}", NULL);
++ oneshot = 1;
++ if (binarychangelogtrim && *binarychangelogtrim) {
++ maxnum = atoi(binarychangelogtrim);
++ binarychangelogtrim = strchr(binarychangelogtrim, ',');
++ if (binarychangelogtrim)
++ binarychangelogtrim++;
++ }
++ if (binarychangelogtrim && *binarychangelogtrim) {
++ cuttime = atoi(binarychangelogtrim);
++ binarychangelogtrim = strchr(binarychangelogtrim, ',');
++ if (binarychangelogtrim)
++ binarychangelogtrim++;
++ }
++ if (binarychangelogtrim && *binarychangelogtrim) {
++ minnum = atoi(binarychangelogtrim);
++ binarychangelogtrim = strchr(binarychangelogtrim, ',');
++ }
++ }
++ if (!cuttime && !minnum && !maxnum) {
++ return;
++ }
++ if (!headerGetEntry(h, RPMTAG_CHANGELOGTIME, NULL, (void **) &times, &count))
++ return;
++ if ((!cuttime || count <= minnum) && (!maxnum || count <= maxnum)) {
++ return;
++ }
++ keep = count;
++ if (maxnum && keep > maxnum)
++ keep = maxnum;
++ if (cuttime) {
++ for (i = 0; i < keep; i++) {
++ if (i >= minnum && times[i] < cuttime)
++ break;
++ }
++ keep = i;
++ }
++ if (keep >= count)
++ return;
++ headerGetEntry(h, RPMTAG_CHANGELOGNAME, NULL, (void **) &names, &count);
++ headerGetEntry(h, RPMTAG_CHANGELOGTEXT, NULL, (void **) &texts, &count);
++ headerModifyEntry(h, RPMTAG_CHANGELOGTIME, RPM_INT32_TYPE, times, keep);
++ headerModifyEntry(h, RPMTAG_CHANGELOGNAME, RPM_STRING_ARRAY_TYPE, names, keep);
++ headerModifyEntry(h, RPMTAG_CHANGELOGTEXT, RPM_STRING_ARRAY_TYPE, texts, keep);
++ free(names);
++ free(texts);
++}
++
+ rpmRC packageBinaries(rpmSpec spec, const char *cookie, int cheating)
+ {
+ struct cpioSourceArchive_s csabuf;
+@@ -680,6 +737,7 @@ rpmRC packageBinaries(rpmSpec spec, cons
+ Package pkg;
+ char *pkglist = NULL;
+
++ trimChangelog(spec->packages->header);
+ for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
+ char *fn;
+
+Index: rpm-4.9.0/build/parseChangelog.c
+===================================================================
+--- rpm-4.9.0.orig/build/parseChangelog.c
++++ rpm-4.9.0/build/parseChangelog.c
+@@ -168,6 +168,11 @@ static rpmRC addChangelog(Header h, ARGV
+ return RPMRC_FAIL;
+ }
+
++ /* workaround old suse oddity */
++ if (*s == '-' && s[1] == ' ') {
++ s += 2;
++ }
++
+ /* name */
+ name = s;
+ while (*s != '\0') s++;
diff --git a/packaging/rpm.changes b/packaging/rpm.changes
new file mode 100644
index 0000000..2ce3727
--- /dev/null
+++ b/packaging/rpm.changes
@@ -0,0 +1,117 @@
+* Fri Dec 14 2012 Elena Reshetova <elena.reshetova@intel.com> - 4.9.0
+- Fixing issues in security plugin found during the fuzzing
+ - Adding check for ac domain name
+ - Adding verification for xml parcer return code in msmProcessDefine and sub-functions
+
+* Wed Dec 5 2012 Elena Reshetova <elena.reshetova@intel.com> - 4.9.0
+- Making upgrade policy more restrictive: only packages from more trusted sources can overwrite the packages
+
+* Thu Nov 29 2012 Elena Reshetova <elena.reshetova@intel.com> - 4.9.0
+- Device security policy now includes * and ^ domains
+
+* Mon Nov 12 2012 Elena Reshetova <elena.reshetova@intel.com> - 4.9.0
+- Changes to the security plugin
+ - Minor fix for the sw source processing
+ - Add a check for the magic_t cookie initialization
+ - Adding a hook to label unowned directories
+ - Fix for the transmutable attribute setting
+
+* Tue Sep 11 2012 Elena Reshetova <elena.reshetova@intel.com> - 4.9.0
+- Changes to the security plugin
+ - Moving the place of the FSM_CLOSED hook in order to ignore the hardlinks
+
+* Thu Sep 6 2012 Elena Reshetova <elena.reshetova@intel.com> - 4.9.0
+- Changes to the security plugin
+ - Using libmagic instead of file utility to check file's content
+
+* Wed Sep 5 2012 Elena Reshetova <elena.reshetova@intel.com> - 4.9.0
+- Changes to the security plugin
+ - Removing the fopen check before setting xattr
+ - Changing fsetxattr to lsetxattr
+
+* Tue Sep 4 2012 Elena Reshetova <elena.reshetova@intel.com> - 4.9.0
+- Changes to the security plugin
+ - Adding an option to specify wildcards in file paths (bug TDIS-121)
+ - Adding a possibility to specify more fine-grained permits (bug TDIS-120)
+ - Minor cosmetic fixes
+
+* Tue Aug 21 2012 William Douglas <william.douglas@intel.com> submit/trunk/2012-08-08.064212@aa8ef92
+- Revert 88da3b2439b41193f3d964db7d4a7f0e8321c8f1
+
+* Wed Aug 08 2012 Elena Reshetova <elena.reshetova@intel.com> - 4.9.0
+- Changes to the security plugin
+ - Moving the setup of xattr to the FSM_CLOSED hook
+ - Adding a new ac domain "Isolated" to the policy
+ - Using "Isolated" domain in cases when default labels of the files can't be determined
+
+* Mon Aug 06 2012 William Douglas <william.douglas@intel.com> build/2012-07-30.142546@9c7636b
+[ William Douglas ]
+- Keep function symbols for backtraces.
+
+* Mon Aug 06 2012 Elena Reshetova <elena.reshetova@intel.com> - 4.9.0
+- Changes to the security plugin
+ - Fix the smack directory creation when subdir is present
+ - Add a check for access type lenght
+ - Small code rearrangments
+
+* Mon Jul 30 2012 Elena Reshetova <elena.reshetova@intel.com> - 4.9.0
+- Changes to the security plugin
+ - Cosmetic change to msmFreePointer function
+ - Adding more log on errors
+ - Removing the decription tags
+ - Verifying the allowed characters in label, domain and access type
+ - Not allowing sections in manifest to repeat
+ - Improving handling of hash lists
+
+* Fri Jul 24 2012 Elena Reshetova <elena.reshetova@intel.com> - 4.9.0
+- Fixing the handling of all_packages uthash list
+- Changing the free functions to use msmFreePointer in order to delete safely
+- Changing the request handling in order to allow only one domain name inside a request section
+- Changing the allowed length of the label or domain to be 255
+
+* Fri Jul 12 2012 Elena Reshetova <elena.reshetova@intel.com> - 4.9.0
+- Fixing the path handling in plugin during labelling phase
+- Fixing the sw source retrival in case verify hook isn't called
+
+* Fri Jul 10 2012 Elena Reshetova <elena.reshetova@intel.com> - 4.9.0
+- Fixing rpm-security-plugin bug PTSEC-22: dbus manifest is not generated correctly
+- Fixing rpm-security-plugin bug PTSEC-24: package upgrade removes the file from /etc/smack/accesses.d
+
+* Wed Jul 04 2012 Anas Nashif <anas.nashif@intel.com> 6bf3412
+- remove auto dependencies
+
+* Mon Jun 25 2012 Anas Nashif <anas.nashif@intel.com> ab35aed
+- update release
+- require bzip2-devel >= 1.0.5
+
+* Mon Jun 25 2012 Anas Nashif <anas.nashif@intel.com> 70cc161
+- require bzip2-devel >= 1.0.5
+
+* Thu Jun 21 2012 Anas Nashif <anas.nashif@intel.com> 6863478
+- fixed optflags and perl auto-dependencies
+
+* Thu Jun 21 2012 Anas Nashif <anas.nashif@intel.com> c290eab
+- disable perl auto requires
+- fixed optflags
+
+* Wed Jun 20 2012 Elena, Reshetova <elena.reshetova@intel.com> dd9dc00
+- fixing pre/posttrans scripts calls and plugin
+
+* Fri Jun 15 2012 Ryan Ware <ryan.r.ware@intel.com> bf466c3
+- Version 4.9.0, release to OBS
+
+* Tue Jun 12 2012 Elena, Reshetova <elena.reshetova@intel.com> 733aadb
+- Fixng rpm-security-plugin bugs (PTSEC-19, PTSEC-20, PTSEC-21)
+
+* Wed May 30 2012 Ryan Ware <ryan.r.ware@intel.com> 91057db
+- Add default Smack manifest for rpm.spec
+- Add default Smack manifest for rpm-python.spec
+
+* Tue May 29 2012 Elena, Reshetova <elena.reshetova@intel.com> 3257c01
+- adding fixes for exec label handling and fixing plugin dependencies
+
+* Mon May 21 2012 Kim Kibum <kb0929.kim@samsung.com> dec48cf
+- Upload Tizen:Base source
+[ Hyesook Choi ]
+- Initial empty repository
+
diff --git a/packaging/rpm.manifest b/packaging/rpm.manifest
new file mode 100644
index 0000000..017d22d
--- /dev/null
+++ b/packaging/rpm.manifest
@@ -0,0 +1,5 @@
+<manifest>
+ <request>
+ <domain name="_"/>
+ </request>
+</manifest>
diff --git a/packaging/rpm.spec b/packaging/rpm.spec
new file mode 100644
index 0000000..2380dd3
--- /dev/null
+++ b/packaging/rpm.spec
@@ -0,0 +1,378 @@
+# run internal testsuite?
+%bcond_without check
+
+
+Name: rpm
+Version: 4.9.1
+Release: 4
+Summary: The RPM package management system
+Url: http://www.rpm.org/
+Group: System/Base
+Source0: http://rpm.org/releases/rpm-4.9.x/rpm-%{version}.tar.bz2
+Source1: libsymlink.attr
+Source11: db-4.8.30.tar.gz
+Source20: macros
+Source21: find-docs.sh
+Source22: device-sec-policy
+Source1001: packaging/rpm.manifest
+
+Patch1: db.diff
+# quilt patches start here
+Patch3: rpm-4.5.90-pkgconfig-path.patch
+Patch4: rpm-4.5.90-gstreamer-provides.patch
+Patch5: rpm-4.8.0-tilde.patch
+Patch6: rpm-macros.patch
+Patch7: rpm-4.9.0-tizen-arm.patch
+Patch10: remove-translations.patch
+Patch11: rpm-shorten-changelog.patch
+Patch12: no_rep_autop.diff
+Patch13: finddebuginfo.diff
+Patch14: debugsource-package.diff
+Patch15: debugsubpkg.diff
+Patch24: autodeps.diff
+Patch49: mimetype.diff
+Patch52: firmware.diff
+Patch56: buildidprov.diff
+Patch64: pythondeps.diff
+Patch65: fontprovides.diff
+Patch66: rpm-gst-provides.patch
+Patch76: fileattrs.diff
+Patch80: optflags.patch
+Patch81: build_pack_4.9.1_fix.patch
+Patch82: lib_rpmdb_4.9.1_fix.patch
+Patch83: rpmbuild_4.9.1_fix.patch
+Patch84: rpmbuild_rpmfc_4.9.1_fix.patch
+Patch85: rpmio_base64_4.9.1_fix.patch
+Patch86: rpmlib_format_value_4.9.1_fix.patch
+Patch87: security_4.9.1.patch
+Patch90: disableperl.patch
+Patch100: eu-strip.patch
+
+# Partially GPL/LGPL dual-licensed and some bits with BSD
+# SourceLicense: (GPLv2+ and LGPLv2+ with exceptions) and BSD
+License: GPLv2+
+##PYTHON##
+
+Requires: curl
+
+BuildRequires: bzip2-devel >= 1.0.5
+BuildRequires: elfutils-devel >= 0.112
+BuildRequires: elfutils-libelf-devel
+BuildRequires: libfile-devel
+BuildRequires: gettext-tools
+BuildRequires: libcap-devel
+BuildRequires: liblua-devel >= 5.1
+BuildRequires: pkgconfig(ncurses)
+# The popt version here just documents an older known-good version
+BuildRequires: popt-devel >= 1.10.2
+BuildRequires: readline-devel
+BuildRequires: xz-devel >= 4.999.8
+BuildRequires: zlib-devel
+BuildRequires: nss-devel
+BuildRequires: uthash-devel
+BuildRequires: libxml2-devel
+BuildRequires: libattr-devel
+BuildRequires: pkgconfig(libsmack)
+
+
+%description
+The RPM Package Manager (RPM) is a powerful command line driven
+package management system capable of installing, uninstalling,
+verifying, querying, and updating software packages. Each software
+package consists of an archive of files along with information about
+the package like its version, a description, etc.
+
+%package libs
+License: GPLv2+ and LGPLv2+ with exceptions
+Summary: Libraries for manipulating RPM packages
+Group: Development/Libraries
+Requires: rpm = %{version}
+
+%description libs
+This package contains the RPM shared libraries.
+
+%package devel
+License: GPLv2+ and LGPLv2+ with exceptions
+Summary: Development files for manipulating RPM packages
+Group: Development/Libraries
+Requires: libfile-devel
+Requires: rpm = %{version}
+
+%description devel
+This package contains the RPM C library and header files. These
+development files will simplify the process of writing programs that
+manipulate RPM packages and databases. These files are intended to
+simplify the process of creating graphical package managers or any
+other tools that need an intimate knowledge of RPM packages in order
+to function.
+
+This package should be installed if you want to develop programs that
+will manipulate RPM packages and databases.
+
+%package build
+Summary: Scripts and executable programs used to build packages
+Group: Development/Tools
+Requires: binutils
+Requires: bzip2
+Requires: /bin/cpio
+Requires: diffutils
+Requires: elfutils >= 0.128
+Requires: file
+Requires: /bin/find
+Requires: /bin/awk
+Requires: /bin/grep
+Requires: /bin/gzip
+Requires: lzma
+Requires: patch >= 2.5
+Requires: pkgconfig
+Requires: rpm = %{version}
+Requires: /bin/sed
+Requires: unzip
+Requires: xz
+
+%description build
+The rpm-build package contains the scripts and executable programs
+that are used to build packages using the RPM Package Manager.
+
+
+%package security-plugin
+Summary: MSM security plugin for rpm
+Group: Development/Libraries
+Requires: rpm = %{version}-%{release}
+
+%description security-plugin
+This package contains the MSM security plugin for rpm that performs
+security-related functionality.
+
+%prep
+%setup -q -n rpm-%{version}
+tar xzf %{SOURCE11}
+ln -s db-4.8.30 db
+chmod -R u+w db/*
+rm -f rpmdb/db.h
+
+%patch1 -p0
+%patch3 -p1 -b .pkgconfig-path
+#%patch4 -p1 -b .gstreamer-prov
+%patch5 -p1 -b .tilde
+%patch6 -p1 -b .vendor
+%patch7 -p1 -b .arm
+%patch10 -p1
+%patch11 -p1
+%patch12 -p0
+%patch13 -p0
+%patch14 -p0
+#%patch15 -p0
+#%patch24 -p0
+#%patch49 -p0
+#%patch52 -p0
+#%patch56 -p0
+#%patch64 -p0
+#%patch65 -p0
+#%patch66 -p0
+#%patch76 -p0
+%patch80 -p1
+%patch81 -p1
+%patch82 -p1
+%patch83 -p1
+%patch84 -p1
+%patch85 -p1
+%patch86 -p1
+%patch87 -p1 -b .msm
+#%patch90 -p1
+%patch100 -p1
+
+
+rm -f m4/libtool.m4
+rm -f m4/lt*.m4
+
+%build
+cp %{SOURCE1001} .
+CPPFLAGS="$CPPFLAGS `pkg-config --cflags nss`"
+CFLAGS="%{optflags}"
+export CPPFLAGS CFLAGS LDFLAGS
+
+# Using configure macro has some unwanted side-effects on rpm platform
+# setup, use the old-fashioned way for now only defining minimal paths.
+
+libtoolize -f -c
+./autogen.sh \
+ --prefix=%{_prefix} \
+ --sysconfdir=%{_sysconfdir} \
+ --localstatedir=%{_localstatedir} \
+ --sharedstatedir=%{_localstatedir}/lib \
+ --libdir=%{_libdir} \
+%if %{with python}
+ --enable-python \
+%endif
+ --with-lua \
+ --with-cap \
+ --with-msm
+
+make %{?_smp_mflags}
+
+%install
+
+%make_install
+find %{buildroot} -regex ".*\\.la$" | xargs rm -f --
+
+mkdir -p %{buildroot}%{_sysconfdir}/rpm
+mkdir -p %{buildroot}%{_libdir}/rpm
+install -m 644 %{SOURCE1} %{buildroot}%{_libdir}/rpm/fileattrs/libsymlink.attr
+install -m 644 %{SOURCE22} ${RPM_BUILD_ROOT}%{_sysconfdir}/device-sec-policy
+mkdir -p %{buildroot}%{_localstatedir}/lib/rpm
+
+#install -m 755 scripts/firmware.prov %{buildroot}%{_prefix}/lib/rpm
+#install -m 755 scripts/debuginfo.prov %{buildroot}%{_prefix}/lib/rpm
+
+for dbi in \
+ Basenames Conflictname Dirnames Group Installtid Name Packages \
+ Providename Provideversion Requirename Requireversion Triggername \
+ Filedigests Pubkeys Sha1header Sigmd5 Obsoletename \
+ __db.001 __db.002 __db.003 __db.004 __db.005 __db.006 __db.007 \
+ __db.008 __db.009
+do
+ touch %{buildroot}%{_localstatedir}/lib/rpm/$dbi
+done
+
+#macros
+
+mkdir -p %{buildroot}%{_libdir}/rpm/tizen
+install -m 755 %{SOURCE21} %{buildroot}%{_libdir}/rpm/tizen
+install -m 644 %{SOURCE20} %{buildroot}%{_libdir}/rpm/tizen
+
+# avoid dragging in tonne of perl libs for an unused script
+chmod 0644 %{buildroot}/%{_libdir}/rpm/perldeps.pl
+
+rm -rf %{buildroot}%{_mandir}/*/man?
+%clean
+rm -rf %{buildroot}
+
+%if %{with check}
+%check
+make check
+%endif
+
+%remove_docs
+rm -rf %{buildroot}/usr/share/man
+%find_lang rpm
+
+%post libs -p /sbin/ldconfig
+%postun libs -p /sbin/ldconfig
+
+%posttrans
+# XXX this is klunky and ugly, rpm itself should handle this
+dbstat=/usr/lib/rpm/rpmdb_stat
+if [ -x "$dbstat" ]; then
+ if "$dbstat" -e -h /var/lib/rpm 2>&1 | grep -q "doesn't match environment version \| Invalid argument"; then
+ rm -f /var/lib/rpm/__db.*
+ fi
+fi
+exit 0
+
+
+%files -f rpm.lang
+%manifest rpm.manifest
+%defattr(-,root,root,-)
+%doc GROUPS COPYING CREDITS
+%exclude /usr/lib/rpm/rpmdb_loadcvt
+%dir %{_sysconfdir}/rpm
+
+%attr(0755, root, root) %dir %{_localstatedir}/lib/rpm
+%attr(0644, root, root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) %{_localstatedir}/lib/rpm/*
+%attr(0755, root, root) %dir %{_libdir}/rpm
+
+/bin/rpm
+%{_bindir}/rpmkeys
+%{_bindir}/rpmspec
+%{_bindir}/rpm2cpio
+%{_bindir}/rpmdb
+%{_bindir}/rpmsign
+%{_bindir}/rpmquery
+%{_bindir}/rpmverify
+
+%{_libdir}/rpm-plugins/exec.so
+%{_libdir}/rpm-plugins/sepolicy.so
+
+%{_libdir}/rpm/macros
+%{_libdir}/rpm/tizen/macros
+%{_libdir}/rpm/rpmpopt*
+%{_libdir}/rpm/rpmrc
+
+%{_libdir}/rpm/rpmdb_*
+%{_libdir}/rpm/rpm.daily
+%{_libdir}/rpm/rpm.log
+%{_libdir}/rpm/rpm2cpio.sh
+%{_libdir}/rpm/tgpg
+
+%{_libdir}/rpm/platform
+
+%files libs
+%manifest rpm.manifest
+%defattr(-,root,root)
+%{_libdir}/librpm*.so.*
+
+%files build
+%manifest rpm.manifest
+%defattr(-,root,root)
+%{_bindir}/rpmbuild
+%{_bindir}/gendiff
+
+%{_libdir}/rpm/fileattrs/*.attr
+%{_libdir}/rpm/script.req
+
+%{_libdir}/rpm/brp-*
+%{_libdir}/rpm/check-buildroot
+%{_libdir}/rpm/check-files
+%{_libdir}/rpm/check-prereqs
+%{_libdir}/rpm/check-rpaths*
+%{_libdir}/rpm/debugedit
+%{_libdir}/rpm/elfdeps
+%{_libdir}/rpm/find-debuginfo.sh
+%{_libdir}/rpm/tizen/find-docs.sh
+%{_libdir}/rpm/find-lang.sh
+%{_libdir}/rpm/find-provides
+%{_libdir}/rpm/find-requires
+%{_libdir}/rpm/javadeps
+%{_libdir}/rpm/mono-find-provides
+%{_libdir}/rpm/mono-find-requires
+%{_libdir}/rpm/ocaml-find-provides.sh
+%{_libdir}/rpm/ocaml-find-requires.sh
+%{_libdir}/rpm/osgideps.pl
+%{_libdir}/rpm/perldeps.pl
+%{_libdir}/rpm/libtooldeps.sh
+%{_libdir}/rpm/pkgconfigdeps.sh
+%{_libdir}/rpm/perl.prov
+#%{_libdir}/rpm/debuginfo.prov
+#%{_libdir}/rpm/firmware.prov
+%{_libdir}/rpm/perl.req
+%{_libdir}/rpm/tcl.req
+%{_libdir}/rpm/pythondeps.sh
+%{_libdir}/rpm/rpmdeps
+%{_libdir}/rpm/config.guess
+%{_libdir}/rpm/config.sub
+%{_libdir}/rpm/mkinstalldirs
+%{_libdir}/rpm/desktop-file.prov
+%{_libdir}/rpm/fontconfig.prov
+
+%{_libdir}/rpm/macros.perl
+%{_libdir}/rpm/macros.python
+%{_libdir}/rpm/macros.php
+
+
+
+%files devel
+%manifest rpm.manifest
+%defattr(-,root,root)
+%{_includedir}/rpm
+%{_libdir}/librp*[a-z].so
+%{_bindir}/rpmgraph
+%{_libdir}/pkgconfig/rpm.pc
+
+
+%files security-plugin
+%manifest rpm.manifest
+%defattr(-,root,root)
+%{_libdir}/rpm-plugins/msm.so
+%config(noreplace) %{_sysconfdir}/device-sec-policy
+
diff --git a/packaging/rpmbuild_4.9.1_fix.patch b/packaging/rpmbuild_4.9.1_fix.patch
new file mode 100644
index 0000000..fb46271
--- /dev/null
+++ b/packaging/rpmbuild_4.9.1_fix.patch
@@ -0,0 +1,24 @@
+From f1ccce85da03399b7c33c35b3573df2b84d92ac7 Mon Sep 17 00:00:00 2001
+From: Elena, Reshetova <elena.reshetova@intel.com>
+Date: Mon, 20 Feb 2012 15:48:49 +0200
+Subject: [PATCH] Fix for rpmbuild functionality
+
+---
+ rpmbuild.c | 1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/rpmbuild.c b/rpmbuild.c
+index 856798a..0165f30 100644
+--- a/rpmbuild.c
++++ b/rpmbuild.c
+@@ -248,6 +248,7 @@ static int isSpecFile(const char * specfile)
+ if (f == NULL || ferror(f)) {
+ rpmlog(RPMLOG_ERR, _("Unable to open spec file %s: %s\n"),
+ specfile, strerror(errno));
++ if (f) fclose(f);
+ return 0;
+ }
+ count = fread(buf, sizeof(buf[0]), sizeof(buf), f);
+--
+1.7.4.1
+
diff --git a/packaging/rpmbuild_rpmfc_4.9.1_fix.patch b/packaging/rpmbuild_rpmfc_4.9.1_fix.patch
new file mode 100644
index 0000000..cf68be8
--- /dev/null
+++ b/packaging/rpmbuild_rpmfc_4.9.1_fix.patch
@@ -0,0 +1,158 @@
+From 3a0d3dea6d7cd4d66144ee6a68e91e327adaf874 Mon Sep 17 00:00:00 2001
+From: Elena, Reshetova <elena.reshetova@intel.com>
+Date: Mon, 20 Feb 2012 15:50:05 +0200
+Subject: [PATCH] Fix for rpmbuild rpmfc functionality
+
+---
+ build/rpmfc.c | 127 +++++++++++++++++++++++++++++----------------------------
+ 1 files changed, 64 insertions(+), 63 deletions(-)
+
+diff --git a/build/rpmfc.c b/build/rpmfc.c
+index a779b6a..698d485 100644
+--- a/build/rpmfc.c
++++ b/build/rpmfc.c
+@@ -681,79 +681,80 @@ void rpmfcPrint(const char * msg, rpmfc fc, FILE * fp)
+ 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)
++ 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
++ 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 (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;
++ 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);
++ 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;
+ }
+- break;
++ if (depval)
++ fprintf(fp, "\t%s\n", depval);
+ }
+- if (depval)
+- fprintf(fp, "\t%s\n", depval);
+ }
+ }
+ }
+--
+1.7.4.1
+
diff --git a/packaging/rpmio_base64_4.9.1_fix.patch b/packaging/rpmio_base64_4.9.1_fix.patch
new file mode 100644
index 0000000..71d8ef4
--- /dev/null
+++ b/packaging/rpmio_base64_4.9.1_fix.patch
@@ -0,0 +1,48 @@
+From 524ee5fa925cc40ff72ac79769f4c7e3f62e5092 Mon Sep 17 00:00:00 2001
+From: Elena, Reshetova <elena.reshetova@intel.com>
+Date: Mon, 20 Feb 2012 15:50:55 +0200
+Subject: [PATCH] Fix for rpmio base64 handling
+
+---
+ rpmio/base64.c | 6 ++++--
+ 1 files changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/rpmio/base64.c b/rpmio/base64.c
+index 6b006e1..3ebf2a5 100644
+--- a/rpmio/base64.c
++++ b/rpmio/base64.c
+@@ -104,7 +104,7 @@ static int base64_decode_value(unsigned char value_in)
+ {
+ 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 *outlen)
+ {
+ size_t outcnt = 0;
+ const char *inptr = in;
++ char *outptr;
+
+ *out = NULL;
+
+@@ -189,12 +190,13 @@ int b64decode(const char *in, void **out, size_t *outlen)
+
+ 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;
+ }
+--
+1.7.4.1
+
diff --git a/packaging/rpmlib_format_value_4.9.1_fix.patch b/packaging/rpmlib_format_value_4.9.1_fix.patch
new file mode 100644
index 0000000..ae0293c
--- /dev/null
+++ b/packaging/rpmlib_format_value_4.9.1_fix.patch
@@ -0,0 +1,40 @@
+From 8a0cc408da4644b67af0b57fc2c8e75e182f0e48 Mon Sep 17 00:00:00 2001
+From: Elena, Reshetova <elena.reshetova@intel.com>
+Date: Mon, 20 Feb 2012 15:51:50 +0200
+Subject: [PATCH] Fix for rpmlib format value
+
+---
+ lib/headerfmt.c | 15 ++++++++-------
+ 1 files changed, 8 insertions(+), 7 deletions(-)
+
+diff --git a/lib/headerfmt.c b/lib/headerfmt.c
+index 49c7047..05048f7 100644
+--- a/lib/headerfmt.c
++++ b/lib/headerfmt.c
+@@ -631,15 +631,16 @@ static char * formatValue(headerSprintfArgs hsa, sprintfTag tag, int element)
+ val = xstrdup("(none)");
+ }
+
+- need = strlen(val);
++ if (val) {
++ need = strlen(val);
+
+- if (val && need > 0) {
+- t = hsaReserve(hsa, need);
+- te = stpcpy(t, val);
+- hsa->vallen += (te - t);
++ if (need > 0) {
++ t = hsaReserve(hsa, need);
++ te = stpcpy(t, val);
++ hsa->vallen += (te - t);
++ }
++ free(val);
+ }
+- free(val);
+-
+ return (hsa->val + hsa->vallen);
+ }
+
+--
+1.7.4.1
+
diff --git a/packaging/security_4.9.1.patch b/packaging/security_4.9.1.patch
new file mode 100644
index 0000000..9967063
--- /dev/null
+++ b/packaging/security_4.9.1.patch
@@ -0,0 +1,5575 @@
+diff -Nuarp rpm/build/files.c rpm-security/build/files.c
+--- rpm/build/files.c 2012-08-08 09:33:56.000000000 +0300
++++ rpm-security/build/files.c 2012-10-01 10:29:50.283983646 +0300
+@@ -827,6 +827,7 @@ static VFA_t virtualFileAttributes[] = {
+ { "%readme", 0, RPMFILE_README },
+ { "%license", 0, RPMFILE_LICENSE },
+ { "%pubkey", 0, RPMFILE_PUBKEY },
++ { "%manifest", 0, RPMFILE_SECMANIFEST },
+ { NULL, 0, 0 }
+ };
+
+@@ -894,7 +895,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 {
+@@ -1612,6 +1613,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) {
+@@ -1868,6 +1877,8 @@ static rpmRC processPackageFiles(rpmSpec
+ dupAttrRec(&fl.cur_ar, specialDocAttrRec);
+ } else if (fl.currentFlags & RPMFILE_PUBKEY) {
+ (void) processMetadataFile(pkg, &fl, fileName, RPMTAG_PUBKEYS);
++ } else if (fl.currentFlags & RPMFILE_SECMANIFEST) {
++ (void) processMetadataFile(pkg, &fl, fileName, RPMTAG_SECMANIFEST);
+ } else {
+ (void) processBinaryFile(pkg, &fl, fileName);
+ }
+diff -Nuarp rpm/build/parsePreamble.c rpm-security/build/parsePreamble.c
+--- rpm/build/parsePreamble.c 2012-08-08 09:33:56.000000000 +0300
++++ rpm-security/build/parsePreamble.c 2012-10-01 10:29:50.287983644 +0300
+@@ -216,7 +216,7 @@ static int addSource(rpmSpec spec, Packa
+ *fieldp = '\0';
+
+ nump = fieldp_backup;
+- SKIPSPACE(nump);
++ if (nump) SKIPSPACE(nump);
+ if (nump == NULL || *nump == '\0') {
+ num = flag == RPMBUILD_ISSOURCE ? 0 : INT_MAX;
+ } else {
+@@ -891,6 +891,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 rpm/configure.ac rpm-security/configure.ac
+--- rpm/configure.ac 2012-08-08 09:33:56.000000000 +0300
++++ rpm-security/configure.ac 2012-10-01 10:29:50.291983643 +0300
+@@ -653,6 +653,65 @@ 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-msm 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 -lmagic"
++ 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])],
+@@ -732,6 +791,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])])
+@@ -878,5 +942,6 @@ AC_CONFIG_FILES([Makefile
+ luaext/Makefile
+ tests/Makefile
+ plugins/Makefile
++ security/Makefile
+ ])
+ AC_OUTPUT
+diff -Nuarp rpm/lib/fsm.c rpm-security/lib/fsm.c
+--- rpm/lib/fsm.c 2012-08-08 09:33:56.000000000 +0300
++++ rpm-security/lib/fsm.c 2012-10-01 10:36:53.175964792 +0300
+@@ -28,6 +28,8 @@
+ #include "lib/rpmts_internal.h" /* rpmtsSELabelFoo() only */
+ #include "lib/rpmug.h"
+
++#include "lib/rpmsecurity.h"
++
+ #include "debug.h"
+
+ #define _FSM_DEBUG 0
+@@ -800,6 +802,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;
+@@ -1127,7 +1134,7 @@ static int fsmCommitLinks(FSM_t fsm)
+ break;
+ }
+
+- 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;
+ fsm->ix = fsm->li->filex[i];
+ rc = fsmMapPath(fsm);
+@@ -1263,6 +1270,9 @@ static int fsmMkdirs(FSM_t fsm)
+ }
+ }
+
++ /* Call plugin hook to label the directory */
++ rc = rpmsecurityCallDirLabel(fsm, rc);
++
+ if (fsm->fcontext == NULL)
+ rpmlog(RPMLOG_DEBUG,
+ "%s directory created with perms %04o, no context.\n",
+@@ -1654,6 +1664,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) {
+@@ -2026,6 +2043,12 @@ if (!(fsm->mapFlags & CPIO_ALL_HARDLINKS
+ /*
+ * Set file security context (if not disabled).
+ */
++
++ /* Call security plugin with return code to finish the file. */
++ if (!rc) {
++ rc = rpmsecurityCallFsmClosed(fsm, rc);
++ }
++
+ if (!rc && !getuid()) {
+ rc = fsmMapFContext(fsm);
+ if (!rc) {
+diff -Nuarp rpm/lib/Makefile.am rpm-security/lib/Makefile.am
+--- rpm/lib/Makefile.am 2012-08-08 09:33:56.000000000 +0300
++++ rpm-security/lib/Makefile.am 2012-10-01 10:29:50.295983643 +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:1:0
+
+diff -Nuarp rpm/lib/package.c rpm-security/lib/package.c
+--- rpm/lib/package.c 2012-08-08 09:33:56.000000000 +0300
++++ rpm-security/lib/package.c 2012-10-01 10:29:50.295983643 +0300
+@@ -18,6 +18,8 @@
+ #include "rpmio/rpmio_internal.h" /* fd digest bits */
+ #include "lib/header_internal.h" /* XXX headerCheck */
+
++#include "lib/rpmsecurity.h"
++
+ #include "debug.h"
+
+ static int _print_pkts = 0;
+@@ -698,7 +700,10 @@ 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. */
+ rpmlog(RPMLOG_DEBUG, "%s: %s", fn, msg);
+diff -Nuarp rpm/lib/rpmfi.h rpm-security/lib/rpmfi.h
+--- rpm/lib/rpmfi.h 2012-08-08 09:33:56.000000000 +0300
++++ rpm-security/lib/rpmfi.h 2012-10-01 10:29:50.299983645 +0300
+@@ -60,6 +60,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 rpm/lib/rpmscript.c rpm-security/lib/rpmscript.c
+--- rpm/lib/rpmscript.c 2012-08-08 09:33:56.000000000 +0300
++++ rpm-security/lib/rpmscript.c 2012-10-01 10:29:50.299983645 +0300
+@@ -14,6 +14,8 @@
+ #include "rpmio/rpmlua.h"
+ #include "lib/rpmscript.h"
+
++#include "lib/rpmsecurity.h"
++
+ #include "debug.h"
+
+ /**
+@@ -162,7 +164,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) */
+@@ -286,7 +289,7 @@ exit:
+ if (fn) {
+ if (!rpmIsDebug())
+ xx = unlink(fn);
+- fn = _free(fn);
++ if (fn) fn = _free(fn);
+ }
+ return rc;
+ }
+diff -Nuarp 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 2012-10-01 10:39:43.959957177 +0300
+@@ -0,0 +1,281 @@
++#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_FSM_DIR_LABEL_FUNC)(FSM_t, int);
++ rpmRC (*SECURITYHOOK_POST_PSM_FUNC)(rpmte, char*, 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_DEBUG, _("Failed to dlopen %s %s\n"), path, dlerror());
++ return RPMRC_OK; /* in case plug‌in isn't avalible in the configuration */
++ }
++ 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_FSM_DIR_LABEL_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);
++ securityPlugin = NULL;
++ }
++ 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, "")) {
++/* enforce security by default #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);
++ free(securityPlugin);
++ securityPlugin = NULL;
++ }
++ }
++ 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, char* rootDir, int rpmrc)
++{
++ if (securityPlugin) {
++ rpmRC (*hookFunc)(rpmte, char*, int);
++ RPMSECURITY_SET_HOOK_FUNC(SECURITYHOOK_POST_PSM_FUNC);
++ return hookFunc(te, rootDir, 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 rpmsecurityCallDirLabel(FSM_t fsm, int rpmrc)
++{
++ if (securityPlugin) {
++ rpmRC (*hookFunc)(FSM_t, int);
++ RPMSECURITY_SET_HOOK_FUNC(SECURITYHOOK_FSM_DIR_LABEL_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 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 2012-10-01 10:37:47.415962375 +0300
+@@ -0,0 +1,170 @@
++#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 dir labelling plugin hook.
++ * This hook is called for each dir not explicitly included into the package
++ * @param fsm fsm in question
++ * @param rpmrc success from RPM
++ * @return RPMRC_OK on success, RPMRC_FAIL otherwise
++ */
++rpmRC rpmsecurityCallDirLabel(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 rootDir root directory for installation
++ * @param rpmrc success from RPM
++ * @return RPMRC_OK on success, RPMRC_FAIL otherwise
++ */
++rpmRC rpmsecurityCallPostPsm(rpmte te, char* rootDir, 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 rpm/lib/rpmtag.h rpm-security/lib/rpmtag.h
+--- rpm/lib/rpmtag.h 2012-08-08 09:33:56.000000000 +0300
++++ rpm-security/lib/rpmtag.h 2012-10-01 10:29:50.303983646 +0300
+@@ -299,7 +299,8 @@ typedef enum rpmTag_e {
+ RPMTAG_ORDERNAME = 5035, /* s[] */
+ RPMTAG_ORDERVERSION = 5036, /* s[] */
+ RPMTAG_ORDERFLAGS = 5037, /* i[] */
+-
++ RPMTAG_SECMANIFEST = 5038, /* s[] security manifest file */
++ RPMTAG_SECSWSOURCE = 5039, /* s[] security software source */
+ RPMTAG_FIRSTFREE_TAG /*!< internal */
+ } rpmTag;
+
+diff -Nuarp rpm/lib/rpmte.c rpm-security/lib/rpmte.c
+--- rpm/lib/rpmte.c 2012-08-08 09:33:56.000000000 +0300
++++ rpm-security/lib/rpmte.c 2012-10-01 10:29:50.303983646 +0300
+@@ -14,7 +14,9 @@
+ #include <rpm/rpmlog.h>
+
+ #include "lib/rpmplugins.h"
++#include "lib/rpmsecurity.h"
+ #include "lib/rpmte_internal.h"
++#include "lib/rpmts_internal.h"
+
+ #include "debug.h"
+
+@@ -895,7 +897,7 @@ int rpmteProcess(rpmte te, pkgGoal goal)
+ /* Only install/erase resets pkg file info */
+ int scriptstage = (goal != PKG_INSTALL && goal != PKG_ERASE);
+ int reset_fi = (scriptstage == 0);
+- int failed = 1;
++ int failed = 0;
+
+ /* Dont bother opening for elements without pre/posttrans scripts */
+ if (goal == PKG_PRETRANS || goal == PKG_POSTTRANS) {
+@@ -909,7 +911,17 @@ 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 */
++ /* But do not call plugin for the pre/posttrans scripts */
++ if (goal != PKG_PRETRANS && goal != PKG_POSTTRANS)
++ failed = rpmsecurityCallPrePsm(te);
++ if (!failed) {
++ failed = rpmpsmRun(te->ts, te, goal);
++ /* Call security plugin to finish any te related tasks */
++ /* But do not call plugin for the pre/posttrans scripts */
++ if (goal != PKG_PRETRANS && goal != PKG_POSTTRANS)
++ failed = rpmsecurityCallPostPsm(te, te->ts->rootDir, failed);
++ }
+ rpmteClose(te, reset_fi);
+ }
+
+diff -Nuarp rpm/lib/rpmts.c rpm-security/lib/rpmts.c
+--- rpm/lib/rpmts.c 2012-08-08 09:33:56.000000000 +0300
++++ rpm-security/lib/rpmts.c 2012-10-01 10:29:50.303983646 +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"
+@@ -630,6 +631,8 @@ rpmts rpmtsFree(rpmts ts)
+ ts->installLangs = argvFree(ts->installLangs);
+
+ ts->plugins = rpmpluginsFree(ts->plugins);
++ /* Free security plugin here also. */
++ rpmsecurityFreePlugin();
+
+ if (_rpmts_stats)
+ rpmtsPrintStats(ts);
+diff -Nuarp rpm/lib/rpmtypes.h rpm-security/lib/rpmtypes.h
+--- rpm/lib/rpmtypes.h 2012-08-08 09:33:56.000000000 +0300
++++ rpm-security/lib/rpmtypes.h 2012-10-01 10:29:50.303983646 +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 rpm/lib/transaction.c rpm-security/lib/transaction.c
+--- rpm/lib/transaction.c 2012-08-08 09:33:56.000000000 +0300
++++ rpm-security/lib/transaction.c 2012-10-01 10:29:50.307983646 +0300
+@@ -21,6 +21,8 @@
+ #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 */
+ #if STATFS_IN_SYS_STATVFS
+@@ -354,6 +356,9 @@ static int handleInstInstalledFile(const
+ }
+ }
+
++ /* 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),
+@@ -1420,6 +1425,13 @@ int rpmtsRun(rpmts ts, rpmps okProbs, rp
+ goto exit;
+ }
+
++ /* Setup the security plugin */
++ if (rpmsecuritySetupPlugin(ts)) {
++/* enforce security by default #ifdef ENFORCE_SECURITY */
++ goto exit;
++/* #endif */
++ }
++
+ rpmtsSetupCollections(ts);
+
+ /* Check package set for problems */
+@@ -1452,9 +1464,15 @@ 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 rpm/macros.in rpm-security/macros.in
+--- rpm/macros.in 2012-08-08 09:33:56.000000000 +0300
++++ rpm-security/macros.in 2012-10-01 10:29:50.307983646 +0300
+@@ -1070,5 +1070,7 @@ done \
+ %__collection_sepolicy %{__plugindir}/sepolicy.so
+ %__collection_sepolicy_flags 1
+
++%__security_plugin %{__plugindir}/msm.so
++
+ # \endverbatim
+ #*/
+diff -Nuarp rpm/Makefile.am rpm-security/Makefile.am
+--- rpm/Makefile.am 2012-08-08 09:33:56.000000000 +0300
++++ rpm-security/Makefile.am 2012-10-01 10:29:50.311983646 +0300
+@@ -29,7 +29,11 @@ if ENABLE_PLUGINS
+ SUBDIRS += plugins
+ 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
+
+@@ -76,6 +80,8 @@ pkginclude_HEADERS += lib/rpmte.h
+ pkginclude_HEADERS += lib/rpmts.h
+ pkginclude_HEADERS += lib/rpmtypes.h
+ pkginclude_HEADERS += lib/rpmvf.h
++pkginclude_HEADERS += lib/rpmplugins.h
++pkginclude_HEADERS += lib/rpmsecurity.h
+
+ pkginclude_HEADERS += sign/rpmsign.h
+
+diff -Nuarp rpm/preinstall.am rpm-security/preinstall.am
+--- rpm/preinstall.am 2012-08-08 09:33:56.000000000 +0300
++++ rpm-security/preinstall.am 2012-10-01 10:29:50.311983646 +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 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 2012-10-01 10:29:50.315983644 +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
+diff -Nuarp rpm/security/Makefile.msm rpm-security/security/Makefile.msm
+--- rpm/security/Makefile.msm 1970-01-01 02:00:00.000000000 +0200
++++ rpm-security/security/Makefile.msm 2012-10-01 10:29:50.315983644 +0300
+@@ -0,0 +1,15 @@
++CC=gcc
++CFLAGS=-g -Wall
++LDFLAGS=-lxml2 -lcap -lattr -lrpmio -lsmack
++INCLUDES=-I/usr/include/libxml2 -I..
++
++all: msmmatch
++
++msmmatch: msmmatch.o
++ $(CC) -o $@ $^ $(LDFLAGS)
++
++.c.o:
++ $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@
++
++clean:
++ rm msmmatch *.o
+diff -Nuarp rpm/security/msm.c rpm-security/security/msm.c
+--- rpm/security/msm.c 1970-01-01 02:00:00.000000000 +0200
++++ rpm-security/security/msm.c 2012-10-01 10:53:48.919919507 +0300
+@@ -0,0 +1,896 @@
++/*
++ * This file is part of MSM security plugin
++ * Greatly based on the code of MSSF security plugin
++ *
++ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
++ *
++ * Contact: Tero Aho <ext-tero.aho@nokia.com>
++ *
++ * Copyright (C) 2011 -2012 Intel Corporation.
++ *
++ * Contact: Elena Reshetova <elena.reshetova@intel.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ */
++
++#include "debug.h"
++
++#include <errno.h>
++#include <sys/types.h>
++#include <unistd.h>
++#include <sys/wait.h>
++#include <sys/prctl.h>
++#include <sys/capability.h>
++#include <sys/stat.h>
++
++#include <rpm/rpmfileutil.h>
++#include <rpm/rpmmacro.h>
++#include <rpm/rpmpgp.h>
++#include <rpm/rpmkeyring.h>
++#include <rpm/rpmdb.h>
++
++#include "rpmio/base64.h"
++#include "rpmio/rpmio.h"
++
++#include "msm.h"
++
++typedef struct fileconflict {
++ const char *path;
++ sw_source_x *sw_source;
++ UT_hash_handle hh;
++} fileconflict;
++
++typedef struct packagecontext {
++ char *data; /*!< base64 manifest data */
++ manifest_x *mfx; /*!< parsed manifest data */
++ rpmte te; /*!< related te */
++ struct packagecontext *next; /*!< next in linked list */
++ struct smack_accesses *smack_accesses; /*!< handle to smack_accesses */
++} packagecontext;
++
++static rpmts ts = NULL;
++static int rootSWSource= 0;
++static manifest_x *root = NULL; /* pointer to device security policy file */
++static packagecontext *context = NULL;
++static sw_source_x *current = NULL;
++static packagecontext *contextsHead = NULL;
++static packagecontext *contextsTail = NULL;
++static fileconflict *allfileconflicts = NULL;
++static char* ownSmackLabel = NULL;
++static int SmackEnabled = 0;
++static magic_t cookie = NULL;
++
++rpmRC SECURITYHOOK_INIT_FUNC(rpmts _ts, const char *_opts)
++{
++ ts = _ts;
++ int res = 0;
++
++ rpmlog(RPMLOG_INFO, "reading device security policy from %s\n", DEVICE_SECURITY_POLICY);
++ root = msmProcessDevSecPolicyXml(DEVICE_SECURITY_POLICY);
++
++ if (root) {
++ if (msmSetupSWSources(NULL, root, NULL)) {
++ rpmlog(RPMLOG_ERR, "Failed to setup device security policy from %s\n",
++ DEVICE_SECURITY_POLICY);
++ return RPMRC_FAIL;
++ }
++ } else {
++ /* Do not allow plug-in to proceed without security policy existing */
++ rpmlog(RPMLOG_ERR, "Failed to process sw sources from %s\n",
++ DEVICE_SECURITY_POLICY);
++ return RPMRC_FAIL;
++ }
++
++ /* check its own security context and store it for the case when packages without manifest will be installed */
++ struct stat buf;
++
++ if (stat(SMACK_LOAD_PATH, &buf) == 0) {
++ res = smack_new_label_from_self(&ownSmackLabel);
++ SmackEnabled = 1;
++ if (res != 0) {
++ rpmlog(RPMLOG_ERR, "Failed to obtain rpm security context\n");
++ return RPMRC_FAIL;
++ }
++ } else {
++ rpmlog(RPMLOG_INFO, "Smack disabled in kernel. Going to the image build mode. \n");
++ ownSmackLabel = strdup("_");
++ SmackEnabled = 0;
++ }
++
++ if (stat(SMACK_RULES_PATH, &buf) != 0) {
++ rpmlog(RPMLOG_INFO, "A directory for writing smack rules is missing. Creating one.\n");
++ mode_t mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IROTH; // 644 -rwer--r--
++ if (stat(SMACK_RULES_PATH_BEG, &buf) != 0) {
++ if (mkdir(SMACK_RULES_PATH_BEG, mode) != 0) {
++ rpmlog(RPMLOG_ERR, "Failed to create a sub-directory for smack rules\n");
++ return RPMRC_FAIL;
++ }
++ }
++ if (mkdir(SMACK_RULES_PATH, mode) != 0){
++ rpmlog(RPMLOG_ERR, "Failed to create a directory for smack rules\n");
++ return RPMRC_FAIL;
++ }
++ }
++
++ rpmlog(RPMLOG_DEBUG, "rpm security context: %s\n", ownSmackLabel);
++
++ cookie = magic_open(0);
++ if (!cookie)
++ return RPMRC_FAIL;
++
++ if (magic_load(cookie, NULL) != 0) {
++ rpmlog(RPMLOG_ERR, "cannot load magic database - %s\n", magic_error(cookie));
++ magic_close(cookie);
++ return RPMRC_FAIL;
++ }
++
++ return RPMRC_OK;
++}
++
++static int findSWSourceByName(sw_source_x *sw_source, void *param)
++{
++ const char *name = (const char *)param;
++ return strcmp(sw_source->name, name);
++}
++
++static char *getFilePath(const char *dirName, const char *baseName)
++{
++ char *fullName = NULL;
++ size_t len = 0;
++
++ if (!dirName) return fullName;
++ len = strlen(dirName);
++
++ if (baseName) {
++ if (dirName[len-1] == '/') {
++ len += strlen(baseName);
++ fullName = malloc(len+1);
++ if (fullName)
++ sprintf(fullName, "%s%s", dirName, baseName);
++ } else {
++ len += strlen(baseName) + 1;
++ fullName = malloc(len+1);
++ if (fullName)
++ sprintf(fullName, "%s/%s", dirName, baseName);
++ }
++ } else {
++ fullName = malloc(len+1);
++ if (fullName)
++ sprintf(fullName, "%s", dirName);
++ }
++ return fullName;
++}
++
++rpmRC SECURITYHOOK_FILE_CONFLICT_FUNC(rpmts ts, rpmte te, rpmfi fi,
++ Header oldHeader, rpmfi oldFi,
++ int rpmrc)
++{
++ fileconflict *fc;
++
++ const char *name = headerGetString(oldHeader, RPMTAG_SECSWSOURCE);
++ if (!name || !root) {
++ return rpmrc; /* no sw source(s) - abnormal state */
++ }
++
++ sw_source_x *sw_source = msmSWSourceTreeTraversal(root->sw_sources, findSWSourceByName, (void *)name);
++ if (!sw_source)
++ return rpmrc; /* no old sw_source - abnormal state */
++
++ const char *path = getFilePath(rpmfiDN(fi), rpmfiBN(fi));
++ if (!path) return RPMRC_FAIL;
++
++ HASH_FIND(hh, allfileconflicts, path, strlen(path), fc);
++ if (!fc) {
++ /* Add new file conflict into hash */
++ fc = xcalloc(1, sizeof(*fc));
++ if (!fc) return RPMRC_FAIL;
++ fc->path = path;
++ fc->sw_source = sw_source;
++ HASH_ADD_KEYPTR(hh, allfileconflicts, path, strlen(path), fc);
++ } else {
++ /* Many packages have installed the same file */
++ if (strcmp(sw_source->rankkey, fc->sw_source->rankkey) <= 0) {
++ /* Change sw source to the higher ranked one */
++ fc->sw_source = sw_source;
++ }
++ msmFreePointer((void**)&path);
++ }
++
++ if (rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEOLDFILES) {
++ /* Conflict has been noted, now return ok. It will be actually */
++ /* resolved later when conflicting package signature is verified */
++ /* and sw_source is known. */
++ return RPMRC_OK;
++ }
++ return rpmrc;
++}
++
++rpmRC SECURITYHOOK_PRE_TSM_FUNC(rpmts _ts)
++{
++ packagecontext *ctx = context;
++ if (!ctx) return RPMRC_FAIL;
++
++ return RPMRC_OK;
++}
++
++static int findSWSourceBySignature(sw_source_x *sw_source, void *param)
++{
++ origin_x *origin;
++ keyinfo_x *keyinfo;
++ pgpDig dig = (pgpDig)param;
++
++ for (origin = sw_source->origins; origin; origin = origin->prev) {
++ for (keyinfo = origin->keyinfos; keyinfo; keyinfo = keyinfo->prev) {
++ pgpDig ddig = pgpNewDig();
++ if (pgpPrtPkts(keyinfo->keydata, keyinfo->keylen, ddig, 0)) {
++ rpmlog(RPMLOG_INFO, "invalid sw source key\n");
++ pgpFreeDig(ddig);
++ return -1;
++ }
++ /* Compare all fields of RSA key. */
++ if (SECITEM_ItemsAreEqual(&dig->keydata->u.rsa.publicExponent, &ddig->keydata->u.rsa.publicExponent) &&
++ SECITEM_ItemsAreEqual(&dig->keydata->u.rsa.modulus, &ddig->keydata->u.rsa.modulus)) {
++ pgpFreeDig(ddig);
++ return 0;
++ }
++ pgpFreeDig(ddig);
++ }
++ }
++ return 1;
++}
++
++rpmRC SECURITYHOOK_VERIFY_FUNC(rpmKeyring keyring, rpmtd sigtd,
++ pgpDig dig, rpmRC rpmrc)
++{
++ current = NULL;
++
++#if 0
++ if (!root) {
++ if (rpmrc == RPMRC_NOKEY) {
++ rpmlog(RPMLOG_INFO, "package verified as root sw source\n");
++ rootSWSource = 1; /* accept any signed package as root */
++ return RPMRC_OK;
++ }
++ rpmlog(RPMLOG_ERR, "No device security policy, cannot verify signature\n");
++ return rpmrc;
++ }
++
++
++// make currently that even non-signed package with root policy will be treated as trusted
++
++ if (!root) {
++ rpmlog(RPMLOG_INFO, "package verified as root sw source\n");
++ rootSWSource = 1; /* accept any signed package as root */
++ return RPMRC_OK;
++ }
++
++//------------------
++#endif
++
++ if (!root) {
++ rpmlog(RPMLOG_INFO, "No device policy found\n");
++ rootSWSource = 1; /* accept any signed package as root */
++ return rpmrc;
++ }
++
++ if (rpmrc == RPMRC_NOKEY) {
++ /* No key, revert to unknown sw source. */
++ rpmlog(RPMLOG_INFO, "no key for signature, cannot search sw source\n");
++ goto exit;
++ }
++ if (rpmrc) {
++ /* RPM failed to verify signature */
++ rpmlog(RPMLOG_ERR, "Invalid signature, cannot search sw source\n");
++ return rpmrc;
++ }
++ if (sigtd->tag != RPMSIGTAG_RSA) {
++ /* Not RSA, revert to unknown sw source. */
++ rpmlog(RPMLOG_INFO, "no RSA signature, cannot search sw source\n");
++ goto exit;
++ }
++ current = msmSWSourceTreeTraversal(root->sw_sources, findSWSourceBySignature, dig);
++ if (current)
++ rpmlog(RPMLOG_INFO, "signature matches sw source %s\n", current->name);
++ else
++ rpmlog(RPMLOG_INFO, "valid signature but no matching sw source\n");
++
++ exit:
++ if (!current) {
++ current = msmSWSourceTreeTraversal(root->sw_sources, findSWSourceByName, (void *)"_default_");
++ if (current)
++ rpmlog(RPMLOG_INFO, "using _default_ sw source\n");
++ else { // for now in case default sw source isn't there yet, allow to think that it is coming from root
++ current = msmSWSourceTreeTraversal(root->sw_sources, findSWSourceByName, (void *)"root");
++ if (current)
++ rpmlog(RPMLOG_INFO, "using _root_ sw source now for testing\n");
++ }
++ }
++
++ return rpmrc;
++}
++
++static packagecontext *msmNew(rpmte te)
++{
++ Header h;
++ struct rpmtd_s msm;
++ int count;
++ packagecontext *ctx = NULL;
++ const char *sw_source = NULL;
++
++ rpmtdReset(&msm);
++
++ h = rpmteHeader(te);
++ if (!h) return NULL;
++
++ ctx = xcalloc(1, sizeof(*ctx));
++ if (!ctx) {
++ goto exit1;
++ }
++ ctx->te = te;
++
++ if (!headerIsEntry(h, RPMTAG_SECMANIFEST)) {
++ goto exit1;
++ }
++
++ if (!headerGet(h, RPMTAG_SECMANIFEST, &msm, HEADERGET_MINMEM)) {
++ goto exit1;
++ }
++
++ count = rpmtdCount(&msm);
++ if (count != 1) {
++ goto exit2;
++ }
++
++ ctx->data = xstrdup(rpmtdNextString(&msm));
++ rpmlog(RPMLOG_INFO, "%s manifest b64 data: %.40s...\n",
++ rpmteN(ctx->te), ctx->data);
++
++ if (rpmteType(ctx->te) == TR_ADDED) {
++ /* Save sw_source name into database, we need it when package */
++ /* is removed because signature verify is not called then. */
++ if (current) sw_source = current->name;
++ else if (rootSWSource) sw_source = rpmteN(ctx->te);
++
++ if (!sw_source || !headerPutString(h, RPMTAG_SECSWSOURCE, sw_source)) {
++ rpmlog(RPMLOG_ERR, "Failed to save sw source for %s, sw_source: %s\n",
++ rpmteN(ctx->te), sw_source);
++ msmFreePointer((void**)&ctx->data);
++ msmFreePointer((void**)&ctx);
++ }
++ }
++
++
++ exit2:
++ rpmtdFreeData(&msm);
++ exit1:
++ headerFree(h);
++
++ return ctx;
++}
++
++static packagecontext *msmAddTE(rpmte te)
++{
++ packagecontext *ctx = msmNew(te);
++ if (ctx) {
++ /* add the new policy to the list */
++ if (!contextsHead) {
++ contextsHead = ctx;
++ contextsTail = ctx;
++ } else {
++ if (rpmteType(te) == TR_ADDED) {
++ /* add to the end of the list */
++ contextsTail->next = ctx;
++ contextsTail = ctx;
++ } else {
++ /* add to the beginning of the list */
++ ctx->next = contextsHead;
++ contextsHead = ctx;
++ }
++ }
++ }
++ return ctx;
++}
++
++rpmRC SECURITYHOOK_PRE_PSM_FUNC(rpmte te)
++{
++ packagecontext *ctx = NULL;
++ manifest_x *mfx = NULL;
++ char *xml = NULL;
++ size_t xmllen;
++ rpmRC rc = RPMRC_OK;
++ int ret = 0;
++
++ if (!root && !rootSWSource) {
++ /* no sw source config, just exit */
++ goto exit;
++ }
++
++ if (!current) {
++ /* this means that verify hook has not been called */
++ current = msmSWSourceTreeTraversal(root->sw_sources, findSWSourceByName, (void *)"_default_");
++ if (current)
++ rpmlog(RPMLOG_INFO, "using _default_ sw source\n");
++ else {
++ rpmlog(RPMLOG_ERR, "Default source isn't availiable. Package source can't be determined. Abort installation\n");
++ goto fail;
++ }
++ }
++
++ ctx = msmAddTE(te);
++ if (!ctx) {
++ rpmlog(RPMLOG_ERR, "Failed to create security context for %s\n",
++ rpmteNEVRA(te));
++ goto fail;
++ }
++
++ if (rpmteType(ctx->te) == TR_REMOVED) {
++
++ /* Verify hook is not called before remove, */
++ /* so get the sw_source name from package header */
++ Header h = rpmteHeader(te);
++ if (h) {
++ const char *name = headerGetString(h, RPMTAG_SECSWSOURCE);
++ if (name) {
++ current = msmSWSourceTreeTraversal(root->sw_sources, findSWSourceByName, (void *)name);
++ rpmlog(RPMLOG_INFO, "removing %s from sw source %s\n",
++ rpmteN(ctx->te), name);
++ }
++ headerFree(h);
++ }
++ /* if (!current) {
++ rpmlog(RPMLOG_INFO, "no sw source for removing %s\n", rpmteN(ctx->te));
++ goto exit;
++ }*/
++ }
++
++ if (!ctx->data) {
++ rpmlog(RPMLOG_INFO, "No manifest in this package. Creating default one\n");
++
++ /* create default manifest manually. Make the package to belong to the domain where rpm is running */
++
++ mfx = calloc(1, sizeof(manifest_x));
++ if (!mfx) goto fail;
++ mfx->sw_source = current;
++ mfx->name = strdup(rpmteN(ctx->te));
++ mfx->request = calloc(1, sizeof(request_x));
++ if (!mfx->request) {
++ msmFreePointer((void**)&mfx->name);
++ msmFreePointer((void**)&mfx);
++ goto fail;
++ }
++ mfx->request->ac_domain = strdup(ownSmackLabel);
++ rpmlog(RPMLOG_DEBUG, "Done with manifest creation\n");
++
++ } else {
++ if (b64decode(ctx->data, (void **) &xml, &xmllen) != 0) {
++ rpmlog(RPMLOG_ERR, "Failed to decode manifest for %s\n",
++ rpmteN(ctx->te));
++ goto fail;
++ }
++
++ rpmlog(RPMLOG_INFO, "parsing %s manifest: \n%s", rpmteN(ctx->te), xml);
++ mfx = msmProcessManifestXml(xml, xmllen, current, rpmteN(ctx->te));
++
++ if (!mfx) {
++ rpmlog(RPMLOG_ERR, "Failed to parse manifest for %s\n",
++ rpmteN(ctx->te));
++ goto fail;
++ }
++ }
++
++
++ ctx->mfx = mfx;
++
++ int res = smack_accesses_new(&(ctx->smack_accesses));
++ if (res != 0) {
++ rpmlog(RPMLOG_ERR, "Failed to create smack access set\n");
++ goto fail;
++ }
++
++ if (rpmteType(ctx->te) == TR_ADDED) {
++
++ rpmlog(RPMLOG_DEBUG, "Installing the package\n");
++
++ package_x *package = NULL;
++
++ if (rootSWSource) {
++ /* this is the first package */
++ package = msmCreatePackage(mfx->name, mfx->sw_sources,
++ mfx->provides, NULL);
++ } else if (mfx->sw_source) {
++ /* all packages must have sw_source */
++ package = msmCreatePackage(mfx->name, mfx->sw_source,
++ mfx->provides, NULL);
++ } else {
++ rpmlog(RPMLOG_ERR, "Package doesn't have a sw source. Abnormal situation. Abort.\n");
++ goto fail;
++ }
++
++ if (!package) {
++ rpmlog(RPMLOG_ERR, "Package could not be created. \n");
++ goto fail;
++ }
++
++ mfx->provides = NULL; /* owned by package now */
++
++ if (!package->sw_source) { /* this must never happen */
++ rpmlog(RPMLOG_ERR, "Install failed. Check that configuration has at least root sw source installed.\n");
++ msmFreePackage(package);
++ package = NULL;
++ goto fail;
++ }
++
++ rpmlog(RPMLOG_INFO, "adding %s manifest data to system, package_name %s\n",
++ rpmteN(ctx->te), package->name);
++
++ if (msmSetupPackages(ctx->smack_accesses, package, package->sw_source)) {
++ rpmlog(RPMLOG_ERR, "Package setup failed for %s\n", rpmteN(ctx->te) );
++ msmFreePackage(package);
++ package = NULL;
++ goto fail;
++ }
++
++ if (rootSWSource) {
++ /* current is root */
++ root = ctx->mfx;
++ }
++
++ rpmlog(RPMLOG_DEBUG, "Starting the security setup...\n");
++ unsigned int smackLabel = 0;
++
++ if (rootSWSource || ctx->mfx->sw_source) {
++ if (ctx->mfx->sw_sources) {
++ smackLabel = 1; /* setting this one on since this manifest doesn't have any define/request section */
++ ret = msmSetupSWSources(ctx->smack_accesses, ctx->mfx, ts);
++ if (ret) {
++ rpmlog(RPMLOG_ERR, "SW source setup failed for %s\n",
++ rpmteN(ctx->te));
++ msmCancelPackage(ctx->mfx->name);
++ goto fail;
++ }
++ }
++ if (ctx->mfx->define) {
++ if (ctx->mfx->define->name)
++ smackLabel = 1;
++ ret = msmSetupDefine(ctx->smack_accesses, ctx->mfx);
++ if (ret) {
++ rpmlog(RPMLOG_ERR, "AC domain setup failed for %s\n",
++ rpmteN(ctx->te));
++ msmCancelPackage(ctx->mfx->name);
++ goto fail;
++ }
++ }
++ if (ctx->mfx->request) {
++ if (ctx->mfx->request->ac_domain)
++ smackLabel = 1;
++ ret = msmSetupRequests(ctx->mfx);
++ if (ret) {
++ rpmlog(RPMLOG_ERR, "Request setup failed for %s\n",
++ rpmteN(ctx->te));
++ msmCancelPackage(ctx->mfx->name);
++ goto fail;
++ }
++ }
++ if (ctx->smack_accesses) {
++ ret = msmSetupSmackRules(ctx->smack_accesses, ctx->mfx->name, 0, SmackEnabled);
++ smack_accesses_free(ctx->smack_accesses);
++ ctx->smack_accesses = NULL;
++ if (ret) {
++ rpmlog(RPMLOG_ERR, "Setting up smack rules for %s failed\n",
++ rpmteN(ctx->te));
++ msmCancelPackage(ctx->mfx->name);
++ goto fail;
++ }
++ }
++ if (package->provides) {
++ ret = msmSetupDBusPolicies(package);
++ if (ret) {
++ rpmlog(RPMLOG_ERR, "Setting up dbus policies for %s failed\n",
++ rpmteN(ctx->te));
++ msmCancelPackage(ctx->mfx->name);
++ goto fail;
++ }
++ }
++
++ /* last check is needed in order to catch in advance
++ the situation when no ac domain defined or requested */
++ if (smackLabel == 0) {
++ rpmlog(RPMLOG_ERR, "No ac domain defined or requested for package %s. Abort.\n", rpmteN(ctx->te));
++ msmCancelPackage(ctx->mfx->name);
++ goto fail;
++ }
++ }
++
++
++ } else if (rpmteDependsOn(ctx->te)) { /* TR_REMOVED */
++ rpmlog(RPMLOG_INFO, "upgrading package %s by %s\n",
++ rpmteNEVR(ctx->te), rpmteNEVR(rpmteDependsOn(ctx->te)));
++ } else if (mfx->sw_sources) {
++ rpmlog(RPMLOG_ERR, "Cannot remove sw source package %s\n",
++ rpmteN(ctx->te));
++ goto fail;
++ }
++
++ rpmlog(RPMLOG_DEBUG, "Finished with pre psm hook \n");
++
++ goto exit;
++
++ fail: /* error, cancel the rpm operation */
++ rc = RPMRC_FAIL;
++
++ exit: /* success, continue rpm operation */
++ context = ctx;
++ msmFreePointer((void**)&xml);
++
++ return rc;
++}
++
++rpmRC SECURITYHOOK_SCRIPT_EXEC_FUNC(ARGV_const_t argv)
++{
++ /* no functionality yet for scripts, just execute it like it is */
++ return execv(argv[0], argv);
++}
++
++rpmRC SECURITYHOOK_FSM_OPENED_FUNC(FSM_t fsm)
++{
++
++ //check if there any conflicts that prevent file being written to the disk
++
++ fileconflict *fc;
++ packagecontext *ctx = context;
++ if (!ctx) return RPMRC_FAIL;
++
++ char* fullpath = getFilePath(fsm->dirName, fsm->baseName);
++ if (!fullpath) return RPMRC_FAIL;
++ rpmlog(RPMLOG_DEBUG, "Constructed file name: %s\n", fullpath);
++ HASH_FIND(hh, allfileconflicts, fullpath, strlen(fullpath), fc);
++ msmFreePointer((void**)&fullpath);
++
++ if (fc) {
++ /* There is a conflict, see if we are not allowed to overwrite */
++ if (!current || (strcmp(current->rankkey, fc->sw_source->rankkey) > 0)) {
++ rpmlog(RPMLOG_ERR, "%s has file conflict in %s from sw source %s\n",
++ rpmteN(ctx->te), fc->path, fc->sw_source->name);
++ return RPMRC_FAIL;
++ }
++ rpmlog(RPMLOG_INFO, "%s from %s overwrites %s from %s\n",
++ rpmteN(ctx->te), current->name, fc->path, fc->sw_source->name);
++ }
++
++ return RPMRC_OK;
++}
++
++rpmRC SECURITYHOOK_FSM_UPDATED_FUNC(FSM_t fsm)
++{
++
++ packagecontext *ctx = context;
++ if (!ctx) return RPMRC_FAIL;
++
++ //no need to have any hashes calculation now
++
++ return RPMRC_OK;
++}
++
++rpmRC SECURITYHOOK_FSM_CLOSED_FUNC(FSM_t fsm, int rpmrc)
++{
++
++ packagecontext *ctx = context;
++ if (!ctx) return RPMRC_FAIL;
++ if (rpmrc) return rpmrc;
++
++ rpmlog(RPMLOG_DEBUG, "Started with FSM_CLOSED_FUNC hook for file dir name: %s, base name %s \n", fsm->dirName, fsm->baseName);
++
++ if (ctx->mfx) {
++ file_x *file = xcalloc(1, sizeof(*file));
++ if (file) {
++ file->path = getFilePath(fsm->dirName, fsm->baseName);
++ LISTADD(ctx->mfx->files, file);
++ if (rpmteType(ctx->te) == TR_ADDED) {
++ if (msmSetFileXAttributes(ctx->mfx, file->path, cookie) < 0) {
++ rpmlog(RPMLOG_ERR, "Setting of extended attributes failed for file %s from package %s\n",
++ file->path, rpmteN(ctx->te));
++ return RPMRC_FAIL;
++ }
++ }
++
++ } else
++ return RPMRC_FAIL;
++ } else {
++ rpmlog(RPMLOG_ERR, "Manifest is missing while it should be present for the package %s\n",
++ rpmteN(ctx->te));
++ return RPMRC_FAIL;
++ }
++
++ rpmlog(RPMLOG_DEBUG, "Finished with FSM_CLOSED_FUNC hook for file dir name: %s, base name %s \n", fsm->dirName, fsm->baseName);
++ return RPMRC_OK;
++}
++
++rpmRC SECURITYHOOK_FSM_DIR_LABEL_FUNC(FSM_t fsm, int rpmrc)
++{
++ packagecontext *ctx = context;
++ if (!ctx) return RPMRC_FAIL;
++ if (rpmrc) return rpmrc;
++
++ rpmlog(RPMLOG_DEBUG, "Started with FSM_DIR_LABEL_FUNC hook for file fsm->path: %s \n", fsm->path);
++ if (ctx->mfx) {
++ if (msmSetFileXAttributes(ctx->mfx, fsm->path, cookie) < 0) {
++ rpmlog(RPMLOG_ERR, "Setting of extended attributes failed for dir %s from package %s\n",
++ fsm->path, rpmteN(ctx->te));
++ rpmrc = RPMRC_FAIL;
++ }
++
++ } else {
++ rpmlog(RPMLOG_ERR, "Manifest is missing while it should be present for the package %s\n",
++ rpmteN(ctx->te));
++ return RPMRC_FAIL;
++ }
++
++ rpmlog(RPMLOG_DEBUG, "Finished with FSM_DIR_LABEL_FUNC hook for file fsm->path: %s \n", fsm->path);
++ return rpmrc;
++}
++
++
++rpmRC SECURITYHOOK_POST_PSM_FUNC(rpmte te, char* rootDir, int rpmrc)
++{
++
++ int ret = 0;
++ packagecontext *ctx = context;
++ if (!ctx) return RPMRC_FAIL;
++
++ if (rpmrc) {
++ /* failure in rpm psm, rollback */
++ if (rpmteType(ctx->te) == TR_ADDED)
++ msmCancelPackage(ctx->mfx->name);
++ goto exit;
++ }
++
++ if (!ctx->mfx){
++ rpmlog(RPMLOG_ERR, "Manifest is missing while it should be present for the package %s\n",
++ rpmteN(ctx->te));
++ goto exit;
++ }
++
++ if (rootSWSource) {
++ /* current is root */
++ root = context->mfx;
++ }
++
++
++ if (rpmteType(ctx->te) == TR_REMOVED) {
++ if (ctx->mfx->sw_source) {
++ if (rpmteDependsOn(ctx->te)) {
++ rpmlog(RPMLOG_INFO, "upgrading %s manifest data\n",
++ rpmteN(ctx->te));
++ } else {
++ rpmlog(RPMLOG_INFO, "removing %s manifest data\n",
++ rpmteN(ctx->te));
++ if (ctx->mfx->define || ctx->mfx->provides || ctx->mfx->sw_sources) {
++ msmRemoveRules(ctx->smack_accesses, ctx->mfx, SmackEnabled);
++ }
++ msmRemoveConfig(ctx->mfx);
++ }
++ }
++
++ }
++
++ exit:
++ current = NULL;
++
++ if (ret) {
++ return RPMRC_FAIL;
++ }
++ return rpmrc;
++}
++
++rpmRC SECURITYHOOK_POST_TSM_FUNC(rpmts _ts)
++{
++
++ packagecontext *ctx = context;
++ if (!ctx) return RPMRC_FAIL;
++ return RPMRC_OK;
++}
++
++static packagecontext *msmFree(packagecontext *ctx)
++{
++
++ while (ctx) {
++ packagecontext *next = ctx->next;
++ msmFreePointer((void**)&ctx->data);
++ ctx->mfx = msmFreeManifestXml(ctx->mfx);
++ if (ctx->smack_accesses) smack_accesses_free(ctx->smack_accesses);
++ msmFreePointer((void**)&ctx);
++ ctx = next;
++ }
++
++ return NULL;
++
++}
++
++rpmRC SECURITYHOOK_CLEANUP_FUNC(void)
++{
++
++ msmFreeInternalHashes(); // free hash structures first
++
++ if (root) {
++ msmSaveDeviceSecPolicyXml(root);
++ if (!rootSWSource) root = msmFreeManifestXml(root);
++ }
++
++ ts = NULL;
++
++ contextsHead = contextsTail = msmFree(contextsHead);
++ contextsHead = contextsTail = NULL;
++
++ if (allfileconflicts) {
++ fileconflict *fc, *temp;
++ HASH_ITER(hh, allfileconflicts, fc, temp) {
++ HASH_DELETE(hh, allfileconflicts, fc);
++ msmFreePointer((void**)&fc->path);
++ msmFreePointer((void**)&fc);
++ }
++ }
++
++ msmFreePointer((void**)&ownSmackLabel);
++ if (cookie) magic_close(cookie);
++
++ return RPMRC_OK;
++}
++
++const char *msmQueryPackageFile(const char *rfor,
++ const char **dname, const char **pname)
++{
++ int match = 0;
++ const char *path = NULL;
++
++ if (ts) {
++ char *sep = strchr(rfor, ':');
++ if (sep && sep[1] == ':' && sep[2] == '/')
++ path = &sep[2];
++ if (!path) return NULL;
++
++ rpmdbMatchIterator mi = rpmtsInitIterator(ts, RPMTAG_BASENAMES, path, 0);
++ if (!mi)
++ mi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, path, 0);
++ if (mi) {
++ Header h;
++ const char *name, *sw_source;
++ while ((h = rpmdbNextIterator(mi))) {
++ rpmdbCheckSignals();
++ name = headerGetString(h, RPMTAG_NAME);
++ sw_source = headerGetString(h, RPMTAG_SECSWSOURCE);
++ if (name && sw_source) {
++ match = !strncmp(rfor, name, path - rfor - 2);
++ rpmlog(RPMLOG_INFO, "file %s belongs to package %s in sw source %s %s\n", path, name, sw_source, (match ? "(matched request)" : ""));
++ if (match) {
++ *pname = xstrdup(name);
++ *dname = xstrdup(sw_source);
++ break;
++ }
++ }
++ }
++ mi = rpmdbFreeIterator(mi);
++ }
++ }
++ return match ? path : NULL;
++}
++
++void msmFreePointer(void** ptr)
++{
++ if (*ptr)
++ free(*ptr);
++ *ptr = NULL;
++ return;
++}
+diff -Nuarp rpm/security/msmconfig.c rpm-security/security/msmconfig.c
+--- rpm/security/msmconfig.c 1970-01-01 02:00:00.000000000 +0200
++++ rpm-security/security/msmconfig.c 2012-10-01 10:29:50.323983642 +0300
+@@ -0,0 +1,264 @@
++/*
++ * This file is part of MSM security plugin
++ * Greatly based on the code of MSSF security plugin
++ *
++ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
++ *
++ * Contact: Ilhan Gurel <ilhan.gurel@nokia.com>
++ *
++ * Copyright (C) 2011 - 2012 Intel Corporation.
++ *
++ * Contact: Elena Reshetova <elena.reshetova@intel.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ */
++
++#include <libxml/tree.h>
++
++#include "rpmio/base64.h"
++
++#include "msm.h"
++
++typedef enum credType_e {
++ CRED_ALLOWMATCHES = 0,
++ CRED_ALLOW = 1,
++ CRED_DENYMATCHES = 2,
++ CRED_DENY = 3,
++ CRED_PROVIDE = 4
++} credType;
++
++/**
++ * Serializes key data
++ * @todo Problem with getting keydata
++ * @param parent XML node
++ * @param keyinfo keyinfo structure
++ * @return none
++ */
++static void msmHandleKeyinfo(xmlNode *parent, keyinfo_x *keyinfo)
++{
++ char *enc = NULL;
++
++ if (!parent)
++ return;
++
++ while (keyinfo) {
++ xmlNode *node = xmlNewNode(NULL, BAD_CAST "keyinfo");
++
++ /* b64 encode keydata first */
++ if ((enc = b64encode(keyinfo->keydata, keyinfo->keylen, -1)) != NULL) {
++ xmlAddChild(node, xmlNewText(BAD_CAST "\n"));
++ xmlAddChild(node, xmlNewText(BAD_CAST enc));
++ msmFreePointer((void**)&enc);
++ }
++
++ xmlAddChild(parent, node);
++ keyinfo = keyinfo->prev;
++ }
++}
++
++/**
++ * Serializes ac_domain data
++ * @param parent XML node
++ * @param type Type (allow, deny,..)
++ * @param ac_domain ac_domain structure
++ * @return none
++ */
++static void msmHandleACDomains(xmlNode *parent, credType type,
++ ac_domain_x *ac_domain)
++{
++ if (!ac_domain || !parent)
++ return;
++
++ xmlNode *node = NULL;
++
++ if ((type == CRED_ALLOWMATCHES) || (type == CRED_ALLOW)) {
++ node = xmlNewNode(NULL, BAD_CAST "allow");
++ } else if ((type == CRED_DENYMATCHES) || (type == CRED_DENY)) {
++ node = xmlNewNode(NULL, BAD_CAST "deny");
++ } else if (type == CRED_PROVIDE) {
++ node = parent;
++ } else {
++ return;
++ }
++
++ while (ac_domain) {
++ xmlNode *childnode = xmlNewNode(NULL, BAD_CAST "ac_domain");
++ if ((type == CRED_ALLOWMATCHES) || (type == CRED_DENYMATCHES)) {
++ xmlNewProp(childnode, BAD_CAST "match", BAD_CAST ac_domain->match);
++ } else {
++ xmlNewProp(childnode, BAD_CAST "name", BAD_CAST ac_domain->name);
++ if (ac_domain->type)
++ xmlNewProp(childnode, BAD_CAST "policy", BAD_CAST ac_domain->type);
++ if (ac_domain->plist)
++ xmlNewProp(childnode, BAD_CAST "plist", BAD_CAST ac_domain->plist);
++ }
++ xmlAddChild(node, childnode);
++ if (type == CRED_ALLOW || type == CRED_DENY)
++ ac_domain = ac_domain->hh.next;
++ else
++ ac_domain = ac_domain->prev;
++ }
++
++ if (type != CRED_PROVIDE)
++ xmlAddChild(parent, node);
++}
++
++/**
++ * Serializes origin data
++ * @param parent XML node
++ * @param origin origin structure
++ * @return none
++ */
++static void msmHandleOrigin(xmlNode *parent, origin_x *origin)
++{
++ if (!parent)
++ return;
++
++ while (origin) {
++ xmlNode *node = xmlNewNode(NULL, BAD_CAST "origin");
++ xmlAddChild(parent, node);
++ msmHandleKeyinfo(node, origin->keyinfos);
++ origin = origin->prev;
++ }
++}
++
++/**
++ * Serializes provides data
++ * @param parent XML node
++ * @param provide provide structure
++ * @return none
++ */
++static void msmHandleProvide(xmlNode *parent, provide_x *provide)
++{
++ if (!parent)
++ return;
++
++ while (provide) {
++ if (provide->ac_domains) {
++ xmlNode *node = xmlNewNode(NULL, BAD_CAST "provide");
++ xmlAddChild(parent, node);
++ msmHandleACDomains(node, CRED_PROVIDE, provide->ac_domains);
++ if (provide->origin) {
++ xmlNode *childnode = xmlNewNode(NULL, BAD_CAST "for");
++ xmlNewProp(childnode, BAD_CAST "origin", BAD_CAST provide->origin);
++ xmlAddChild(node, childnode);
++ }
++ }
++ provide = provide->prev;
++ }
++}
++
++/**
++ * Serializes packages data
++ * @param parent XML node
++ * @param package package structure
++ * @return none
++ */
++static void msmHandlePackage(xmlNode *parent, package_x *package)
++{
++ if (!parent)
++ return;
++
++ while (package) {
++ if (!package->newer) {
++ xmlNode *node = xmlNewNode(NULL, BAD_CAST "package");
++ xmlNewProp(node, BAD_CAST "name", BAD_CAST package->name);
++ if (package->modified)
++ xmlNewProp(node, BAD_CAST "modified", BAD_CAST package->modified);
++ xmlAddChild(parent, node);
++ msmHandleProvide(node, package->provides);
++ }
++ package = package->prev;
++ }
++}
++
++/**
++ * Serializes sw source data
++ * @param parent XML node
++ * @param sw_source sw_source structure
++ * @return none
++ */
++static void msmHandleSWSource(xmlNode *parent, sw_source_x *sw_source)
++{
++ #define MAX_DEPTH 10
++ xmlNode *node[MAX_DEPTH];
++ sw_source_x *temp;
++ int depth = 0;
++
++ if (!sw_source || !parent)
++ return;
++
++ node[0] = parent;
++
++ while (sw_source) {
++ depth = 1; /* recalculate depth */
++ for (temp = sw_source->parent; temp; temp = temp->parent) depth++;
++ if (!sw_source->newer && depth < MAX_DEPTH) {
++ node[depth] = xmlNewNode(NULL, BAD_CAST "sw_source");
++ xmlNewProp(node[depth], BAD_CAST "name", BAD_CAST sw_source->name);
++ xmlNewProp(node[depth], BAD_CAST "rankkey", BAD_CAST sw_source->rankkey);
++ xmlAddChild(node[depth-1], node[depth]);
++ msmHandleOrigin(node[depth], sw_source->origins);
++ msmHandleACDomains(node[depth], CRED_ALLOWMATCHES, sw_source->allowmatches);
++ msmHandleACDomains(node[depth], CRED_ALLOW, sw_source->allows);
++ msmHandleACDomains(node[depth], CRED_DENYMATCHES, sw_source->denymatches);
++ msmHandleACDomains(node[depth], CRED_DENY, sw_source->denys);
++ msmHandlePackage(node[depth], sw_source->packages);
++ if (sw_source->older) {
++ /* packages still belong to this sw_source */
++ msmHandlePackage(node[depth], sw_source->older->packages);
++ }
++ }
++ sw_source = sw_source->next;
++ }
++}
++
++/**
++ * Saves sw_source configuration into /etc/dev-sec-policy.
++ * @param mfx data to serialize
++ * @return RPMRC_OK or RPMRC_FAIL
++ */
++rpmRC msmSaveDeviceSecPolicyXml(manifest_x *mfx)
++{
++ FILE *outFile;
++ rpmRC rc = RPMRC_OK;
++
++ /* if data doesn't have sw_source information, no need to do anything */
++ if (mfx && mfx->sw_sources) {
++ sw_source_x *sw_source;
++ xmlDoc *doc = xmlNewDoc( BAD_CAST "1.0");
++ xmlNode *rootnode = xmlNewNode(NULL, BAD_CAST "config");
++ xmlDocSetRootElement(doc, rootnode);
++
++ LISTHEAD(mfx->sw_sources, sw_source);
++ msmHandleSWSource(rootnode, sw_source);
++
++ outFile = fopen(DEVICE_SECURITY_POLICY, "w");
++ if (outFile) {
++ xmlElemDump(outFile, doc, rootnode);
++ fclose(outFile);
++ } else {
++ rpmlog(RPMLOG_ERR, "Unable to write device security policy%s\n",
++ DEVICE_SECURITY_POLICY);
++ rc = RPMRC_FAIL;
++ }
++ xmlFreeDoc(doc);
++ xmlCleanupParser();
++ }
++
++ return rc;
++}
++
+diff -Nuarp rpm/security/msm.h rpm-security/security/msm.h
+--- rpm/security/msm.h 1970-01-01 02:00:00.000000000 +0200
++++ rpm-security/security/msm.h 2012-10-01 10:29:50.323983642 +0300
+@@ -0,0 +1,469 @@
++/*
++ * This file is part of MSM security plugin
++ * Greatly based on the code of MSSF security plugin
++ *
++ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
++ *
++ * Contact: Tero Aho <ext-tero.aho@nokia.com>
++ *
++ * Copyright (C) 2011 - 2012 Intel Corporation.
++ *
++ * Contact: Elena Reshetova <elena.reshetova@intel.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ */
++
++#ifndef MSM_H
++#define MSM_H
++
++#include "security.h"
++
++#define IMA "security.ima"
++#define SMACK64TRANSMUTE "security.SMACK64TRANSMUTE"
++#define SMACK64 "security.SMACK64"
++#define SMACK64EXEC "security.SMACK64EXEC"
++
++#define SMACK_RULES_PATH "/etc/smack/accesses.d/"
++#define SMACK_RULES_PATH_BEG "/etc/smack/"
++#define DEVICE_SECURITY_POLICY "/etc/device-sec-policy"
++#define SMACK_LOAD_PATH "/smack/load"
++
++#define SMACK_ISOLATED_LABEL "Isolated"
++
++#define SMACK_LABEL_LENGTH 255
++#define SMACK_ACCESS_TYPE_LENGHT 5
++#define SMACK_UNINSTALL 1
++#define RANK_LIMIT 10000
++
++#define DBUS_SERVICE 1
++#define DBUS_PATH 2
++#define DBUS_INTERFACE 3
++#define DBUS_METHOD 4
++#define DBUS_SIGNAL 5
++
++#include <uthash.h>
++#include <sys/capability.h>
++#include <sys/smack.h>
++#include <magic.h>
++
++/** \ingroup msm
++ * List definitions.
++ * All lists are doubly-linked, the last element is stored to list pointer,
++ * which means that lists must be looped using the prev pointer, or by
++ * calling LISTHEAD first to go to start in order to use the next pointer.
++ */
++#define LISTADD(list, node) \
++ do { \
++ (node)->prev = (list); \
++ if (list) (node)->next = (list)->next; \
++ else (node)->next = NULL; \
++ if (list) (list)->next = (node); \
++ (list) = (node); \
++ } while (0);
++
++#define NODEADD(node1, node2) \
++ do { \
++ (node2)->prev = (node1); \
++ (node2)->next = (node1)->next; \
++ if ((node1)->next) (node1)->next->prev = (node2); \
++ (node1)->next = (node2); \
++ } while (0);
++
++#define LISTCAT(list, first, last) \
++ if ((first) && (last)) { \
++ (first)->prev = (list); \
++ (list) = (last); \
++ }
++
++#define LISTDEL(list, node) \
++ do { \
++ if ((node)->prev) (node)->prev->next = (node)->next; \
++ if ((node)->next) (node)->next->prev = (node)->prev; \
++ if (!((node)->prev) && !((node)->next)) (list) = NULL; \
++ } while (0);
++
++#define LISTHEAD(list, node) \
++ for ((node) = (list); (node)->prev; (node) = (node)->prev);
++
++#define LISTTAIL(list, node) \
++ for ((node) = (list); (node)->next; (node) = (node)->next);
++
++/** \ingroup msm
++ * Structure definitions.
++ * These structures represent the parsed security manifest of a package.
++ */
++
++
++typedef struct file_x {
++ const char *path; /* file path */
++ ino_t ino; /* file inode */
++ unsigned char digest[SHA1_LENGTH];
++ struct file_x *prev;
++ struct file_x *next;
++} file_x;
++
++typedef struct filesystem_x {
++ const char *path; /* filesystem object absolute path */
++ const char *label; /* SMACK64 xattr */
++ const char *exec_label; /* SMACK64EXEC xattr */
++ const char *type; /* can be set as TRANSMUTABLE for directory */
++ struct filesystem_x *prev;
++ struct filesystem_x *next;
++ } filesystem_x;
++
++typedef struct ac_domain_x { /* structure for storing ac domain */
++ const char *name; /* ac domain name */
++ const char *match;
++ const char *type; /* ac domain policy type: "shared" or "restricted" or "NULL" (private) */
++ const char *plist; /* list of packages that allowed to request domain, if policy is "restricted" */
++ const char *pkg_name; /* package that defined ac domain */
++ struct ac_domain_x *prev;
++ struct ac_domain_x *next;
++ struct sw_source_x *sw_source; /* sw source of the package that defined the domain */
++ const char *origin;
++ UT_hash_handle hh;
++ int allowed;
++ struct ac_domain_x *older; /* previous version in upgrades */
++ struct ac_domain_x *newer; /* the newer upgraded version */
++} ac_domain_x;
++
++typedef struct annotation_x {
++ const char *name;
++ const char *value;
++} annotation_x;
++
++typedef struct member_x {
++ int type;
++ const char *name;
++ struct annotation_x *annotation;
++ struct member_x *prev;
++ struct member_x *next;
++} member_x;
++
++typedef struct interface_x {
++ const char *name;
++ struct annotation_x *annotation;
++ struct member_x *members;
++ struct interface_x *prev;
++ struct interface_x *next;
++} interface_x;
++
++typedef struct node_x {
++ const char *name;
++ struct annotation_x *annotation;
++ struct member_x *members;
++ struct interface_x *interfaces;
++ struct node_x *prev;
++ struct node_x *next;
++} node_x;
++
++typedef struct dbus_x {
++ const char *name;
++ const char *own;
++ const char *bus;
++ struct annotation_x *annotation;
++ struct node_x *nodes;
++ struct dbus_x *prev;
++ struct dbus_x *next;
++} dbus_x;
++
++typedef struct provide_x {
++ const char *name; /* _system_ or NULL */
++ struct ac_domain_x *ac_domains;
++ struct filesystem_x *filesystems;
++ struct dbus_x *dbuss;
++ const char *origin;
++ struct provide_x *prev;
++ struct provide_x *next;
++} provide_x;
++
++typedef struct request_x {
++ const char *ac_domain;
++} request_x;
++
++typedef struct keyinfo_x {
++ const unsigned char *keydata;
++ size_t keylen;
++ struct keyinfo_x *prev;
++ struct keyinfo_x *next;
++} keyinfo_x;
++
++typedef struct access_x {
++ const char *data;
++ const char *type;
++ struct access_x *prev;
++ struct access_x *next;
++} access_x;
++
++typedef struct origin_x {
++ const char *type;
++ struct keyinfo_x *keyinfos;
++ struct access_x *accesses;
++ struct origin_x *prev;
++ struct origin_x *next;
++} origin_x;
++
++typedef struct constraint_x {
++ const char *name;
++ const char *value;
++ struct constraint_x *prev;
++ struct constraint_x *next;
++} constraint_x;
++
++typedef struct d_request_x {
++ const char *label_name;
++ const char *ac_type;
++ struct d_request_x *prev;
++ struct d_request_x *next;
++} d_request_x;
++
++typedef struct d_permit_x {
++ const char *label_name;
++ const char *to_label_name;
++ const char *ac_type;
++ struct d_permit_x *prev;
++ struct d_permit_x *next;
++} d_permit_x;
++
++typedef struct d_provide_x {
++ const char *label_name;
++ struct d_provide_x *prev;
++ struct d_provide_x *next;
++} d_provide_x;
++
++typedef struct define_x {
++ const char *name; /* ac domain name */
++ const char *policy;
++ const char *plist; /* list of packages that are allowed to request the ac domain */
++ struct d_request_x *d_requests;
++ struct d_permit_x *d_permits;
++ struct d_provide_x *d_provides;
++} define_x;
++
++typedef struct package_x {
++ const char *name; /* package name */
++ struct sw_source_x *sw_source; /* package sw source */
++ struct provide_x *provides;
++ const char *modified; /* internal packages */
++ struct package_x *prev;
++ struct package_x *next;
++ UT_hash_handle hh;
++ struct package_x *older; /* previous version in upgrades */
++ struct package_x *newer; /* the newer upgraded version */
++} package_x;
++
++typedef struct sw_source_x {
++ const char *name;
++ const char *rankkey;
++ struct package_x *packages; /* config processing */
++ struct ac_domain_x *allowmatches; /* list of allow wildcards */
++ struct ac_domain_x *allows; /* hash of allowed ac domains */
++ struct ac_domain_x *denymatches; /* list of deny wildcards */
++ struct ac_domain_x *denys; /* hash of denied ac domains */
++ struct origin_x *origins;
++ struct sw_source_x *prev;
++ struct sw_source_x *next;
++ struct sw_source_x *parent;
++ struct sw_source_x *older; /* previous version in upgrades */
++ struct sw_source_x *newer; /* the newer upgraded version */
++} sw_source_x;
++
++typedef struct manifest_x { /*package manifest */
++ struct sw_source_x *sw_source; /* package sw source */
++ const char *name; /* package name */
++ struct provide_x *provides; /* assign section */
++ struct request_x *request; /* request section */
++ struct sw_source_x *sw_sources; /*defined software sources(non-NULL only for configuration manifests)*/
++ struct define_x *define; /* define section */
++ struct file_x *files; /* installed files */
++} manifest_x;
++
++/** \ingroup msm
++ * Frees the given pointer and sets it to NULL
++ * @param ptr address of pointer to be freed
++ * @return
++ */
++void msmFreePointer(void **ptr);
++
++/** \ingroup msm
++ * Process package security manifest.
++ * @param buffer xml data buffer
++ * @param size buffer length
++ * @param current sw source for package
++ * @param packagename name of the package
++ * @return pointer to structure on success
++ */
++manifest_x *msmProcessManifestXml(const char *buffer, int size, sw_source_x *current, const char *packagename);
++
++/** \ingroup msm
++ * Process device security policy file.
++ * @param filename file name
++ * @return pointer to structure on success
++ */
++manifest_x *msmProcessDevSecPolicyXml(const char *filename);
++
++/** \ingroup msm
++ * Free all structures reserved during manifest processing.
++ * @param mfx pointer to structure
++ */
++manifest_x* msmFreeManifestXml(manifest_x * mfx);
++
++/** \ingroup msm
++ * Go through all sw sources in manifest, import keys to RPM keyring.
++ * @param smack_accesses smack_accesses handle for setting smack rules
++ * @param mfx package manifest
++ * @param ts rpm transaction set
++ * @return 0 on success, else -1
++ */
++int msmSetupSWSources(struct smack_accesses *smack_accesses, manifest_x *mfx, rpmts ts);
++
++
++/** \ingroup msm
++ * Create package structure for package being installed.
++ * @param name package name
++ * @param sw_source package sw source
++ * @param provides provided ac domains
++ * @param modified for internal packages
++ * @return allocated and initialized package struct
++ */
++package_x *msmCreatePackage(const char *name, sw_source_x *sw_source, provide_x *provides, const char *modified);
++
++/** \ingroup msm
++ * Go through all provides in manifest, add provided ac domains to hash.
++ * @param packages pointer to packages list
++ * @param sw_source link to sw source in device security policy
++ * @param rule_set rule set for setting smack rules
++ * @return 0 on success, else -1
++ */
++int msmSetupPackages(struct smack_accesses *smack_accesses, package_x *packages, sw_source_x *sw_source);
++
++/** \ingroup msm
++ * Setup define section of manifest
++ * @param smack_accesses smack_accesses handle for setting smack rules
++ * @param mfx package manifest
++ * @return 0 on success, else -1
++ */
++int msmSetupDefine(struct smack_accesses *smack_accesses, manifest_x *mfx);
++
++/** \ingroup msm
++ * Setup smack rules according to the manifest
++ * @param smack_accesses smack_accesses handle for setting smack rules
++ * @param package_name package name
++ * @param flag flag to indicate installation or uninstallation
++ * @param SmackEnabled flag to indicate Smack presence in the kernel
++ * @return 0 on success, else -1
++ */
++int msmSetupSmackRules(struct smack_accesses *smack_accesses, const char* package_name, int flag, int SmackEnabled);
++
++/** \ingroup msm
++ * Check previous installation of package.
++ * @param name package name
++ * @return package or NULL
++ */
++package_x *msmCheckPackage(const char *name);
++
++/** \ingroup msm
++ * Cancel the installation of package (rules and config data).
++ * @param name package name
++ */
++void msmCancelPackage(const char *name);
++
++/** \ingroup msm
++ * Free package structure.
++ * @param package package
++ * @return next package in list or NULL
++ */
++package_x *msmFreePackage(package_x *package);
++
++/** \ingroup msm
++ * Set extended attributes of the file based on manifest.
++ * @param mfx package manifest
++ * @param filepath path of the file
++ * @param cookie magic cookie
++ * @return 0 on success, else -1
++ */
++int msmSetFileXAttributes(manifest_x *mfx, const char* filepath, magic_t cookie);
++
++/** \ingroup msm
++ * Set setup the request section of manifest.
++ * @param mfx package manifest
++ * @return 0 on success, else -1
++ */
++int msmSetupRequests(manifest_x *mfx);
++
++/** \ingroup msm
++ * Package is removed, remove all related Smack rules.
++ * @param mfx package manifest
++ * @param smack_accesses smack_accesses handle for setting smack rules
++ * @param SmackEnabled flag to indicate Smack presence in the kernel
++ */
++void msmRemoveRules(struct smack_accesses *smack_accesses, manifest_x *mfx, int SmackEnabled);
++
++/** \ingroup msm
++ * Setup DBus policies for package
++ * @param package package
++ */
++int msmSetupDBusPolicies(package_x *package);
++
++
++/** \ingroup msm
++ * Package is removed, remove related data in device security policy.
++ * @param mfx package manifest
++ */
++void msmRemoveConfig(manifest_x *mfx);
++
++/** \ingroup msm
++ * String compare which allows wildcards (* and ?) in s2.
++ * @param s1 string to compare
++ * @param s2 string to compare
++ * @return 0 if s1 matches s2
++ */
++int strwcmp(const char *s1, const char *s2);
++
++/** \ingroup msm
++ * Saves configuration into /etc/dev-sec-policy.
++ * @param mfx data to serialize
++ * @return RPMRC_OK or RPMRC_FAIL
++ */
++rpmRC msmSaveDeviceSecPolicyXml(manifest_x *root);
++
++/** \ingroup msm
++ * Depth first tree traversal for sw source tree.
++ * @param sw_sources sw source tree
++ * @param func function to call for each sw source until 0 is returned
++ * @param param parameter for the function
++ * @return matching sw source or NULL
++ */
++sw_source_x *msmSWSourceTreeTraversal(sw_source_x *sw_sources, int (func)(sw_source_x *, void *), void *param);
++
++/** \ingroup msm
++ * Free internal hashes.
++ */
++void msmFreeInternalHashes(void);
++
++/** \ingroup msm
++ * Query that requested package really owns the file.
++ * @param rfor request for 'package::/file/path'
++ * @param sw_sname sw source name, caller must free
++ * @param pname package name, caller must free
++ * @return pointer to the path part in rfor, or NULL if file
++ * is not owned by the specified package
++ */
++const char *msmQueryPackageFile(const char *rfor,
++ const char **sw_sname, const char **pname);
++
++
++#endif
+diff -Nuarp rpm/security/msmmanifest.c rpm-security/security/msmmanifest.c
+--- rpm/security/msmmanifest.c 1970-01-01 02:00:00.000000000 +0200
++++ rpm-security/security/msmmanifest.c 2012-10-01 10:29:50.323983642 +0300
+@@ -0,0 +1,1500 @@
++/*
++ * This file is part of MSM security plugin
++ * Greatly based on the code of MSSF security plugin
++ *
++ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
++ *
++ * Contact: Tero Aho <ext-tero.aho@nokia.com>
++ *
++ * Copyright (C) 2011 -2012 Intel Corporation.
++ *
++ * Contact: Elena Reshetova <elena.reshetova@intel.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdarg.h>
++#include <string.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <unistd.h>
++
++#include <libxml/xmlreader.h>
++#include <sys/capability.h>
++
++#include "msm.h"
++
++#include "rpmio/base64.h"
++
++/* We'll support only the basic set of characters */
++#define ASCII(s) (const char *)s
++#define XMLCHAR(s) (const xmlChar *)s
++
++
++static int msmVerifyAccessType(const char* type)
++{
++ int res = 0, idx = 0;
++
++ if (type) {
++ if (strlen(type) > SMACK_ACCESS_TYPE_LENGHT) {
++ rpmlog(RPMLOG_ERR, "Lenght of the access type is bigger than allowed value: %s\n", type);
++ return -1;
++ }
++ while ( type[idx] != '\0' ){
++ if ((type[idx] !='a') && (type[idx]!='r') && (type[idx]!='w') &&
++ (type[idx]!='x') && (type[idx]!='t') && (type[idx] !='-')) {
++ rpmlog(RPMLOG_ERR, "Not allowed character in access type: %s\n", type);
++ res = -1;
++ break;
++ }
++ idx++;
++ }
++ } else return -1;
++ return res;
++}
++
++static int msmVerifySmackLabel(const char* label)
++{
++ int res = 0, idx = 0;
++
++ if (label) {
++ if (strlen(ASCII(label)) > SMACK_LABEL_LENGTH) { //smack limitation on lenght
++ rpmlog(RPMLOG_ERR, "Domain or label name %s lenght is longer than defined SMACK_LABEL_LENGTH\n", label);
++ return -1;
++ }
++ if (strlen(ASCII(label)) == 0){
++ rpmlog(RPMLOG_ERR, "An attempt to define an empty domain or label name\n");
++ return -1;
++ }
++ if (label[0] == '-') {
++ rpmlog(RPMLOG_ERR, "Dash is not allowed as first character in smack label: %s\n", label);
++ return -1;
++ }
++ while ( label[idx] != '\0' ){
++ if ((label[idx] =='\"') || (label[idx] =='\'') || (label[idx] =='/') ||
++ (label[idx] =='\\') || (label[idx] > '~') || (label[idx] <= ' ')) {
++ rpmlog(RPMLOG_ERR, "Not allowed character in smack label: %s, position: %d \n", label, idx);
++ res = -1;
++ break;
++ }
++ idx++;
++ }
++ } else return -1;
++
++ return res;
++}
++
++static int msmVerifyLabelPrefix(const char* sub_label, const char* domain_name)
++{
++ char *tmp = NULL;
++ char sep[]= "::";
++
++ tmp = calloc(strlen(domain_name) + 3, sizeof (const char));
++ if (!tmp)
++ return -1;
++
++ strncpy(tmp, domain_name, strlen(domain_name));
++ strncpy(tmp + strlen(domain_name), sep, 2);
++
++ if (strstr(ASCII(sub_label), tmp) != ASCII(sub_label)) { //sub label name should be prefixed by domain name and "::"
++ rpmlog(RPMLOG_ERR, "Label name %s isn't prefixed by domain name %s\n", ASCII(sub_label), domain_name);
++ msmFreePointer((void**)&tmp);
++ return -1;
++ }
++
++ msmFreePointer((void**)&tmp);
++ return 0;
++
++}
++
++static int msmNextChildElement(xmlTextReaderPtr reader, int depth)
++{
++ int ret = xmlTextReaderRead(reader);
++ int cur = xmlTextReaderDepth(reader);
++ while (ret == 1) {
++ /*
++ rpmlog(RPMLOG_DEBUG, "node %s %d\n",
++ ASCII(xmlTextReaderConstName(reader)),
++ xmlTextReaderDepth(reader));
++ */
++ switch (xmlTextReaderNodeType(reader)) {
++ case XML_READER_TYPE_ELEMENT:
++ case XML_READER_TYPE_TEXT:
++ if (cur == depth+1)
++ return 1;
++ break;
++ case XML_READER_TYPE_END_ELEMENT:
++ if (cur == depth)
++ return 0;
++ break;
++ default:
++ if (cur <= depth)
++ return 0;
++ break;
++ }
++ ret = xmlTextReaderRead(reader);
++ cur = xmlTextReaderDepth(reader);
++ }
++ return ret;
++}
++
++static ac_domain_x *msmFreeACDomain(ac_domain_x *ac_domain)
++{
++ if (ac_domain) {
++ ac_domain_x *prev = ac_domain->prev;
++ msmFreePointer((void**)&ac_domain->name);
++ msmFreePointer((void**)&ac_domain->type);
++ msmFreePointer((void**)&ac_domain->match);
++ msmFreePointer((void**)&ac_domain->plist);
++ msmFreePointer((void**)&ac_domain);
++ return prev;
++ } else return NULL;
++}
++
++static annotation_x *msmProcessAnnotation(xmlTextReaderPtr reader)
++{
++ const xmlChar *name, *value;
++
++ name = xmlTextReaderGetAttribute(reader, XMLCHAR("name"));
++ value = xmlTextReaderGetAttribute(reader, XMLCHAR("value"));
++ rpmlog(RPMLOG_DEBUG, "annotation %s %s\n", ASCII(name), ASCII(value));
++
++ if (name && value) {
++ annotation_x *annotation = calloc(1, sizeof(annotation_x));
++ if (annotation) {
++ annotation->name = ASCII(name);
++ annotation->value = ASCII(value);
++ return annotation;
++ }
++ }
++ msmFreePointer((void**)&name);
++ msmFreePointer((void**)&value);
++ return NULL;
++}
++
++static int msmProcessMember(xmlTextReaderPtr reader, member_x *member)
++{
++ const xmlChar *node, *name;
++ int ret, depth;
++
++ name = xmlTextReaderGetAttribute(reader, XMLCHAR("name"));
++ rpmlog(RPMLOG_DEBUG, "member %s\n", ASCII(name));
++ member->name = ASCII(name);
++
++ if (!name) return -1;
++
++ depth = xmlTextReaderDepth(reader);
++ while ((ret = msmNextChildElement(reader, depth))) {
++ node = xmlTextReaderConstName(reader);
++ if (!node) return -1;
++
++ if (!strcmp(ASCII(node), "annotation")) {
++ annotation_x *annotation = msmProcessAnnotation(reader);
++ if (annotation) {
++ member->annotation = annotation;
++ } else return -1;
++ } else return -1;
++
++ if (ret < 0) return -1;
++ }
++ return ret;
++}
++
++static int msmProcessInterface(xmlTextReaderPtr reader, interface_x *interface)
++{
++ const xmlChar *node, *name;
++ int ret, depth;
++
++ name = xmlTextReaderGetAttribute(reader, XMLCHAR("name"));
++ rpmlog(RPMLOG_DEBUG, "interface %s\n", ASCII(name));
++ interface->name = ASCII(name);
++
++ if (!name) return -1;
++
++ depth = xmlTextReaderDepth(reader);
++ while ((ret = msmNextChildElement(reader, depth))) {
++ node = xmlTextReaderConstName(reader);
++ if (!node) return -1;
++
++ if (!strcmp(ASCII(node), "method")) {
++ member_x *member = calloc(1, sizeof(member_x));
++ if (member) {
++ member->type = DBUS_METHOD;
++ ret = msmProcessMember(reader, member);
++ LISTADD(interface->members, member);
++ } else return -1;
++ } else if (!strcmp(ASCII(node), "signal")) {
++ member_x *member = calloc(1, sizeof(member_x));
++ if (member) {
++ member->type = DBUS_SIGNAL;
++ ret = msmProcessMember(reader, member);
++ LISTADD(interface->members, member);
++ } else return -1;
++ } else if (!strcmp(ASCII(node), "annotation")) {
++ annotation_x *annotation = msmProcessAnnotation(reader);
++ if (annotation) {
++ interface->annotation = annotation;
++ } else return -1;
++ } else return -1;
++
++ if (ret < 0) return -1;
++ }
++ return ret;
++}
++
++static int msmProcessNode(xmlTextReaderPtr reader, node_x *nodex)
++{
++ const xmlChar *node, *name;
++ int ret, depth;
++
++ name = xmlTextReaderGetAttribute(reader, XMLCHAR("name"));
++ rpmlog(RPMLOG_DEBUG, "node %s\n", ASCII(name));
++ nodex->name = ASCII(name);
++
++ if (!name) return -1;
++
++ depth = xmlTextReaderDepth(reader);
++ while ((ret = msmNextChildElement(reader, depth))) {
++ node = xmlTextReaderConstName(reader);
++ if (!node) return -1;
++
++ if (!strcmp(ASCII(node), "interface")) {
++ interface_x *interface = calloc(1, sizeof(interface_x));
++ if (interface) {
++ ret = msmProcessInterface(reader, interface);
++ LISTADD(nodex->interfaces, interface);
++ } else return -1;
++ } else if (!strcmp(ASCII(node), "method")) {
++ member_x *member = calloc(1, sizeof(member_x));
++ if (member) {
++ member->type = DBUS_METHOD;
++ ret = msmProcessMember(reader, member);
++ LISTADD(nodex->members, member);
++ } else return -1;
++ } else if (!strcmp(ASCII(node), "signal")) {
++ member_x *member = calloc(1, sizeof(member_x));
++ if (member) {
++ member->type = DBUS_SIGNAL;
++ ret = msmProcessMember(reader, member);
++ LISTADD(nodex->members, member);
++ } else return -1;
++ } else if (!strcmp(ASCII(node), "annotation")) {
++ annotation_x *annotation = msmProcessAnnotation(reader);
++ if (annotation) {
++ nodex->annotation = annotation;
++ } else return -1;
++ } else return -1;
++
++ if (ret < 0) return -1;
++ }
++ return ret;
++}
++
++static int msmProcessDBus(xmlTextReaderPtr reader, dbus_x *dbus)
++{
++ const xmlChar *node, *name, *own, *bus;
++ int ret, depth;
++
++ name = xmlTextReaderGetAttribute(reader, XMLCHAR("name"));
++ own = xmlTextReaderGetAttribute(reader, XMLCHAR("own"));
++ bus = xmlTextReaderGetAttribute(reader, XMLCHAR("bus"));
++ rpmlog(RPMLOG_DEBUG, "dbus %s %s %s\n", ASCII(name), ASCII(own), ASCII(bus));
++ dbus->name = ASCII(name);
++ dbus->own = ASCII(own);
++ dbus->bus = ASCII(bus);
++
++ if (!name || !bus) return -1;
++ if (strcmp(dbus->bus, "session") && strcmp(dbus->bus, "system"))
++ return -1;
++
++ depth = xmlTextReaderDepth(reader);
++ while ((ret = msmNextChildElement(reader, depth))) {
++ node = xmlTextReaderConstName(reader);
++ if (!node) return -1;
++
++ if (!strcmp(ASCII(node), "node")) {
++ node_x *nodex = calloc(1, sizeof(node_x));
++ if (nodex) {
++ ret = msmProcessNode(reader, nodex);
++ LISTADD(dbus->nodes, nodex);
++ } else return -1;
++ } else if (!strcmp(ASCII(node), "annotation")) {
++ annotation_x *annotation = msmProcessAnnotation(reader);
++ if (annotation) {
++ dbus->annotation = annotation;
++ } else return -1;
++ } else return -1;
++
++ if (ret < 0) return -1;
++ }
++ return ret;
++}
++
++static ac_domain_x *msmProcessACDomain(xmlTextReaderPtr reader, sw_source_x *sw_source, const char* pkg_name)
++{
++ const xmlChar *name, *match, *policy, *plist;
++
++ name = xmlTextReaderGetAttribute(reader, XMLCHAR("name"));
++ match = xmlTextReaderGetAttribute(reader, XMLCHAR("match"));
++ policy = xmlTextReaderGetAttribute(reader, XMLCHAR("policy"));
++ plist = xmlTextReaderGetAttribute(reader, XMLCHAR("plist"));
++ rpmlog(RPMLOG_DEBUG, "ac_domain %s match %s policy %s plist %s\n", ASCII(name), ASCII(match), ASCII(policy), ASCII(plist));
++
++ if (!((!name && !match) || (name && match))) {
++ ac_domain_x *ac_domain = calloc(1, sizeof(ac_domain_x));
++ if (ac_domain) {
++ ac_domain->name = ASCII(name);
++ ac_domain->match = ASCII(match);
++ ac_domain->type = ASCII(policy);
++ ac_domain->plist = ASCII(plist);
++ ac_domain->sw_source = sw_source;
++ ac_domain->pkg_name = pkg_name;
++ return ac_domain;
++ }
++ }
++ rpmlog(RPMLOG_ERR, "Mandatory argument is missing for ac domain definition\n");
++ rpmlog(RPMLOG_ERR, "ac_domain %s match %s policy %s plist %s\n", ASCII(name), ASCII(match), ASCII(policy), ASCII(plist));
++ msmFreePointer((void**)&name);
++ msmFreePointer((void**)&match);
++ msmFreePointer((void**)&policy);
++ msmFreePointer((void**)&plist);
++ return NULL;
++}
++
++static filesystem_x *msmProcessFilesystem(xmlTextReaderPtr reader)
++{
++ const xmlChar *path, *label, *type, *exec_label;
++
++ path = xmlTextReaderGetAttribute(reader, XMLCHAR("path"));
++ label = xmlTextReaderGetAttribute(reader, XMLCHAR("label"));
++ exec_label = xmlTextReaderGetAttribute(reader, XMLCHAR("exec_label"));
++ type = xmlTextReaderGetAttribute(reader, XMLCHAR("type"));
++
++ rpmlog(RPMLOG_DEBUG, "filesystem path %s label %s exec label %s type %s\n",
++ ASCII(path), ASCII(label), ASCII(exec_label), ASCII(type));
++
++ if (path && (label || exec_label)) {
++ if ((label) && (msmVerifySmackLabel(ASCII(label)) < 0)) {
++ goto fail;
++ }
++ if ((exec_label) && (msmVerifySmackLabel(ASCII(exec_label)) < 0)) {
++ goto fail;
++ }
++
++ filesystem_x *filesystem = calloc(1, sizeof(filesystem_x));
++ if (filesystem) {
++ filesystem->path = ASCII(path);
++ filesystem->label = ASCII(label);
++ filesystem->exec_label = ASCII(exec_label);
++ filesystem->type = ASCII(type);
++ return filesystem;
++ }
++
++ } else {
++ rpmlog(RPMLOG_ERR, "Mandatory argument is missing for filesystem assign request\n");
++ rpmlog(RPMLOG_ERR, "filesystem path %s label %s exec label %s\n",
++ ASCII(path), ASCII(label), ASCII(exec_label));
++ }
++
++fail:
++ msmFreePointer((void**)&path);
++ msmFreePointer((void**)&label);
++ msmFreePointer((void**)&exec_label);
++ msmFreePointer((void**)&type);
++ return NULL;
++}
++
++static int msmProcessProvide(xmlTextReaderPtr reader, provide_x *provide, sw_source_x *current, manifest_x *mfx, const char* pkg_name)
++{
++ const xmlChar *node, *name, *origin;
++ int ret, depth;
++
++ name = xmlTextReaderGetAttribute(reader, XMLCHAR("name"));
++ rpmlog(RPMLOG_DEBUG, "assign %s\n", ASCII(name));
++ provide->name = ASCII(name);
++
++ if (provide->name &&
++ (strcmp(provide->name, "_system_") || mfx->sw_source->parent))
++ return -1; /* only _system_ is accepted from root sw source */
++
++ depth = xmlTextReaderDepth(reader);
++ while ((ret = msmNextChildElement(reader, depth))) {
++ node = xmlTextReaderConstName(reader);
++ if (!node) return -1;
++
++ if (!strcmp(ASCII(node), "dbus")) {
++ dbus_x *dbus = calloc(1, sizeof(dbus_x));
++ if (dbus) {
++ ret = msmProcessDBus(reader, dbus);
++ LISTADD(provide->dbuss, dbus);
++ } else return -1;
++ } else if (!strcmp(ASCII(node), "ac_domain")) {
++ ac_domain_x *ac_domain = msmProcessACDomain(reader, current, pkg_name);
++ if (ac_domain) {
++ const char *name = ac_domain->name;
++ LISTADD(provide->ac_domains, ac_domain);
++ if (!name) return -1;
++ if (mfx && !provide->name) {
++ ac_domain->name = malloc(strlen(mfx->name) + 2 +
++ strlen(name) + 1);
++ sprintf((char *)ac_domain->name, "%s::%s", mfx->name, name);
++ msmFreePointer((void**)&name);
++ }
++ } else return -1;
++
++ } else if (!strcmp(ASCII(node), "for")) {
++ origin = xmlTextReaderGetAttribute(reader, XMLCHAR("origin"));
++ rpmlog(RPMLOG_DEBUG, "for %s\n", ASCII(origin));
++ if (!origin) return -1;
++ if (provide->origin) {
++ msmFreePointer((void**)&origin);
++ return -1;
++ }
++ provide->origin = ASCII(origin);
++ if (strcmp(ASCII(origin), "trusted") &&
++ strcmp(ASCII(origin), "current") &&
++ strcmp(ASCII(origin), "all"))
++ return -1;
++
++ } else if (!strcmp(ASCII(node), "filesystem")) {
++ filesystem_x *filesystem = msmProcessFilesystem(reader);
++ if (filesystem) {
++ LISTADD(provide->filesystems, filesystem);
++ } else return -1;
++
++ } else {
++ rpmlog(RPMLOG_ERR, "No allowed element in assign section: %s\n", ASCII(node));
++ return -1;
++ }
++
++ if (ret < 0) return ret;
++ }
++
++ return ret;
++}
++
++static int msmProcessPackage(xmlTextReaderPtr reader, package_x *package, sw_source_x *current)
++{
++ const xmlChar *node, *name, *modified;
++ int ret, depth;
++
++ /* config processing */
++ name = xmlTextReaderGetAttribute(reader, XMLCHAR("name"));
++ modified = xmlTextReaderGetAttribute(reader, XMLCHAR("modified"));
++ rpmlog(RPMLOG_DEBUG, "package %s %s\n", name, modified);
++
++ package->name = ASCII(name);
++ package->modified = ASCII(modified);
++ package->sw_source = current;
++
++ depth = xmlTextReaderDepth(reader);
++ while ((ret = msmNextChildElement(reader, depth))) {
++ node = xmlTextReaderConstName(reader);
++ if (!node) return -1;
++
++ if (!strcmp(ASCII(node), "provide")) {
++ provide_x *provide = calloc(1, sizeof(provide_x));
++ if (provide) {
++ LISTADD(package->provides, provide);
++ ret = msmProcessProvide(reader, provide, current, NULL, package->name);
++ } else return -1;
++ } else return -1;
++
++ if (ret < 0) return ret;
++ }
++ return ret;
++}
++
++static int msmProcessRequest(xmlTextReaderPtr reader, request_x *request)
++{
++ const xmlChar *node, *name;
++ int ret, depth, requestPresent = 0;
++
++ rpmlog(RPMLOG_DEBUG, "request \n");
++ depth = xmlTextReaderDepth(reader);
++ while ((ret = msmNextChildElement(reader, depth))) {
++
++ node = xmlTextReaderConstName(reader);
++ if (!node) return -1;
++
++ if (!strcmp(ASCII(node), "domain")) {
++ if (requestPresent) {
++ rpmlog(RPMLOG_ERR, "A second domain defined inside a request section. Abort package installation\n");
++ return -1;
++ }
++ name = xmlTextReaderGetAttribute(reader, XMLCHAR("name"));
++ rpmlog(RPMLOG_DEBUG, "ac domain name %s\n", ASCII(name));
++ if (name) {
++ request->ac_domain = ASCII(name);
++ requestPresent = 1;
++ } else {
++ rpmlog(RPMLOG_ERR, "No ac domain name defined in request.\n");
++ return -1;
++ }
++ } else {
++ rpmlog(RPMLOG_ERR, "Not allowed element in request section: %s\n", ASCII(node));
++ return -1;
++ }
++ }
++
++ return ret;
++}
++
++static int msmProcessDRequest(xmlTextReaderPtr reader, define_x *define)
++{
++ const xmlChar *node = NULL, *label = NULL, *type = NULL;
++ int ret, depth;
++
++ rpmlog(RPMLOG_DEBUG, "request\n");
++
++ if (!define->name) {
++ rpmlog(RPMLOG_ERR, "An attempt to define a domain without a name. Abort.\n");
++ return -1;
++ }
++
++ depth = xmlTextReaderDepth(reader);
++ while ((ret = msmNextChildElement(reader, depth))) {
++ node = xmlTextReaderConstName(reader);
++ if (!node) return -1;
++
++ if (!strcmp(ASCII(node), "smack")) {
++ label = xmlTextReaderGetAttribute(reader, XMLCHAR("request"));
++ type = xmlTextReaderGetAttribute(reader, XMLCHAR("type"));
++ rpmlog(RPMLOG_DEBUG, "request label %s type %s\n", ASCII(label), ASCII(type));
++ if (label && type) {
++ if (msmVerifyAccessType(ASCII(type)) < 0) {
++ msmFreePointer((void**)&label);
++ msmFreePointer((void**)&type);
++ return -1;
++ }
++ if (msmVerifySmackLabel(ASCII(label)) < 0) {
++ msmFreePointer((void**)&label);
++ msmFreePointer((void**)&type);
++ return -1;
++ }
++ d_request_x *request = calloc(1, sizeof(d_request_x));
++ if (request) {
++ request->label_name = ASCII(label);
++ request->ac_type = ASCII(type);
++ LISTADD(define->d_requests, request);
++ } else {
++ msmFreePointer((void**)&label);
++ msmFreePointer((void**)&type);
++ return -1;
++ }
++
++ } else {
++ rpmlog(RPMLOG_ERR, "One of the mandatory arguments for domain request is missing. Abort installation\n");
++ rpmlog(RPMLOG_ERR, "smack request label %s type %s\n", ASCII(label), ASCII(type));
++ msmFreePointer((void**)&label);
++ msmFreePointer((void**)&type);
++ return -1;
++ }
++ } else {
++ rpmlog(RPMLOG_ERR, "Not allowed element in domain request section: %s\n", ASCII(node));
++ return -1;
++ }
++ if (ret < 0) return ret;
++ }
++
++ return ret;
++}
++
++static int msmProcessDPermit(xmlTextReaderPtr reader, define_x *define)
++{
++ const xmlChar *node, *label, *type, *to_label;
++ int ret, depth;
++
++ rpmlog(RPMLOG_DEBUG, "permit\n");
++
++ if (!define->name) {
++ rpmlog(RPMLOG_ERR, "An attempt to define a domain without a name. Abort.\n");
++ return -1;
++ }
++
++ depth = xmlTextReaderDepth(reader);
++
++ while ((ret = msmNextChildElement(reader, depth))) {
++ node = xmlTextReaderConstName(reader);
++ if (!node) return -1;
++
++ if (!strcmp(ASCII(node), "smack")) {
++ label = xmlTextReaderGetAttribute(reader, XMLCHAR("permit"));
++ to_label = xmlTextReaderGetAttribute(reader, XMLCHAR("to"));
++ type = xmlTextReaderGetAttribute(reader, XMLCHAR("type"));
++ rpmlog(RPMLOG_DEBUG, "permit %s to %s type %s\n", ASCII(label), ASCII(to_label), ASCII(type));
++
++ if (label && type) {
++ if (msmVerifyAccessType(ASCII(type)) < 0) {
++ msmFreePointer((void**)&label);
++ msmFreePointer((void**)&to_label);
++ msmFreePointer((void**)&type);
++ return -1;
++ }
++ if (msmVerifySmackLabel(ASCII(label)) < 0) {
++ msmFreePointer((void**)&label);
++ msmFreePointer((void**)&to_label);
++ msmFreePointer((void**)&type);
++ return -1;
++ }
++ if ((to_label) && (msmVerifyLabelPrefix(ASCII(to_label), define->name) < 0)) {
++ msmFreePointer((void**)&label);
++ msmFreePointer((void**)&to_label);
++ msmFreePointer((void**)&type);
++ return -1;
++ }
++ d_permit_x *permit = calloc(1, sizeof(d_permit_x));
++ if (permit) {
++ permit->label_name = ASCII(label);
++ permit->to_label_name = ASCII(to_label);
++ permit->ac_type = ASCII(type);
++ LISTADD(define->d_permits, permit);
++ } else {
++ msmFreePointer((void**)&label);
++ msmFreePointer((void**)&to_label);
++ msmFreePointer((void**)&type);
++ return -1;
++ }
++
++ } else {
++ rpmlog(RPMLOG_ERR, "One of the mandatory arguments for domain permit is missing. Abort installation\n");
++ rpmlog(RPMLOG_ERR, "smack permit label %s type %s\n", ASCII(label), ASCII(type));
++ msmFreePointer((void**)&label);
++ msmFreePointer((void**)&to_label);
++ msmFreePointer((void**)&type);
++ return -1;
++ }
++ } else {
++ rpmlog(RPMLOG_ERR, "Not allowed element in domain permit section: %s\n", ASCII(node));
++ return -1;
++ }
++ if (ret < 0) return ret;
++ }
++
++ return ret;
++}
++
++static int msmProcessDProvide(xmlTextReaderPtr reader, define_x *define)
++{
++ const xmlChar *node, *label;
++ int ret = 0, depth;
++
++ rpmlog(RPMLOG_DEBUG, "provide\n");
++
++ if (!define->name) {
++ rpmlog(RPMLOG_ERR, "An attempt to define a domain without a name. Abort.\n");
++ return -1;
++ }
++
++ depth = xmlTextReaderDepth(reader);
++ while ((ret = msmNextChildElement(reader, depth))) {
++ node = xmlTextReaderConstName(reader);
++ if (!node) return -1;
++
++ if (!strcmp(ASCII(node), "label")) {
++ label = xmlTextReaderGetAttribute(reader, XMLCHAR("name"));
++ rpmlog(RPMLOG_DEBUG, "label %s \n", ASCII(label));
++
++ if (label) {
++ if (msmVerifySmackLabel(ASCII(label)) < 0) {
++ msmFreePointer((void**)&label);
++ return -1;
++ }
++
++ if (msmVerifyLabelPrefix(ASCII(label), define->name) < 0) {
++ msmFreePointer((void**)&label);
++ return -1;
++ }
++
++ d_provide_x *provide = calloc(1, sizeof(d_provide_x));
++ if (provide) {
++ provide->label_name = ASCII(label);
++ LISTADD(define->d_provides, provide);
++ } else {
++ msmFreePointer((void**)&label);
++ return -1;
++ }
++
++ } else {
++ rpmlog(RPMLOG_INFO, "Label name is empty. Label provide is ignored\n");
++ continue;
++ }
++ } else {
++ rpmlog(RPMLOG_ERR, "Not allowed element in domain provide section: %s\n", ASCII(node));
++ return -1;
++ }
++ if (ret < 0) return ret;
++ }
++
++ return ret;
++}
++
++static int msmProcessDefine(xmlTextReaderPtr reader, define_x *define, manifest_x *mfx, sw_source_x *current)
++{
++ const xmlChar *node, *name, *policy, *plist;
++ int ret, depth, domainPresent = 0;
++
++ rpmlog(RPMLOG_DEBUG, "define\n");
++
++ depth = xmlTextReaderDepth(reader);
++
++ while ((ret = msmNextChildElement(reader, depth))) {
++ node = xmlTextReaderConstName(reader);
++ if (!node) return -1;
++
++ if (!strcmp(ASCII(node), "domain")) {
++ if (domainPresent) {
++ rpmlog(RPMLOG_ERR, "Only one domain is allowed per define section. Abort installation\n");
++ return -1;
++ }
++ domainPresent = 1;
++ name = xmlTextReaderGetAttribute(reader, XMLCHAR("name"));
++ policy = xmlTextReaderGetAttribute(reader, XMLCHAR("policy"));
++ plist = xmlTextReaderGetAttribute(reader, XMLCHAR("plist"));
++ rpmlog(RPMLOG_DEBUG, "domain %s policy %s plist %s\n",
++ ASCII(name), ASCII(policy), ASCII(plist));
++
++ if (name) {
++
++ if (msmVerifySmackLabel(ASCII(name)) < 0){
++ msmFreePointer((void**)&name);
++ msmFreePointer((void**)&policy);
++ msmFreePointer((void**)&plist);
++ return -1;
++ }
++
++ define->name = ASCII(name);
++ define->policy = ASCII(policy);
++ define->plist = ASCII(plist);
++
++ // store defined ac domain name
++ ac_domain_x *ac_domain = calloc(1, sizeof(ac_domain_x));
++ if (ac_domain) {
++ if (define->name) {
++ ac_domain->name = strdup(define->name);
++ }
++ ac_domain->match = strdup("trusted"); // hardcode trusted policy for ac domain definition
++ if (define->policy) {
++ ac_domain->type = strdup(define->policy);
++ }
++ if (define->plist) {
++ ac_domain->plist = strdup(define->plist);
++ }
++ ac_domain->sw_source = current;
++ ac_domain->pkg_name = mfx->name;
++ if (!mfx->provides){
++ provide_x *provide = calloc(1, sizeof(provide_x));
++ if (provide) {
++ LISTADD(mfx->provides, provide);
++ } else {
++ if (ac_domain) {
++ msmFreeACDomain(ac_domain);
++ return -1;
++ }
++ }
++ }
++ LISTADD(mfx->provides->ac_domains, ac_domain);
++ } else return -1;
++
++ } else {
++ rpmlog(RPMLOG_ERR, "Domain name must be defined. Abort installation\n");
++ msmFreePointer((void**)&policy);
++ msmFreePointer((void**)&plist);
++ return -1;
++ }
++ } else if (!strcmp(ASCII(node), "request")) {
++ int res = msmProcessDRequest(reader, define);
++ if (res < 0) return res;
++
++ } else if (!strcmp(ASCII(node), "permit")) {
++ int res = msmProcessDPermit(reader, define);
++ if (res < 0) return res;
++
++ } else if (!strcmp(ASCII(node), "provide")) {
++ int res = msmProcessDProvide(reader, define);
++ if (res < 0) return res;
++ } else {
++ rpmlog(RPMLOG_ERR, "Not allowed element in domain define section: %s\n", ASCII(node));
++ return -1;
++ }
++
++ if (ret < 0) return ret;
++ }
++ return ret;
++}
++
++static int msmProcessKeyinfo(xmlTextReaderPtr reader, origin_x *origin)
++{
++ const xmlChar *keydata;
++ keyinfo_x *keyinfo;
++ int ret, depth;
++
++ depth = xmlTextReaderDepth(reader);
++ while ((ret = msmNextChildElement(reader, depth))) {
++ keydata = xmlTextReaderConstValue(reader);
++ rpmlog(RPMLOG_DEBUG, "keyinfo %.40s...\n", ASCII(keydata));
++ if (!keydata) return -1;
++ keyinfo = calloc(1, sizeof(keyinfo_x));
++ if (keyinfo) {
++ if ((ret = b64decode(ASCII(keydata), (void **)&keyinfo->keydata, &keyinfo->keylen))) {
++ rpmlog(RPMLOG_ERR, "Failed to decode keyinfo %s, %d\n", keydata, ret);
++ ret = -1;
++ }
++ LISTADD(origin->keyinfos, keyinfo);
++ } else return -1;
++
++ if (ret < 0) return ret;
++ }
++ return ret;
++}
++
++static access_x *msmProcessAccess(xmlTextReaderPtr reader, origin_x *origin)
++{
++ const xmlChar *data, *type;
++
++ data = xmlTextReaderGetAttribute(reader, XMLCHAR("data"));
++ type = xmlTextReaderGetAttribute(reader, XMLCHAR("type"));
++ rpmlog(RPMLOG_DEBUG, "access %s %s\n", ASCII(data), ASCII(type));
++
++ if (data) {
++ access_x *access = calloc(1, sizeof(access_x));
++ if (access) {
++ access->data = ASCII(data);
++ access->type = ASCII(type);
++ return access;
++ }
++ }
++ msmFreePointer((void**)&data);
++ msmFreePointer((void**)&type);
++ return NULL;
++}
++
++static int msmProcessOrigin(xmlTextReaderPtr reader, origin_x *origin)
++{
++ const xmlChar *node, *type;
++ int ret, depth;
++
++ type = xmlTextReaderGetAttribute(reader, XMLCHAR("type"));
++ rpmlog(RPMLOG_DEBUG, "origin %s\n", ASCII(type));
++ origin->type = ASCII(type);
++
++ depth = xmlTextReaderDepth(reader);
++ while ((ret = msmNextChildElement(reader, depth))) {
++ node = xmlTextReaderConstName(reader);
++ if (!node) return -1;
++
++ if (!strcmp(ASCII(node), "keyinfo")) {
++ ret = msmProcessKeyinfo(reader, origin);
++ } else if (!strcmp(ASCII(node), "access")) {
++ access_x *access = msmProcessAccess(reader, origin);
++ if (access) {
++ LISTADD(origin->accesses, access);
++ } else return -1;
++ } else return -1;
++
++ if (ret < 0) return ret;
++ }
++ return ret;
++}
++
++static int msmProcessDeny(xmlTextReaderPtr reader, sw_source_x *sw_source)
++{
++ const xmlChar *node;
++ int ret, depth;
++
++ rpmlog(RPMLOG_DEBUG, "deny\n");
++
++ depth = xmlTextReaderDepth(reader);
++ while ((ret = msmNextChildElement(reader, depth))) {
++ node = xmlTextReaderConstName(reader);
++ if (!node) return -1;
++
++ if (!strcmp(ASCII(node), "ac_domain")) {
++ ac_domain_x *ac_domain = msmProcessACDomain(reader, sw_source, NULL);
++ if (ac_domain) {
++ if (ac_domain->name) {
++ HASH_ADD_KEYPTR(hh, sw_source->denys, ac_domain->name,
++ strlen(ac_domain->name), ac_domain);
++ } else {
++ LISTADD(sw_source->denymatches, ac_domain);
++ }
++ } else return -1;
++ } else return -1;
++ if (ret < 0) return ret;
++ }
++ return ret;
++}
++
++static int msmProcessAllow(xmlTextReaderPtr reader, sw_source_x *sw_source)
++{
++ const xmlChar *node;
++ int ret, depth;
++
++ rpmlog(RPMLOG_DEBUG, "allow\n");
++
++ depth = xmlTextReaderDepth(reader);
++ while ((ret = msmNextChildElement(reader, depth))) {
++ node = xmlTextReaderConstName(reader);
++ if (!node) return -1;
++
++ if (!strcmp(ASCII(node), "deny")) {
++ ret = msmProcessDeny(reader, sw_source);
++ } else if (!strcmp(ASCII(node), "ac_domain")) {
++ ac_domain_x *ac_domain = msmProcessACDomain(reader, sw_source, NULL);
++ if (ac_domain) {
++ if (ac_domain->name) {
++ HASH_ADD_KEYPTR(hh, sw_source->allows, ac_domain->name,
++ strlen(ac_domain->name), ac_domain);
++ } else {
++ LISTADD(sw_source->allowmatches, ac_domain);
++ }
++ } else return -1;
++ } else return -1;
++ if (ret < 0) return ret;
++ }
++ return ret;
++}
++
++static int msmFindSWSourceByName(sw_source_x *sw_source, void *param)
++{
++ const char *name = (const char *)param;
++ return strcmp(sw_source->name, name);
++}
++
++static int msmProcessSWSource(xmlTextReaderPtr reader, sw_source_x *sw_source, const char *parentkey, manifest_x *mfx)
++{
++ const xmlChar *name, *node, *rank, *rankkey;
++ sw_source_x *current;
++ int ret, depth, len;
++ int rankval = 0;
++
++ /* config processing */
++ current = sw_source;
++
++ name = xmlTextReaderGetAttribute(reader, XMLCHAR("name"));
++ rank = xmlTextReaderGetAttribute(reader, XMLCHAR("rank"));
++ rankkey = xmlTextReaderGetAttribute(reader, XMLCHAR("rankkey"));
++ rpmlog(RPMLOG_DEBUG, "sw source %s rank %s key %s\n",
++ ASCII(name), ASCII(rank), ASCII(rankkey));
++
++ sw_source->name = ASCII(name);
++
++ if (rankkey) {
++ /* config processing */
++ sw_source->rankkey = ASCII(rankkey);
++ } else {
++ if (rank) {
++ rankval = atoi(ASCII(rank));
++ msmFreePointer((void**)&rank); /* rankkey is used from now on */
++ }
++ }
++ if (!sw_source->name) return -1; /* sw source must have name */
++ if (!mfx && rankkey) return -1; /* manifest cannot set rankkey itself */
++
++ if (!mfx) {
++ sw_source_x *old = msmSWSourceTreeTraversal(sw_source->parent, msmFindSWSourceByName, (void *)sw_source->name);
++ if (old && old->parent != sw_source->parent) {
++ if (!old->parent && old == sw_source->parent) {
++ /* root sw source upgrade (it's signed by root) */
++ parentkey = "";
++ } else {
++ rpmlog(RPMLOG_ERR, "SW source called %s has already been installed\n",
++ sw_source->name);
++ return -1; /* sw_source names are unique (allow upgrade though) */
++ }
++ }
++ /* rank algorithm is copied from harmattan dpkg wrapper */
++ if (rankval > RANK_LIMIT) rankval = RANK_LIMIT;
++ if (rankval < -RANK_LIMIT) rankval = -RANK_LIMIT;
++ rankval += RANK_LIMIT;
++
++ len = strlen(parentkey) + 1 + 5 + 1 + 5 + 1 + strlen(sw_source->name) + 1;
++ if (!(sw_source->rankkey = malloc(len))) return -1;
++ sprintf((char *)sw_source->rankkey, "%s/%05d/%05d.%s",
++ parentkey, rankval, RANK_LIMIT, sw_source->name);
++ }
++
++ depth = xmlTextReaderDepth(reader);
++ while ((ret = msmNextChildElement(reader, depth))) {
++ node = xmlTextReaderConstName(reader);
++ if (!node) return -1;
++
++ if (!strcmp(ASCII(node), "allow")) {
++ ret = msmProcessAllow(reader, sw_source);
++ } else if (!strcmp(ASCII(node), "deny")) {
++ ret = msmProcessDeny(reader, sw_source);
++ } else if (!strcmp(ASCII(node), "origin")) {
++ origin_x *origin = calloc(1, sizeof(origin_x));
++ if (origin) {
++ LISTADD(sw_source->origins, origin);
++ ret = msmProcessOrigin(reader, origin);
++ } else return -1;
++ } else if (!strcmp(ASCII(node), "package")) {
++ /* config processing */
++ if (!mfx) return -1;
++ package_x *package = calloc(1, sizeof(package_x));
++ if (package) {
++ LISTADD(sw_source->packages, package);
++ ret = msmProcessPackage(reader, package, current);
++ } else return -1;
++ } else if (!strcmp(ASCII(node), "sw_source")) {
++ /* config processing */
++ if (!mfx) return -1;
++ sw_source_x *sw_source = calloc(1, sizeof(sw_source_x));
++ if (sw_source) {
++ sw_source->parent = current;
++ LISTADD(mfx->sw_sources, sw_source);
++ } else return -1;
++ ret = msmProcessSWSource(reader, sw_source, "", mfx);
++ } else return -1;
++
++ if (ret < 0) return ret;
++ }
++ return ret;
++}
++
++static int msmProcessMsm(xmlTextReaderPtr reader, manifest_x *mfx, sw_source_x *current)
++{
++ const xmlChar *node;
++ int ret, depth;
++ int assignPresent = 0, requestPresent = 0, definePresent = 0; /* there must be only one section per manifest */
++ mfx->sw_source = current;
++
++ rpmlog(RPMLOG_DEBUG, "manifest\n");
++
++ depth = xmlTextReaderDepth(reader);
++ while ((ret = msmNextChildElement(reader, depth))) {
++ node = xmlTextReaderConstName(reader);
++ if (!node) return -1;
++
++ if (!strcmp(ASCII(node), "assign")) {
++ if (assignPresent) {
++ rpmlog(RPMLOG_ERR, "A second assign section in manifest isn't allowed. Abort installation.\n");
++ return -1;
++ }
++ assignPresent = 1;
++ provide_x *provide = calloc(1, sizeof(provide_x));
++ if (provide) {
++ LISTADD(mfx->provides, provide);
++ ret = msmProcessProvide(reader, provide, current, mfx, NULL);
++ } else return -1;
++ } else if (!strcmp(ASCII(node), "define")) {
++ if (definePresent) {
++ rpmlog(RPMLOG_ERR, "A second request section in manifest isn't allowed. Abort installation.\n");
++ return -1;
++ }
++ definePresent = 1;
++ mfx->define = calloc(1, sizeof(define_x));
++ if (mfx->define) {
++ ret = msmProcessDefine(reader, mfx->define, mfx, current);
++ } else return -1;
++ } else if (!strcmp(ASCII(node), "request")) {
++ if (requestPresent) {
++ rpmlog(RPMLOG_ERR, "A second request section in manifest isn't allowed. Abort installation.\n");
++ return -1;
++ }
++ requestPresent = 1;
++ mfx->request = calloc(1, sizeof(request_x));
++ if (mfx->request) {
++ ret = msmProcessRequest(reader, mfx->request);
++ } else return -1;
++ } else if (!strcmp(ASCII(node), "sw_source")) {
++ sw_source_x *sw_source = calloc(1, sizeof(sw_source_x));
++ if (sw_source) {
++ char parentkey[256] = { 0 };
++ sw_source->parent = current;
++ if (sw_source->parent) {
++ snprintf(parentkey, sizeof(parentkey),
++ "%s", sw_source->parent->rankkey);
++ char *sep = strrchr(parentkey, '/');
++ if (sep) *sep = '\0';
++ }
++ LISTADD(mfx->sw_sources, sw_source);
++ ret = msmProcessSWSource(reader, sw_source, parentkey, NULL);
++ } else return -1;
++ } else return -1;
++
++ if (ret < 0) return ret;
++ }
++
++ return ret;
++}
++
++static int msmProcessConfig(xmlTextReaderPtr reader, manifest_x *mfx)
++{
++ const xmlChar *node;
++ int ret, depth;
++
++ rpmlog(RPMLOG_DEBUG, "config\n");
++
++ depth = xmlTextReaderDepth(reader);
++ if ((ret = msmNextChildElement(reader, depth))) {
++ node = xmlTextReaderConstName(reader);
++ if (!node) return -1;
++
++ if (!strcmp(ASCII(node), "sw_source")) {
++ mfx->sw_sources = calloc(1, sizeof(sw_source_x));
++ if (!mfx->sw_sources) return -1;
++ ret = msmProcessSWSource(reader, mfx->sw_sources, "", mfx);
++ } else return -1;
++ }
++ return ret;
++}
++
++static int msmProcessManifest(xmlTextReaderPtr reader, manifest_x *mfx, sw_source_x *current)
++{
++ const xmlChar *node;
++ int ret;
++
++ if ((ret = msmNextChildElement(reader, -1))) {
++ node = xmlTextReaderConstName(reader);
++ if (!node) return -1;
++
++ if (!strcmp(ASCII(node), "manifest")) {
++ ret = msmProcessMsm(reader, mfx, current);
++ } else if (!strcmp(ASCII(node), "config")) {
++ ret = msmProcessConfig(reader, mfx);
++ } else return -1;
++ }
++ return ret;
++}
++
++static filesystem_x *msmFreeFilesystem(filesystem_x *filesystem)
++{
++ if (filesystem) {
++ filesystem_x *prev = filesystem->prev;
++ msmFreePointer((void**)&filesystem->path);
++ msmFreePointer((void**)&filesystem->label);
++ msmFreePointer((void**)&filesystem->exec_label);
++ msmFreePointer((void**)&filesystem->type);
++ msmFreePointer((void**)&filesystem);
++ return prev;
++ } else
++ return NULL;
++
++}
++
++static member_x *msmFreeMember(member_x *member)
++{
++
++ if (member) {
++ member_x *prev = member->prev;
++ msmFreePointer((void**)&member->name);
++ if (member->annotation) {
++ msmFreePointer((void**)&member->annotation->name);
++ msmFreePointer((void**)&member->annotation->value);
++ msmFreePointer((void**)&member->annotation);
++ }
++ msmFreePointer((void**)&member);
++ return prev;
++ } else
++ return NULL;
++
++}
++
++static interface_x *msmFreeInterface(interface_x *interface)
++{
++
++ member_x *member;
++
++ if (interface) {
++ interface_x *prev = interface->prev;
++ msmFreePointer((void**)&interface->name);
++ if (interface->annotation) {
++ msmFreePointer((void**)&interface->annotation->name);
++ msmFreePointer((void**)&interface->annotation->value);
++ msmFreePointer((void**)&interface->annotation);
++ }
++ for (member = interface->members; member; member = msmFreeMember(member));
++ msmFreePointer((void**)&interface);
++ return prev;
++ } else
++ return NULL;
++
++}
++
++static node_x *msmFreeNode(node_x *node)
++{
++ member_x *member;
++ interface_x *interface;
++
++ if (node) {
++ node_x *prev = node->prev;
++ msmFreePointer((void**)&node->name);
++ if (node->annotation) {
++ msmFreePointer((void**)&node->annotation->name);
++ msmFreePointer((void**)&node->annotation->value);
++ msmFreePointer((void**)&node->annotation);
++ }
++ for (member = node->members; member; member = msmFreeMember(member));
++ for (interface = node->interfaces; interface; interface = msmFreeInterface(interface));
++ msmFreePointer((void**)&node);
++ return prev;
++ } else
++ return NULL;
++
++}
++
++static dbus_x *msmFreeDBus(dbus_x *dbus)
++{
++ node_x *node;
++
++ if (dbus) {
++ dbus_x *prev = dbus->prev;
++ msmFreePointer((void**)&dbus->name);
++ msmFreePointer((void**)&dbus->own);
++ msmFreePointer((void**)&dbus->bus);
++ if (dbus->annotation) {
++ msmFreePointer((void**)&dbus->annotation->name);
++ msmFreePointer((void**)&dbus->annotation->value);
++ msmFreePointer((void**)&dbus->annotation);
++ }
++ for (node = dbus->nodes; node; node = msmFreeNode(node));
++ msmFreePointer((void**)&dbus);
++ return prev;
++ } else return NULL;
++}
++
++static provide_x *msmFreeProvide(provide_x *provide)
++{
++ ac_domain_x *ac_domain;
++ filesystem_x *filesystem;
++ provide_x *prev = provide->prev;
++ dbus_x *dbus;
++
++ if (provide) {
++ for (ac_domain = provide->ac_domains; ac_domain; ac_domain = msmFreeACDomain(ac_domain));
++ if (provide->filesystems)
++ for (filesystem = provide->filesystems; filesystem; filesystem = msmFreeFilesystem(filesystem));
++ msmFreePointer((void**)&provide->name);
++ msmFreePointer((void**)&provide->origin);
++ for (dbus = provide->dbuss; dbus; dbus = msmFreeDBus(dbus));
++ msmFreePointer((void**)&provide);
++ }
++ return prev;
++}
++
++static file_x *msmFreeFile(file_x *file)
++{
++ file_x *prev = file->prev;
++ msmFreePointer((void**)&file->path);
++ msmFreePointer((void**)&file);
++ return prev;
++}
++
++package_x *msmFreePackage(package_x *package)
++{
++ provide_x *provide;
++ package_x *prev = package->prev;
++ for (provide = package->provides; provide; provide = msmFreeProvide(provide));
++ msmFreePointer((void**)&package->name);
++ msmFreePointer((void**)&package->modified);
++ msmFreePointer((void**)&package);
++ return prev;
++}
++
++static keyinfo_x *msmFreeKeyinfo(keyinfo_x *keyinfo)
++{
++ keyinfo_x *prev = keyinfo->prev;
++ msmFreePointer((void**)&keyinfo->keydata);
++ msmFreePointer((void**)&keyinfo);
++ return prev;
++}
++
++static access_x *msmFreeAccess(access_x *access)
++{
++ access_x *prev = access->prev;
++ msmFreePointer((void**)&access->data);
++ msmFreePointer((void**)&access->type);
++ msmFreePointer((void**)&access);
++ return prev;
++}
++
++static origin_x *msmFreeOrigin(origin_x *origin)
++{
++ keyinfo_x *keyinfo;
++ access_x *access;
++ origin_x *prev = origin->prev;
++ for (keyinfo = origin->keyinfos; keyinfo; keyinfo = msmFreeKeyinfo(keyinfo));
++ for (access = origin->accesses; access; access = msmFreeAccess(access));
++ msmFreePointer((void**)&origin->type);
++ msmFreePointer((void**)&origin);
++ return prev;
++}
++
++static sw_source_x *msmFreeSWSource(sw_source_x *sw_source)
++{
++ package_x *package;
++ ac_domain_x *ac_domain, *temp;
++ origin_x *origin;
++ sw_source_x *next = sw_source->next;
++
++ rpmlog(RPMLOG_DEBUG, "freeing sw source %s\n", sw_source->name);
++
++ for (package = sw_source->packages; package; package = msmFreePackage(package));
++ for (ac_domain = sw_source->allowmatches; ac_domain; ac_domain = msmFreeACDomain(ac_domain));
++ if (sw_source->allows) {
++ HASH_ITER(hh, sw_source->allows, ac_domain, temp) {
++ HASH_DELETE(hh, sw_source->allows, ac_domain);
++ msmFreeACDomain(ac_domain);
++ }
++ }
++
++ for (ac_domain = sw_source->denymatches; ac_domain; ac_domain = msmFreeACDomain(ac_domain));
++ if (sw_source->denys) {
++ HASH_ITER(hh, sw_source->denys, ac_domain, temp) {
++ HASH_DELETE(hh, sw_source->denys, ac_domain);
++ msmFreeACDomain(ac_domain);
++ }
++ }
++ for (origin = sw_source->origins; origin; origin = msmFreeOrigin(origin));
++ msmFreePointer((void**)&sw_source->name);
++ msmFreePointer((void**)&sw_source->rankkey);
++ msmFreePointer((void**)&sw_source);
++ return next;
++}
++
++static d_request_x *msmFreeDRequest(d_request_x *d_request)
++{
++ d_request_x *next = d_request->next;
++ rpmlog(RPMLOG_DEBUG, "freeing domain request %s\n", d_request->label_name);
++ msmFreePointer((void**)&d_request->label_name);
++ msmFreePointer((void**)&d_request->ac_type);
++ msmFreePointer((void**)&d_request);
++ return next;
++}
++
++static d_permit_x *msmFreeDPermit(d_permit_x *d_permit)
++{
++ d_permit_x *next = d_permit->next;
++ rpmlog(RPMLOG_DEBUG, "freeing domain permit %s\n", d_permit->label_name);
++ msmFreePointer((void**)&d_permit->label_name);
++ msmFreePointer((void**)&d_permit->to_label_name);
++ msmFreePointer((void**)&d_permit->ac_type);
++ msmFreePointer((void**)&d_permit);
++ return next;
++}
++
++static d_provide_x *msmFreeDProvide(d_provide_x *d_provide)
++{
++ d_provide_x *next = d_provide->next;
++ rpmlog(RPMLOG_DEBUG, "freeing domain provide %s\n", d_provide->label_name);
++ msmFreePointer((void**)&d_provide->label_name);
++ msmFreePointer((void**)&d_provide);
++ return next;
++}
++
++manifest_x* msmFreeManifestXml(manifest_x* mfx)
++{
++ provide_x *provide;
++ file_x *file;
++ sw_source_x *sw_source;
++ d_request_x *d_request;
++ d_permit_x *d_permit;
++ d_provide_x *d_provide;
++
++ rpmlog(RPMLOG_DEBUG, "in msmFreeManifestXml\n");
++ if (mfx) {
++ if (mfx->provides)
++ for (provide = mfx->provides; provide; provide = msmFreeProvide(provide));
++ rpmlog(RPMLOG_DEBUG, "after freeing provides\n");
++ if (mfx->request) {
++ msmFreePointer((void**)&mfx->request->ac_domain);
++ msmFreePointer((void**)&mfx->request);
++ }
++ rpmlog(RPMLOG_DEBUG, "after freeing requests\n");
++ for (file = mfx->files; file; file = msmFreeFile(file));
++ rpmlog(RPMLOG_DEBUG, "after freeing files\n");
++ if (mfx->sw_sources) {
++ LISTHEAD(mfx->sw_sources, sw_source);
++ for (; sw_source; sw_source = msmFreeSWSource(sw_source));
++ }
++ msmFreePointer((void**)&mfx->name);
++ rpmlog(RPMLOG_DEBUG, "after freeing name\n");
++ if (mfx->define) {
++ msmFreePointer((void**)&mfx->define->name);
++ msmFreePointer((void**)&mfx->define->policy);
++ msmFreePointer((void**)&mfx->define->plist);
++ if (mfx->define->d_requests) {
++ LISTHEAD(mfx->define->d_requests, d_request);
++ for (; d_request; d_request = msmFreeDRequest(d_request));
++ }
++ rpmlog(RPMLOG_DEBUG, "after freeing define requests\n");
++ if (mfx->define->d_permits) {
++ LISTHEAD(mfx->define->d_permits, d_permit);
++ for (; d_permit; d_permit = msmFreeDPermit(d_permit));
++ }
++ rpmlog(RPMLOG_DEBUG, "after freeing define permits\n");
++ if (mfx->define->d_provides) {
++ LISTHEAD(mfx->define->d_provides, d_provide);
++ for (; d_provide; d_provide = msmFreeDProvide(d_provide));
++ }
++ rpmlog(RPMLOG_DEBUG, "after freeing provides\n");
++ msmFreePointer((void**)&mfx->define);
++ }
++
++ rpmlog(RPMLOG_DEBUG, "after freeing defines \n");
++ msmFreePointer((void**)&mfx);
++ }
++ return mfx;
++}
++
++manifest_x *msmProcessManifestXml(const char *buffer, int size, sw_source_x *current, const char *packagename)
++{
++ xmlTextReaderPtr reader;
++ manifest_x *mfx = NULL;
++
++ reader = xmlReaderForMemory(buffer, size, NULL, NULL, 0);
++
++ if (reader) {
++ mfx = calloc(1, sizeof(manifest_x));
++ if (mfx) {
++ mfx->name = strdup(packagename);
++ if (msmProcessManifest(reader, mfx, current) < 0) {
++ /* error in parcing. Let's display some hint where we failed */
++ rpmlog(RPMLOG_DEBUG, "Syntax error in processing manifest in the above line\n");
++ mfx = msmFreeManifestXml(mfx);
++ }
++ }
++ xmlFreeTextReader(reader);
++ } else {
++ rpmlog(RPMLOG_ERR, "Unable to create xml reader\n");
++ }
++ return mfx;
++}
++
++manifest_x *msmProcessDevSecPolicyXml(const char *filename)
++{
++ xmlTextReaderPtr reader;
++ manifest_x *mfx = NULL;
++
++ reader = xmlReaderForFile(filename, NULL, 0);
++
++ if (reader) {
++ mfx = calloc(1, sizeof(manifest_x));
++ if (mfx) {
++ if (msmProcessManifest(reader, mfx, NULL) < 0) {
++ mfx = msmFreeManifestXml(mfx);
++ }
++ }
++ xmlFreeTextReader(reader);
++ } else {
++ rpmlog(RPMLOG_ERR, "Unable to open device security policy %s\n", filename);
++ }
++ return mfx;
++}
+diff -Nuarp rpm/security/msmmatch.c rpm-security/security/msmmatch.c
+--- rpm/security/msmmatch.c 1970-01-01 02:00:00.000000000 +0200
++++ rpm-security/security/msmmatch.c 2012-10-01 10:29:50.327983644 +0300
+@@ -0,0 +1,71 @@
++/*
++ * This file is part of MSM security plugin
++ * Greatly based on the code of MSSF security plugin
++ *
++ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
++ *
++ * Contact: Tero Aho <ext-tero.aho@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <errno.h>
++#include <string.h>
++#include <unistd.h>
++
++#include "msm.h"
++
++/* Wild card strcmp, wild cards * and ? allowed in s1 */
++int strwcmp(const char *s1, const char *s2)
++{
++ char *c1 = (char *)s1;
++ char *c2 = (char *)s2;
++ char *star = NULL;
++ int ok = 0;
++
++ if (!s1 || !s2) return 1;
++
++ while (*c2) {
++ if (*c1 == '*') {
++ if (star && (c1 - star) != ok)
++ goto fail;
++ c1++;
++ star = c1;
++ ok = 0;
++ }
++ if (*c1 == '?') {
++ c1++;
++ c2++;
++ continue;
++ }
++ if (*c1 == *c2) {
++ c1++;
++ c2++;
++ ok++;
++ } else if (star) {
++ c1 = star;
++ c2++;
++ ok = 0;
++ } else goto fail;
++ }
++ if (*c1 == '\0' && *c2 == '\0' && (!star || (c1 - star) == ok))
++ return 0;
++ fail:
++ return (*c1 < *c2 ? -1 : 1);
++}
++
+diff -Nuarp rpm/security/msmxattr.c rpm-security/security/msmxattr.c
+--- rpm/security/msmxattr.c 1970-01-01 02:00:00.000000000 +0200
++++ rpm-security/security/msmxattr.c 2012-10-01 10:29:50.327983644 +0300
+@@ -0,0 +1,1323 @@
++/*
++ * This file is part of MSM security plugin
++ * Greatly based on the code of MSSF security plugin
++ *
++ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
++ *
++ * Contact: Tero Aho <ext-tero.aho@nokia.com>
++ *
++ * Copyright (C) 2011 - 2012 Intel Corporation.
++ *
++ * Contact: Elena Reshetova <elena.reshetova@intel.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <errno.h>
++#include <string.h>
++
++#include <sys/capability.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <unistd.h>
++#include <pwd.h>
++#include <grp.h>
++#include <attr/xattr.h>
++#include <uthash.h>
++#include <magic.h>
++
++#include "msm.h"
++
++static ac_domain_x *all_ac_domains = NULL; /* hash of all provided ac domains */
++static package_x *allpackages = NULL; /* hash of all installed packages */
++
++void msmFreeInternalHashes(void)
++{
++ if (all_ac_domains) {
++ HASH_CLEAR(hh,all_ac_domains);
++ }
++
++ if (allpackages) {
++ HASH_CLEAR(hh,allpackages);
++ }
++}
++
++static int msmCheckACDomainRules(ac_domain_x *ac_domain,
++ sw_source_x *requested, sw_source_x *provided)
++{
++ sw_source_x *sw_source;
++
++ /* go through sw source and its parents: ac domains must not match */
++ /* deny or deny wildcards and must match allow or allow wildcards */
++ /* in the whole path up to the level of the providing sw source */
++
++ for (sw_source = requested; sw_source->parent && sw_source->parent != sw_source; sw_source = sw_source->parent) {
++ ac_domain_x *denied;
++ ac_domain_x *allowed;
++ /* check first if requested ac domain is denied */
++ HASH_FIND(hh, sw_source->denys, ac_domain->name, strlen(ac_domain->name), denied);
++ if (denied) return 0; /* matched deny */
++ for (denied = sw_source->denymatches; denied; denied = denied->prev)
++ if (!strwcmp(denied->match, ac_domain->name))
++ return 0; /* matched deny wildcard */
++
++ /* not denied, now check if it's in allows or allowmatches */
++ HASH_FIND(hh, sw_source->allows, ac_domain->name, strlen(ac_domain->name), allowed);
++ if (allowed) continue; /* matched allow */
++ for (allowed = sw_source->allowmatches; allowed; allowed = allowed->prev)
++ if (!strwcmp(allowed->match, ac_domain->name))
++ break; /* matched allow wildcard */
++ if (allowed) continue; /* matched allow wildcard */
++
++ if (strcmp(sw_source->rankkey, provided->rankkey) <= 0)
++ return 1; /* ranked higher (or same sw source), allow */
++ return 0; /* not mentioned, deny */
++ }
++ return 1; /* still here, allow for root sw source */
++}
++
++static int msmCheckLabelProvisioning(manifest_x *mfx, const char* label)
++{
++
++ d_provide_x *provide = NULL;
++
++ if ((mfx) && (label) && (mfx->define) && (mfx->define->d_provides)) {
++ for (provide = mfx->define->d_provides; provide; provide = provide->prev) {
++ if ( strcmp(provide->label_name, label) == 0 )
++ return 0;
++ }
++ }
++ rpmlog(RPMLOG_ERR, "Label %s hasn't been provided in the manifest\n", label);
++ return -1;
++}
++
++static int msmSetSmackRules(struct smack_accesses *smack_accesses, ac_domain_x *ac_domains, const char *aid)
++{
++ ac_domain_x *ac_domain;
++ int ret = 0;
++
++ if (!smack_accesses) return ret;
++
++ for (ac_domain = ac_domains; ac_domain; ac_domain = ac_domain->prev) {
++ if (ac_domain->allowed) {
++ ret = smack_accesses_add(smack_accesses, aid, ac_domain->name, "rw");
++ if (ret < 0) {
++ rpmlog(RPMLOG_ERR, "smack_add failed for %s %s\n",
++ aid, ac_domain->name);
++ return ret;
++ }
++ }/* else if (!ac_domain->allowed && !ac_domain->newer) {
++ // remove not allowed rule in case something has changed
++ smack_rule_set_remove(rule_set, aid, ac_domain->name, NULL);
++ }*/
++ }
++ return ret;
++
++}
++
++static int msmIsProvideAllowed(ac_domain_x *provided, sw_source_x *sw_source, const char *origin)
++{
++
++ /* first check provided ac_domain attributes */
++ if (provided->sw_source == sw_source) {
++ /* allowed always if ac_domain is provided in the same sw source */
++ return 1;
++ } else if (origin && !strcmp(origin, "current")) {
++ /* denied if ac_domain is only meant for current sw source */
++ return 0;
++ }
++ if (origin && !strcmp(origin, "all")) {
++ /* ac_domain is allowed for all sw sources */
++ return 1;
++ }
++ if (!origin || !strcmp(origin, "trusted")) {
++ if (strcmp(sw_source->rankkey, provided->sw_source->rankkey) < 0) {
++ /* higher ranked sw sources are allowed if ac_domain is trusted */
++ return 1;
++ } /* else flow through to check denys and allows below */
++ } else return 0;
++
++ return msmCheckACDomainRules(provided, sw_source, provided->sw_source);
++}
++
++static int msmSetSmackProvide(struct smack_accesses *smack_accesses, provide_x *provide, sw_source_x *sw_source)
++{
++ ac_domain_x *ac_domain;
++ sw_source_x *current = sw_source;
++ int ret = -1;
++
++ if (!provide || (!provide->ac_domains)) return 0;
++
++ /* set smack rules for all sw sources */
++ LISTHEAD(current, sw_source);
++ for (; sw_source; sw_source = sw_source->next) {
++ if (!sw_source->newer) {
++ for (ac_domain = provide->ac_domains; ac_domain; ac_domain = ac_domain->prev) {
++ ac_domain->allowed = msmIsProvideAllowed(ac_domain, sw_source, ac_domain->origin);
++ rpmlog(RPMLOG_INFO, "%s ac_domain %s provided in %s for %s\n", (ac_domain->allowed ? "allowing" : "not allowing"),
++ ac_domain->name, ac_domain->sw_source->name, sw_source->name);
++ }
++ if (smack_accesses)
++ ret = msmSetSmackRules(smack_accesses, provide->ac_domains, sw_source->name);
++ else
++ ret = 0;
++ }
++ }
++ return ret;
++}
++
++static int msmSetupZypperRepo(access_x *access, sw_source_x *sw_source)
++{
++ struct stat sb;
++ char path[NAME_MAX+1];
++ FILE *file = NULL;
++ char data[512];
++ int ret = -1;
++
++ /* NOTE: Creating zypper repos manually here! */
++ /* A library call would be the correct way, but calling c++ from c */
++ /* is not nice. On the other hand, now there is no libzypp dependency. */
++
++ char *sysconfdir = rpmExpand("%{?_sysconfdir}", NULL);
++ if (!sysconfdir || !strcmp(sysconfdir, "")) {
++ rpmlog(RPMLOG_ERR, "Failed to expand %%_sysconfdir macro\n");
++ goto exit;
++ }
++ snprintf(path, sizeof(path), "%s/zypp", sysconfdir);
++ if (stat(path, &sb) == -1) {
++ rpmlog(RPMLOG_ERR, "Failed to stat %s: %s\n",
++ path, strerror(errno));
++ goto exit;
++ }
++ snprintf(path, sizeof(path), "%s/zypp/repos.d", sysconfdir);
++ if (stat(path, &sb) == -1) {
++ if (mkdir(path, 0755) == -1) {
++ rpmlog(RPMLOG_ERR, "Failed to create %s: %s\n",
++ path, strerror(errno));
++ goto exit;
++ }
++ }
++ snprintf(path, sizeof(path), "%s/zypp/repos.d/%s.repo",
++ sysconfdir, sw_source->name);
++ file = fopen(path, "w");
++ if (!file) {
++ rpmlog(RPMLOG_ERR, "Failed to open %s: %s\n",
++ path, strerror(errno));
++ goto exit;
++ }
++ snprintf(data, sizeof(data),
++ "[%s]\n"
++ "name=%s\n"
++ "enabled=1\n"
++ "autorefresh=0\n"
++ "baseurl=%s\n"
++ "type=%s\n"
++ "keeppackages=0\n",
++ sw_source->name, sw_source->name, access->data,
++ (access->type ? access->type : "NONE"));
++
++ if (fputs(data, file) == EOF) {
++ rpmlog(RPMLOG_ERR, "Failed to write %s: %s\n",
++ path, strerror(errno));
++ goto exit;
++ }
++ rpmlog(RPMLOG_INFO, "added zypper repository %s for sw source %s\n",
++ path, sw_source->name);
++
++ ret = 0;
++ exit:
++ if (file) fclose(file);
++ msmFreePointer((void**)&sysconfdir);
++
++ return ret;
++}
++
++static int msmSetSmackSWSource(struct smack_accesses *smack_accesses, sw_source_x *sw_source)
++{
++ package_x *package, *temp;
++ provide_x *provide;
++
++ if (!allpackages) return 0;
++
++ if (sw_source->older) {
++ ac_domain_x *ac_domain, *temp;
++ /* remove old domain rules in case of upgrade */
++ //smack_rule_set_remove_by_subject(rule_set, sw_source->name, NULL);
++ /* make sure domain's credentials point to upgraded domain */
++ HASH_ITER(hh, all_ac_domains, ac_domain, temp) {
++ if (ac_domain->sw_source == sw_source->older)
++ ac_domain->sw_source = sw_source;
++ }
++ }
++
++ /* iterate through all packages to create smack rules for the domain */
++ HASH_ITER(hh, allpackages, package, temp) {
++ if (sw_source->older) {
++ /* make sure domain's packages point to upgraded domain */
++ if (package->sw_source == sw_source->older)
++ package->sw_source = sw_source;
++ }
++ if (!package->newer) {
++ for (provide = package->provides; provide; provide = provide->prev) {
++ if (msmSetSmackProvide(smack_accesses, provide, package->sw_source))
++ return -1;
++ }
++ }
++ }
++ return 0;
++}
++
++int msmSetupSWSources(struct smack_accesses *smack_accesses, manifest_x *mfx, rpmts ts)
++{
++ sw_source_x *sw_source;
++ origin_x *origin;
++ keyinfo_x *keyinfo;
++ access_x *access;
++ ac_domain_x *allow;
++ ac_domain_x *deny;
++ ac_domain_x *ac_domain;
++ int ret;
++ rpmRC rc;
++
++ LISTHEAD(mfx->sw_sources, sw_source);
++
++ while (sw_source) {
++ sw_source_x *next = sw_source->next;
++ sw_source_x *parent = sw_source->parent;
++ if (ts) {
++ for (origin = sw_source->origins; origin; origin = origin->prev) {
++ for (keyinfo = origin->keyinfos; keyinfo; keyinfo = keyinfo->prev) {
++ rpmlog(RPMLOG_INFO, "setting keyinfo for sw source %s\n",
++ sw_source->name);
++ rc = rpmtsImportPubkey(ts, keyinfo->keydata, keyinfo->keylen);
++ if (rc != RPMRC_OK) {
++ rpmlog(RPMLOG_ERR, "Key import failed for sw source %s\n",
++ sw_source->name);
++ return rc;
++ }
++ }
++ for (access = origin->accesses; access; access = access->prev) {
++ rpmlog(RPMLOG_INFO, "setting access %s for sw source %s\n",
++ access->data, sw_source->name);
++ if (origin->type && !strcmp(origin->type, "ZYPPER")) {
++ ret = msmSetupZypperRepo(access, sw_source);
++ if (ret) {
++ rpmlog(RPMLOG_ERR,
++ "Failed to set access %s for sw source %s\n",
++ access->data, sw_source->name);
++ return ret;
++ }
++ }
++ }
++ }
++ } else {
++
++ /* config processing */
++ ret = msmSetupPackages(NULL, sw_source->packages, NULL);
++ if (ret) {
++ rpmlog(RPMLOG_ERR, "Setup packages failed for sw source %s\n",
++ sw_source->name);
++ return ret;
++ }
++ }
++ if (ts) {
++ for (allow = sw_source->allows; allow; allow = allow->hh.next) {
++ HASH_FIND(hh, all_ac_domains, allow->name, strlen(allow->name), ac_domain);
++ if (ac_domain) {
++ rpmlog(RPMLOG_INFO, "sw source %s allows access to ac domain %s\n",
++ sw_source->name, allow->name);
++ } else {
++ rpmlog(RPMLOG_WARNING, "sw source %s allows access to ac domain %s which doesn't exist\n",
++ sw_source->name, allow->name);
++ }
++ }
++ for (allow = sw_source->allowmatches; allow; allow = allow->prev)
++ rpmlog(RPMLOG_INFO, "sw source %s allows access to ac domain match %s\n",
++ sw_source->name, allow->match);
++
++ for (deny = sw_source->denys; deny; deny = deny->hh.next) {
++ HASH_FIND(hh, all_ac_domains, deny->name, strlen(deny->name), ac_domain);
++ if (ac_domain) {
++ rpmlog(RPMLOG_INFO, "sw source %s denies access to ac domain %s\n",
++ sw_source->name, deny->name);
++ } else {
++ rpmlog(RPMLOG_WARNING, "sw source %s denies access to ac domain %s which doesn't exist\n",
++ sw_source->name, deny->name);
++ }
++ }
++ for (deny = sw_source->denymatches; deny; deny = deny->prev)
++ rpmlog(RPMLOG_INFO, "sw source %s denies access to ac domain match %s\n",
++ sw_source->name, deny->match);
++
++ if (parent) {
++ if (strcmp(parent->name, sw_source->name)) {
++ sw_source_x *older;
++ for (older = parent; older; older = older->next) {
++ if (!strcmp(sw_source->name, older->name)) {
++ sw_source->older = older;
++ older->newer = sw_source;
++ break;
++ }
++ }
++ } else if (!parent->parent) {
++ /* root sw_source upgrade */
++ sw_source->older = parent;
++ parent->newer = sw_source;
++ sw_source->parent = NULL;
++ } else return -1;
++
++ LISTDEL(mfx->sw_sources, sw_source); /* take out from sw sources list */
++ NODEADD(parent, sw_source); /* add to sw source tree */
++ }
++
++ /* set smack rules for the new/upgraded sw source */
++ ret = msmSetSmackSWSource(smack_accesses, sw_source);
++ if (ret) {
++ rpmlog(RPMLOG_ERR, "Setting smack rules failed for sw source %s\n",
++ sw_source->name);
++ return ret;
++ }
++
++ }
++ sw_source = next;
++ }
++ return 0;
++}
++
++static void msmRemoveDBusConfig(package_x *package, dbus_x *dbuss)
++{
++ dbus_x *dbus;
++
++ for (dbus = dbuss; dbus; dbus = dbus->prev) {
++ char path[NAME_MAX+1];
++ snprintf(path, sizeof(path), "/etc/dbus-1/%s.d/manifest.%s.conf",
++ dbus->bus, package->name);
++ unlink(path);
++ }
++}
++
++static int msmSetupDBusRule(FILE *file, const char *creds, int type, const char *service, const char *name, const char *parentType, const char *parentValue)
++{
++ char data[1024];
++
++ if (creds && *creds) {
++ switch (type) {
++ case DBUS_SERVICE:
++ snprintf(data, sizeof(data),
++ " <policy context=\"default\">\n"
++ " <deny send_destination=\"%s\"/>\n"
++ " </policy>\n"
++ " <policy smack=\"%s\">\n"
++ " <allow send_destination=\"%s\"/>\n"
++ " </policy>\n",
++ name, creds, name);
++ break;
++ case DBUS_PATH:
++ snprintf(data, sizeof(data),
++ " <policy context=\"default\">\n"
++ " <deny send_destination=\"%s\" send_path=\"%s\"/>\n"
++ " <deny receive_sender=\"%s\" receive_path=\"%s\"/>\n"
++ " </policy>\n"
++ " <policy smack=\"%s\">\n"
++ " <allow send_destination=\"%s\" send_path=\"%s\"/>\n"
++ " <allow receive_sender=\"%s\" receive_path=\"%s\"/>\n"
++ " </policy>\n",
++ service, name, service, name, creds,
++ service, name, service, name);
++ break;
++ case DBUS_INTERFACE:
++ snprintf(data, sizeof(data),
++ " <policy context=\"default\">\n"
++ " <deny send_destination=\"%s\" send_interface=\"%s\"/>\n"
++ " <deny receive_sender=\"%s\" receive_interface=\"%s\"/>\n"
++ " </policy>\n"
++ " <policy smack=\"%s\">\n"
++ " <allow send_destination=\"%s\" send_interface=\"%s\"/>\n"
++ " <allow receive_sender=\"%s\" receive_interface=\"%s\"/>\n"
++ " </policy>\n",
++ service, name, service, name, creds,
++ service, name, service, name);
++ break;
++ case DBUS_METHOD:
++ snprintf(data, sizeof(data),
++ " <policy context=\"default\">\n"
++ " <deny send_destination=\"%s\" send_%s=\"%s\" send_member=\"%s\"/>\n"
++ " </policy>\n"
++ " <policy smack=\"%s\">\n"
++ " <allow send_destination=\"%s\" send_%s=\"%s\" send_member=\"%s\"/>\n"
++ " </policy>\n",
++ service, parentType, parentValue, name, creds,
++ service, parentType, parentValue, name);
++ break;
++ case DBUS_SIGNAL:
++ snprintf(data, sizeof(data),
++ " <policy context=\"default\">\n"
++ " <deny receive_sender=\"%s\" receive_%s=\"%s\" receive_member=\"%s\"/>\n"
++ " </policy>\n"
++ " <policy smack=\"%s\">\n"
++ " <allow receive_sender=\"%s\" receive_%s=\"%s\" receive_member=\"%s\"/>\n"
++ " </policy>\n",
++ service, parentType, parentValue, name, creds,
++ service, parentType, parentValue, name);
++ break;
++ default:
++ return -1;
++ }
++ } else {
++ switch (type) {
++ case DBUS_SERVICE:
++ snprintf(data, sizeof(data),
++ " <policy context=\"default\">\n"
++ " <allow send_destination=\"%s\"/>\n"
++ " </policy>\n",
++ name);
++ break;
++ case DBUS_PATH:
++ snprintf(data, sizeof(data),
++ " <policy context=\"default\">\n"
++ " <allow send_destination=\"%s\" send_path=\"%s\"/>\n"
++ " <allow receive_sender=\"%s\" receive_path=\"%s\"/>\n"
++ " </policy>\n",
++ service, name, service, name);
++ break;
++ case DBUS_INTERFACE:
++ snprintf(data, sizeof(data),
++ " <policy context=\"default\">\n"
++ " <allow send_destination=\"%s\" send_interface=\"%s\"/>\n"
++ " <allow receive_sender=\"%s\" receive_interface=\"%s\"/>\n"
++ " </policy>\n",
++ service, name, service, name);
++ break;
++ case DBUS_METHOD:
++ snprintf(data, sizeof(data),
++ " <policy context=\"default\">\n"
++ " <allow send_destination=\"%s\" send_%s=\"%s\" send_member=\"%s\"/>\n"
++ " </policy>\n",
++ service, parentType, parentValue, name);
++ break;
++ case DBUS_SIGNAL:
++ snprintf(data, sizeof(data),
++ " <policy context=\"default\">\n"
++ " <allow receive_sender=\"%s\" receive_%s=\"%s\" receive_member=\"%s\"/>\n"
++ " </policy>\n",
++ service, parentType, parentValue, name);
++ break;
++ default:
++ return -1;
++ }
++ }
++ if (fputs(data, file) == EOF) {
++ rpmlog(RPMLOG_ERR, "Failed to write DBus rule %s: %s\n",
++ data, strerror(errno));
++ return -1;
++ }
++ return 0;
++}
++
++static int msmSetupDBusConfig(package_x *package, dbus_x *dbus, int phase)
++{
++ char path[NAME_MAX+1];
++ FILE *file = NULL;
++ char data[512];
++ node_x *node;
++ interface_x *interface;
++ member_x *member;
++ int ret = -1;
++
++ char *sysconfdir = rpmExpand("%{?_sysconfdir}", NULL);
++ if (!sysconfdir || !strcmp(sysconfdir, "")) {
++ rpmlog(RPMLOG_ERR, "Failed to expand %%_sysconfdir macro\n");
++ goto exit;
++ }
++ snprintf(path, sizeof(path), "%s/dbus-1/%s.d/manifest.%s.conf",
++ sysconfdir, dbus->bus, package->name);
++
++ file = fopen(path, phase ? "a" : "w");
++ if (!file) {
++ rpmlog(RPMLOG_ERR, "Cannot open %s: %s\n", path, strerror(errno));
++ goto exit;
++ }
++
++ if (phase == 0) {
++ snprintf(data, sizeof(data),
++ "<!-- This configuration is automatically generated from Manifest by RPM %s security plugin -->\n"
++ "<!DOCTYPE busconfig PUBLIC \"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN\" \"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd\">\n"
++ "<busconfig>\n",
++ rpmEVR);
++ if (fputs(data, file) == EOF) {
++ rpmlog(RPMLOG_ERR, "Failed to write %s: %s\n",
++ path, strerror(errno));
++ goto exit;
++ }
++ }
++
++ if (phase >= 0) {
++ if (dbus->own) {
++ snprintf(data, sizeof(data),
++ " <policy context=\"default\">\n"
++ " <deny own=\"%s\"/>\n"
++ " </policy>\n"
++ " <policy smack=\"%s\">\n"
++ " <allow own=\"%s\"/>\n"
++ " </policy>\n",
++ dbus->name, dbus->own, dbus->name);
++ if (fputs(data, file) == EOF) {
++ rpmlog(RPMLOG_ERR, "Failed to write %s: %s\n",
++ path, strerror(errno));
++ goto exit;
++ }
++ }
++ if (dbus->annotation) {
++ msmSetupDBusRule(file, dbus->annotation->value, DBUS_SERVICE,
++ NULL, dbus->name, NULL, NULL);
++ }
++ for (node = dbus->nodes; node; node = node->prev) {
++ if (node->annotation) {
++ msmSetupDBusRule(file, node->annotation->value, DBUS_PATH,
++ dbus->name, node->name, NULL, NULL);
++ }
++ for (member = node->members; member; member = member->prev) {
++ if (member->annotation) {
++ msmSetupDBusRule(file, member->annotation->value, member->type,
++ dbus->name, member->name,
++ "path", node->name);
++ }
++ }
++ for (interface = node->interfaces; interface; interface = interface->prev) {
++ if (interface->annotation) {
++ msmSetupDBusRule(file, interface->annotation->value, DBUS_INTERFACE,
++ dbus->name, interface->name, NULL, NULL);
++ }
++ for (member = interface->members; member; member = member->prev) {
++ if (member->annotation) {
++ msmSetupDBusRule(file, member->annotation->value, member->type,
++ dbus->name, member->name,
++ "interface", interface->name);
++ }
++ }
++ }
++ }
++ }
++
++ if (phase < 0) {
++ snprintf(data, sizeof(data), "</busconfig>\n");
++ if (fputs(data, file) == EOF) {
++ rpmlog(RPMLOG_ERR, "Failed to write %s: %s\n",
++ path, strerror(errno));
++ goto exit;
++ }
++ rpmlog(RPMLOG_INFO, "wrote dbus config %s\n", path);
++ }
++ ret = 0;
++
++ exit:
++ if (file) fclose(file);
++ if (ret) unlink(path);
++ msmFreePointer((void**)&sysconfdir);
++
++ return ret;
++}
++
++static int msmIsRequestAllowed(manifest_x *mfx, ac_domain_x *provided)
++{
++
++ if (mfx->sw_source == provided->sw_source) {
++ /* allowed always if ac domain is provided in the same sw source */
++ return 1;
++ } else if (provided->origin && !strcmp(provided->origin, "current")) {
++ /* denied if ac domain is only meant for current sw source */
++ return 0;
++ }
++ if (provided->origin && !strcmp(provided->origin, "all")) {
++ /* ac_domain is allowed for all sw sources */
++ return 1;
++ }
++ if (!provided->origin || !strcmp(provided->origin, "trusted")) {
++ if (strcmp(mfx->sw_source->rankkey, provided->sw_source->rankkey) < 0) {
++ /* higher ranked sw sources are allowed if ac domain is trusted */
++ return 1;
++ } /* else flow through to check denys and allows below */
++ } else return 0;
++
++ return msmCheckACDomainRules(provided, mfx->sw_source, provided->sw_source);
++}
++
++static int msmCheckDomainJoinPossibility(manifest_x *mfx, ac_domain_x *defined_ac_domain)
++{
++
++ char *tmp = NULL, *pch = NULL;
++ unsigned int found = 0;
++
++ if ((!mfx) || (!defined_ac_domain))
++ return -1;
++
++ if (defined_ac_domain->type) {
++ if (strcmp(defined_ac_domain->type, "restricted") == 0) {
++ if (defined_ac_domain->plist) {
++ tmp = calloc(strlen(defined_ac_domain->plist) + 1, sizeof(char));
++ if (!tmp) return -1;
++ strncpy(tmp, defined_ac_domain->plist, strlen(defined_ac_domain->plist));
++ pch = strtok (tmp, ", ");
++ while (pch != NULL)
++ {
++ if (strcmp(pch, mfx->name) == 0) {
++ found = 1;
++ break;
++ }
++ pch = strtok(NULL, ", ");
++ }
++ msmFreePointer((void**)&tmp);
++ }
++ if (found != 1) {
++ rpmlog(RPMLOG_ERR, "Request for a domain name %s isn't allowed ", mfx->request->ac_domain);
++ rpmlog(RPMLOG_ERR, "because ac domain is marked as restricted\n");
++ return -1;
++ }
++ } else if (strcmp(defined_ac_domain->type, "shared") == 0) {
++ return 0;
++ } else {
++ // domain hasn't been marked as shared
++ rpmlog(RPMLOG_ERR, "Request for a domain name %s isn't allowed ", mfx->request->ac_domain);
++ rpmlog(RPMLOG_ERR, "because ac domain is marked as private\n");
++ return -1;
++ }
++ } else {
++ // by default ac domains are private
++ rpmlog(RPMLOG_ERR, "Request for a domain name %s isn't allowed ", mfx->request->ac_domain);
++ rpmlog(RPMLOG_ERR, "because ac domain is marked as private\n");
++ return -1;
++ }
++
++ return 0;
++}
++
++int msmSetupRequests(manifest_x *mfx)
++{
++
++ ac_domain_x *defined_ac_domain = NULL;
++
++ if ((!mfx) || (!mfx->request) || (!mfx->request->ac_domain))
++ return -1;
++
++ HASH_FIND(hh, all_ac_domains, mfx->request->ac_domain, strlen(mfx->request->ac_domain), defined_ac_domain);
++ if (!defined_ac_domain){ // request for a undefined domain.
++ rpmlog(RPMLOG_ERR, "Request for a domain name %s that hasn't been yet defined by any package\n", mfx->request->ac_domain);
++ return -1;
++ }
++
++ //now check that the package can join the requested AC domain
++
++ if (mfx->define){
++ rpmlog(RPMLOG_DEBUG, "mfx->define->name %s mfx->request->ac_domain %s\n", mfx->define->name, mfx->request->ac_domain);
++ if (strcmp(mfx->define->name, mfx->request->ac_domain) == 0)
++ //ac domain is requested from the same package where it was define. This case is always allowed
++ return 0;
++ }
++
++ //need to check if developer allowed other packages to join this domain
++ if (msmCheckDomainJoinPossibility(mfx, defined_ac_domain) < 0 )
++ return -1;
++
++ // now checking if security policy allows to join this domain
++ if (msmIsRequestAllowed(mfx, defined_ac_domain)) {
++ rpmlog(RPMLOG_INFO, "Request for a domain name %s is allowed based on package sw source\n", mfx->request->ac_domain);
++ return 0;
++
++ } else {
++ rpmlog(RPMLOG_ERR, "Request for a domain name %s isn't allowed based on package sw source\n", mfx->request->ac_domain);
++ return -1;
++ }
++}
++
++static int msmSetupProvides(struct smack_accesses *smack_accesses, package_x *package)
++{
++ provide_x *provide;
++ ac_domain_x *ac_domain;
++
++ for (provide = package->provides; provide; provide = provide->prev) {
++ for (ac_domain = provide->ac_domains; ac_domain; ac_domain = ac_domain->prev) {
++ ac_domain_x *current_d = NULL;
++ ac_domain->origin = provide->origin;
++
++ HASH_FIND(hh, all_ac_domains, ac_domain->name, strlen(ac_domain->name), current_d);
++
++ if (current_d) { /* ac domain has been previously defined */
++
++ if (strcmp(ac_domain->pkg_name, current_d->pkg_name) == 0) { /* check that it was provided by same package */
++ HASH_DELETE(hh, all_ac_domains, current_d);
++ HASH_ADD_KEYPTR(hh, all_ac_domains, ac_domain->name, strlen(ac_domain->name), ac_domain);
++ current_d->newer = ac_domain;
++ ac_domain->older = current_d;
++ rpmlog(RPMLOG_INFO, "package %s upgraded ac domain %s\n", ac_domain->pkg_name, ac_domain->name);
++
++ } else {
++ rpmlog(RPMLOG_ERR, "package %s can't upgrade ac domain %s previously defined in package %s\n",
++ ac_domain->pkg_name, ac_domain->name, current_d->pkg_name);
++ return -1;
++ }
++ } else {
++ HASH_ADD_KEYPTR(hh, all_ac_domains, ac_domain->name, strlen(ac_domain->name), ac_domain);
++ rpmlog(RPMLOG_INFO, "package %s defined ac domain %s\n", ac_domain->pkg_name, ac_domain->name);
++ }
++ }
++ int ret = msmSetSmackProvide(smack_accesses, provide, package->sw_source);
++
++ if (ret < 0) {
++ rpmlog(RPMLOG_ERR, "Failed to set smack rules for provide\n");
++ return -1;
++ }
++ }
++ return 0;
++}
++
++int msmSetupDBusPolicies(package_x *package)
++{
++
++ dbus_x *session = NULL;
++ dbus_x *system = NULL;
++ provide_x *provide;
++ dbus_x *dbus;
++
++ for (provide = package->provides; provide; provide = provide->prev) {
++ for (dbus = provide->dbuss; dbus; dbus = dbus->prev) {
++ if (!strcmp(dbus->bus, "session")) {
++ msmSetupDBusConfig(package, dbus, session ? 1 : 0);
++ session = dbus;
++ } else if (!strcmp(dbus->bus, "system")) {
++ msmSetupDBusConfig(package, dbus, system ? 1 : 0);
++ system = dbus;
++ } else return -1;
++ }
++ if (session) msmSetupDBusConfig(package, session, -1);
++ if (system) msmSetupDBusConfig(package, system, -1);
++ session = system = NULL;
++ }
++ return 0;
++
++}
++
++static int msmCheckDomainRequestOrPermit(manifest_x *mfx, const char* domain)
++{
++
++ ac_domain_x *defined_ac_domain = NULL;
++ char* name = NULL;
++
++ if ((!mfx) || (!domain))
++ return -1;
++
++ name = calloc(strlen(domain) + 1, sizeof(char));
++ if (!name) return -1;
++ strncpy(name, domain, strlen(domain));
++ strtok(name, ":"); // remove label name if present
++ rpmlog(RPMLOG_DEBUG, "label name %s domain name %s \n", domain, name);
++
++ HASH_FIND(hh, all_ac_domains, name, strlen(name), defined_ac_domain);
++ if (!defined_ac_domain) { // request or permit for an undefined domain.
++ rpmlog(RPMLOG_ERR, "A domain name %s hasn't been yet defined by any package. Can't verify if it is allowed\n", name);
++ msmFreePointer((void**)&name);
++ return -1;
++ }
++
++ //now check that this ac_domain can be requested
++
++ if ((mfx->define) && (mfx->define->name)) {
++ rpmlog(RPMLOG_DEBUG, "mfx->define->name %s domain %s\n", mfx->define->name, name);
++ if (strcmp(mfx->define->name, name) == 0) {
++ // AC domain access is requested or permitted from the same package where it was defined.
++ // This case is always allowed
++ msmFreePointer((void**)&name);
++ return 0;
++ }
++ }
++
++ // no need to check if developer allowed other packages to request/permit this domain
++ // because this isn't a request to belong to a domain, but request/permit for domain access
++
++ if (msmIsRequestAllowed(mfx, defined_ac_domain)) {
++ // request or permit is allowed by domain policy
++ rpmlog(RPMLOG_DEBUG, "Request/Permit to access a domain name %s is allowed based on package sw source\n", name);
++ msmFreePointer((void**)&name);
++ return 0;
++
++ } else {
++ rpmlog(RPMLOG_ERR, "Request/Permit to access a domain name %s isn't allowed based on package sw source\n", name);
++ msmFreePointer((void**)&name);
++ return -1;
++ }
++}
++
++int msmSetupDefine(struct smack_accesses *smack_accesses, manifest_x *mfx)
++{
++ d_request_x *d_request;
++ d_permit_x *d_permit;
++ ac_domain_x * defined_ac_domain = NULL;
++ int ret;
++
++ if ( (!mfx) || (!mfx->define) || (!mfx->define->name)) {
++ rpmlog(RPMLOG_ERR, "Failed to setup define with empty name\n");
++ return -1;
++ }
++
++ /* need to check if domain hasn't been already defined by other package */
++
++ HASH_FIND(hh, all_ac_domains, mfx->define->name, strlen(mfx->define->name), defined_ac_domain);
++ if ((defined_ac_domain) && (defined_ac_domain->pkg_name)) { // this domain has been previously defined
++ if (strcmp(defined_ac_domain->pkg_name, mfx->name) != 0) {
++ rpmlog(RPMLOG_ERR, "Attempt to define a domain name %s that has been already defined by package %s\n",
++ mfx->define->name, defined_ac_domain->pkg_name);
++ return -1;
++ }
++
++ }
++
++ if (mfx->define->d_requests) {
++ for (d_request = mfx->define->d_requests; d_request; d_request = d_request->prev) {
++ // first check if the current's package sw source can grant access to requested domain
++ if ( msmCheckDomainRequestOrPermit(mfx, d_request->label_name) < 0 )
++ return -1;
++ if ( smack_accesses_add(smack_accesses, mfx->define->name, d_request->label_name, d_request->ac_type) < 0 ) {
++ rpmlog(RPMLOG_ERR, "Failed to set smack rules for domain requests\n");
++ return -1;
++ }
++
++ }
++ }
++
++ if (mfx->define->d_permits) {
++ for (d_permit = mfx->define->d_permits; d_permit; d_permit = d_permit->prev) {
++ // first check if the current's package sw source can grant access to permited domain
++ if ( msmCheckDomainRequestOrPermit(mfx, d_permit->label_name) < 0 )
++ return -1;
++ if (!d_permit->to_label_name)
++ ret = smack_accesses_add(smack_accesses, d_permit->label_name, mfx->define->name, d_permit->ac_type);
++ else {
++ if ( msmCheckLabelProvisioning(mfx, d_permit->to_label_name) < 0 )
++ return -1;
++ ret = smack_accesses_add(smack_accesses, d_permit->label_name, d_permit->to_label_name, d_permit->ac_type);
++ }
++ if (ret < 0) {
++ rpmlog(RPMLOG_ERR, "Failed to set smack rules for domain permits\n");
++ return -1;
++ }
++ }
++ }
++
++ return 0;
++}
++
++package_x *msmCreatePackage(const char *name, sw_source_x *sw_source, provide_x *provides, const char *modified)
++{
++ if (!name) return NULL;
++
++ package_x *package = calloc(1, sizeof(package_x));
++ if (package) {
++ package->name = strdup(name);
++ if (!package->name) goto exit;
++ package->sw_source = sw_source;
++ package->provides = provides;
++ if (modified) {
++ package->modified = strdup(modified);
++ if (!package->modified) goto exit;
++ }
++ }
++ return package;
++
++ exit:
++ msmFreePointer((void**)&package->name);
++ msmFreePointer((void**)&package->modified);
++ msmFreePointer((void**)&package);
++
++ return NULL;
++}
++
++int msmSetupSmackRules(struct smack_accesses *smack_accesses, const char* package_name, int flag, int SmackEnabled)
++{
++ int ret = 0;
++ char * buffer = calloc(strlen(SMACK_RULES_PATH) + strlen(package_name) + 1, sizeof(char));
++ if (!buffer) return -1;
++ strncpy(buffer, SMACK_RULES_PATH, strlen(SMACK_RULES_PATH));
++ strncpy(buffer + strlen(SMACK_RULES_PATH), package_name, strlen(package_name));
++ rpmlog(RPMLOG_DEBUG, "smack rule file path %s, SmackEnabled %d\n", buffer, SmackEnabled);
++
++ if (flag == SMACK_UNINSTALL) { /* uninstallation case */
++ FILE* fd = fopen(buffer, "r");
++ if (fd) {
++ rpmlog(RPMLOG_DEBUG, "uninstall case \n");
++ struct smack_accesses *old_rule_set = NULL;
++ ret = smack_accesses_new(&old_rule_set);
++ if (ret != 0) return -1;
++ ret = smack_accesses_add_from_file(old_rule_set, fileno(fd));
++ if (ret == 0) {
++ if (SmackEnabled == 1)
++ ret = smack_accesses_clear(old_rule_set); /* deletes rules from kernel */
++
++ }
++ smack_accesses_free(old_rule_set);
++ fclose(fd);
++ remove(buffer); /* delete rules file from system */
++ }
++ } else { /*installation case */
++ /* first attempt to clean previous version of rules, if exists */
++ FILE* fd = fopen(buffer, "r");
++ if (fd) {
++ struct smack_accesses *old_rule_set = NULL;
++ ret = smack_accesses_new(&old_rule_set);
++ if (ret != 0) return -1;
++ ret = smack_accesses_add_from_file(old_rule_set, fileno(fd));
++ if (ret == 0) {
++ if (SmackEnabled == 1)
++ ret = smack_accesses_clear(old_rule_set); /* deletes old rules from kernel */
++ }
++ fclose(fd);
++ smack_accesses_free(old_rule_set);
++ }
++ /* now write new rules to the system */
++ fd = fopen(buffer, "w");
++ if (!fd) {
++ rpmlog(RPMLOG_ERR, "Can't write smack rules\n");
++ return -1;
++ }
++ ret = smack_accesses_save(smack_accesses, fileno(fd));
++ rpmlog(RPMLOG_DEBUG, "ret in installation %d\n", ret);
++ if (!ret) {
++ if (SmackEnabled == 1)
++ ret = smack_accesses_apply(smack_accesses);
++ }
++ fclose(fd);
++ }
++
++ free(buffer);
++ if (ret)
++ return -1;
++ return 0;
++
++}
++
++int msmSetupPackages(struct smack_accesses *smack_accesses, package_x *packages, sw_source_x *sw_source)
++{
++ package_x *package, *first = NULL;
++ char *p_rankkey, *c_rankkey;
++ for (package = packages; package; package = package->prev) {
++ package_x *current_p;
++ rpmlog(RPMLOG_DEBUG, "before HASH_FIND, package->name %s\n", package->name);
++ HASH_FIND(hh, allpackages, package->name, strlen(package->name), current_p);
++ rpmlog(RPMLOG_DEBUG, "after HASH_FIND\n");
++ if (current_p) {
++ if (!current_p->sw_source) {
++ return -1;
++ }
++ p_rankkey = strdup(package->sw_source->rankkey);
++ c_rankkey = strdup(current_p->sw_source->rankkey);
++ p_rankkey = strtok(p_rankkey, ".");
++ c_rankkey = strtok(c_rankkey, ".");
++ /* this is an upgrade, remove old one from config */
++ if ((strcmp(p_rankkey, c_rankkey) < 0) ||
++ (strcmp(package->sw_source->name, current_p->sw_source->name) == 0)) {
++ HASH_DELETE(hh, allpackages, current_p);
++ rpmlog(RPMLOG_INFO, "sw source %s upgraded package %s previously provided in sw source %s\n",
++ package->sw_source->name, package->name, current_p->sw_source->name);
++ current_p->newer = package;
++ package->older = current_p;
++ } else {
++ /* upgrade from lower or similary ranked sw source is not allowed */
++ rpmlog(RPMLOG_ERR, "sw source %s tried to upgrade package %s previously provided in sw source %s\n",
++ package->sw_source->name, package->name, current_p->sw_source->name);
++ return -1;
++ }
++ msmFreePointer((void**)&p_rankkey);
++ msmFreePointer((void**)&c_rankkey);
++ } else {
++ if (sw_source) {
++ rpmlog(RPMLOG_INFO, "sw source %s provided package %s\n", package->sw_source->name, package->name);
++ }
++ }
++ rpmlog(RPMLOG_DEBUG, "before HASH_ADD_KEYPTR\n");
++ HASH_ADD_KEYPTR(hh, allpackages, package->name, strlen(package->name), package);
++ /* set sw source smack rules*/
++ if ((msmSetupProvides(smack_accesses, package)) < 0 ) {
++ msmCancelPackage(package->name);
++ return -1;
++ }
++ first = package;
++ }
++ if (sw_source && packages) {
++ /* catenate list to sw_source config */
++ LISTCAT(sw_source->packages, first, packages);
++ }
++ return 0;
++}
++
++package_x *msmCheckPackage(const char *name)
++{
++ package_x *package = NULL;
++
++ if (name)
++ HASH_FIND(hh, allpackages, name, strlen(name), package);
++
++ return package;
++}
++
++static void msmCancelACDomain(const char *name)
++{
++ if (name) {
++ ac_domain_x *domain;
++ HASH_FIND(hh, all_ac_domains, name, strlen(name), domain);
++ if (domain) {
++ HASH_DELETE(hh, all_ac_domains, domain);
++ if (domain->older) {
++ /* resume previous version */
++ HASH_ADD_KEYPTR(hh, all_ac_domains, domain->older->name, strlen(domain->older->name), domain->older);
++ domain->older->older = domain->older->newer;
++ domain->older->newer = NULL;
++ domain->newer = domain->older;
++ domain->older = NULL;
++ } else {
++ /* no previous, just take this one out */
++ domain->newer = domain;
++ }
++ }
++ }
++}
++
++void msmCancelPackage(const char *name)
++{
++ provide_x *provide;
++ ac_domain_x *ac_domain;
++
++ if (name) {
++ package_x *package;
++ HASH_FIND(hh, allpackages, name, strlen(name), package);
++ if (package) {
++ HASH_DELETE(hh, allpackages, package);
++ if (package->older) {
++ /* resume previous version */
++ HASH_ADD_KEYPTR(hh, allpackages, package->older->name, strlen(package->older->name), package->older);
++ package->older->older = package->older->newer;
++ package->older->newer = NULL;
++ package->newer = package->older;
++ package->older = NULL;
++ } else {
++ /* no previous, just take this one out */
++ package->newer = package;
++ }
++ /* need to clean up the all_ac_domain list, too */
++ for (provide = package->provides; provide; provide = provide->prev) {
++ for (ac_domain = provide->ac_domains; ac_domain; ac_domain = ac_domain->prev)
++ msmCancelACDomain(ac_domain->name);
++ }
++ }
++ }
++}
++
++static int is_executable(const char* path, magic_t cookie)
++{
++ const char* buffer = NULL;
++ int result = -1;
++ char* ptr = NULL;
++
++ if ((!path) || (!cookie))
++ return result;
++
++ buffer = magic_file(cookie, path);
++
++ rpmlog(RPMLOG_DEBUG, "buffer: %s\n", buffer);
++
++ if (buffer != NULL) {
++ ptr = strstr(buffer,"executable");
++ if (ptr) result = 0;
++ ptr = strstr(buffer,"ELF");
++ if (ptr) result = 0;
++ }
++
++ return result;
++}
++
++int msmSetFileXAttributes(manifest_x *mfx, const char* filepath, magic_t cookie)
++{
++ provide_x *provide = NULL;
++ filesystem_x *filesystem = NULL;
++ size_t len = 0, match = 0;
++ const char *label = NULL;
++ const char *exec_label = NULL;
++ const char *type = NULL;
++ const char isolatedLabel[] = SMACK_ISOLATED_LABEL;
++ struct stat st;
++
++ if (!filepath) return -1;
++ if (mfx->name) {
++ package_x *package = msmCheckPackage(mfx->name);
++ if (!package)
++ return -1;
++ for (provide = package->provides; provide; provide = provide->prev) {
++ for (filesystem = provide->filesystems; filesystem; filesystem = filesystem->prev) {
++ if (!strcmp(filepath, filesystem->path)) {
++ /* exact match */
++ label = filesystem->label;
++ exec_label = filesystem->exec_label;
++ if (filesystem->type) type = filesystem->type;
++ goto found;
++ }
++
++ len = strlen(filesystem->path);
++ rpmlog(RPMLOG_DEBUG, "filesystem->path: %s, length %d\n", filesystem->path, len);
++ rpmlog(RPMLOG_DEBUG, "filesystem->path + len - 1: %s\n", filesystem->path + len - 1);
++ if (len > match) {
++ if ((!strncmp(filepath, filesystem->path, len)) && (filesystem->type)) {
++ /* partial match and the directory marked as transmutable*/
++ label = filesystem->label;
++ exec_label = filesystem->exec_label;
++ match = len;
++ }
++ if (!strncmp(filesystem->path + len - 1, "*", 1)) {
++ if (!strncmp(filepath, filesystem->path, len - 1)) {
++ /* partial match and the path is marked with wildcard*/
++ label = filesystem->label;
++ exec_label = filesystem->exec_label;
++ match = len - 1;
++ }
++ }
++ }
++ }
++ }
++ } else
++ return -1;
++
++ found:
++ if ((!label) || (!exec_label)) {
++ /* no match, use default label of AC domain */
++ if (mfx->request) { //AC domain is requested in manifest
++ if (mfx->request->ac_domain) {
++ if (!label) label = mfx->request->ac_domain;
++ if (!exec_label) exec_label = mfx->request->ac_domain;
++ } else {
++ rpmlog(RPMLOG_INFO, "Request for AC domain is empty. Can't identify default file label\n");
++ rpmlog(RPMLOG_INFO, "File will be labelled with the label \"Isolated\"\n");
++ if (!label) label = isolatedLabel;
++ if (!exec_label) exec_label = isolatedLabel;
++ }
++ } else if (mfx->define) { // AC domain defined in manifest
++ if (mfx->define->name) {
++ if (!label) label = mfx->define->name;
++ if (!exec_label) exec_label = mfx->define->name;
++ } else {
++ rpmlog(RPMLOG_INFO, "Define for AC domain is empty. Can't identify default file label\n");
++ rpmlog(RPMLOG_INFO, "File will be labelled with the label \"Isolated\"\n");
++ if (!label) label = isolatedLabel;
++ if (!exec_label) exec_label = isolatedLabel;
++ }
++ } else { // no request or definition of domain
++ rpmlog(RPMLOG_INFO, "Both define and request sections are empty. Can't identify default file label\n");
++ rpmlog(RPMLOG_INFO, "File will be labelled with the label \"Isolated\"\n");
++ if (!label) label = isolatedLabel;
++ if (!exec_label) exec_label = isolatedLabel;
++ }
++ }
++
++
++ rpmlog(RPMLOG_INFO, "setting SMACK64 %s for %s\n", label, filepath);
++
++ if (lsetxattr(filepath, SMACK64, label, strlen(label), 0) < 0 ) {
++ rpmlog(RPMLOG_ERR, "Failed to set SMACK64 %s for %s: %s\n",
++ label, filepath, strerror(errno));
++ }
++
++ if ((is_executable(filepath, cookie)) == 0) {
++ if ((exec_label) && (strcmp(exec_label, "none") == 0)) {
++ // do not set SMACK64EXEC
++ rpmlog(RPMLOG_INFO, "not setting SMACK64EXEC for %s as requested in manifest\n", filepath);
++ } else {
++ rpmlog(RPMLOG_INFO, "setting SMACK64EXEC %s for %s\n", exec_label, filepath);
++ if (lsetxattr(filepath, SMACK64EXEC, exec_label, strlen(exec_label), 0) < 0 ) {
++ rpmlog(RPMLOG_ERR, "Failed to set SMACK64EXEC %s for %s: %s\n",
++ exec_label, filepath, strerror(errno));
++ }
++ }
++ }
++
++ if (type) { //marked as transmutable+
++ if ((lstat(filepath, &st) != -1) && (S_ISDIR(st.st_mode))) { //check that it is a directory
++ char at_true[] = "TRUE";
++ rpmlog(RPMLOG_INFO, "setting SMACK64TRANSMUTE %s for %s\n", at_true, filepath);
++ if ( lsetxattr(filepath, SMACK64TRANSMUTE, at_true, strlen(at_true), 0) < 0 ) {
++ rpmlog(RPMLOG_ERR, "Failed to set SMACK64TRANSMUTE %s for %s: %s\n",
++ at_true, filepath, strerror(errno));
++ }
++ } else {
++ rpmlog(RPMLOG_DEBUG, "No setting up of transmute attr for a non-directory, path %s\n",
++ filepath);
++ }
++
++ }
++
++
++
++ return 0;
++
++}
++
++void msmRemoveRules(struct smack_accesses *smack_accesses, manifest_x *mfx, int SmackEnabled)
++{
++ provide_x *provide;
++ package_x *package;
++
++ HASH_FIND(hh, allpackages, mfx->name, strlen(mfx->name), package);
++ if (!package)
++ return;
++
++ if ((mfx->define) || (mfx->sw_sources)) {
++ /* remove smack rule file and rule set from kernel */
++ rpmlog(RPMLOG_DEBUG, "removing smack rules for %s\n", mfx->name);
++ msmSetupSmackRules(smack_accesses, mfx->name, SMACK_UNINSTALL, SmackEnabled);
++ }
++
++ for (provide = mfx->provides; provide; provide = provide->prev) {
++ if (provide->dbuss && !package->older)
++ msmRemoveDBusConfig(package, provide->dbuss);
++
++ }
++
++}
++
++void msmRemoveConfig(manifest_x *mfx)
++{
++ package_x *package;
++
++ HASH_FIND(hh, allpackages, mfx->name, strlen(mfx->name), package);
++ if (package) {
++ if (!package->older) {
++ /* set newer to remove from config list */
++ package->newer = package;
++ rpmlog(RPMLOG_INFO, "removing package for %s\n", mfx->name);
++ }
++ }
++}
++
++sw_source_x *msmSWSourceTreeTraversal(sw_source_x *sw_sources, int (func)(sw_source_x *, void *), void *param)
++{
++ sw_source_x *sw_source;
++
++ if (sw_sources) {
++ LISTHEAD(sw_sources, sw_source);
++ /* sw source tree is actually a list ordered into tree traversal path */
++ for (; sw_source; sw_source = sw_source->next)
++ if (!sw_source->newer)
++ if (!(func)(sw_source, param)) return sw_source;
++ }
++ return NULL;
++}
++
+diff -Nuarp rpm/security/security.h rpm-security/security/security.h
+--- rpm/security/security.h 1970-01-01 02:00:00.000000000 +0200
++++ rpm-security/security/security.h 2012-10-01 10:29:50.327983644 +0300
+@@ -0,0 +1,26 @@
++#include "system.h"
++
++#include <rpm/rpmmacro.h>
++#include <rpm/rpmlib.h>
++#include <rpm/rpmlog.h>
++#include <rpm/rpmts.h>
++#include <rpm/rpmte.h>
++
++#include "rpmio/digest.h"
++#include "lib/rpmsecurity.h"
++
++rpmRC SECURITYHOOK_INIT_FUNC(rpmts ts, const char *opts);
++rpmRC SECURITYHOOK_CLEANUP_FUNC(void);
++rpmRC SECURITYHOOK_PRE_TSM_FUNC(rpmts _ts);
++rpmRC SECURITYHOOK_POST_TSM_FUNC(rpmts _ts);
++rpmRC SECURITYHOOK_PRE_PSM_FUNC(rpmte _te);
++rpmRC SECURITYHOOK_POST_PSM_FUNC(rpmte _te, char * rootDir, int rpmrc);
++rpmRC SECURITYHOOK_SCRIPT_EXEC_FUNC(ARGV_const_t argv);
++rpmRC SECURITYHOOK_FSM_OPENED_FUNC(FSM_t fsm);
++rpmRC SECURITYHOOK_FSM_UPDATED_FUNC(FSM_t fsm);
++rpmRC SECURITYHOOK_FSM_CLOSED_FUNC(FSM_t fsm, int rpmrc);
++rpmRC SECURITYHOOK_FSM_DIR_LABEL_FUNC(FSM_t fsm, int rpmrc);
++rpmRC SECURITYHOOK_VERIFY_FUNC(rpmKeyring keyring, rpmtd sigtd,
++ pgpDig dig, rpmRC rpmrc);
++rpmRC SECURITYHOOK_FILE_CONFLICT_FUNC(rpmts ts, rpmte te, rpmfi fi,
++ Header oldHeader, rpmfi oldFi, int rpmrc);