diff options
Diffstat (limited to 'packaging')
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 Binary files differnew file mode 100644 index 0000000..4a839bc --- /dev/null +++ b/packaging/beecrypt-4.1.2.tar.bz2 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 Binary files differnew file mode 100644 index 0000000..21a743f --- /dev/null +++ b/packaging/db-4.8.30.tar.gz 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 **) ×, &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); |