Re: [Rpm-maint] First attempt for the patch on extending the plugin interface for rpm

2012-10-17 Thread Tero Aho

>>Ok, that'd be good. I was actually wondering why its done the way it is now -
>>if there is an actual reason (such insufficient information available at that
>>point), I'd like to understand it.
>
>My understanding before was that in the current implementation you are able to
>skip the installation of conflicting files without failing the whole package,
>but now when I think of this it doesn't seem like a right thing to do.  I have
>"inherited" these hooks from Tero (in CC now) and while I have done quite some
>changes to them (some I actually still need to sync to open repo that you get
>to see them too), I haven't touched the conflict hook at all.
>
>@Tero, do you still remember the reason why the conflict hook was done in this
>way? Why wasn't it better to check the conflicts before the transaction and
>fail the whole transaction if conflicts are seen?

I'm not quite sure about the context you are talking about here, but I'll tell 
what I 
remember. File conflict hook is called early inside rpmtsPrepare when the 
security 
plugin doesn't yet know much about the package. File conflict hook just records 
the 
conflict and the decision to go ahead takes place in the FSM hook. Overwriting 
the 
conflicting file is allowed if package comes from a higher more trusted domain. 
If it's 
not allowed, then FSM hook returns an error and package processing is canceled.

Btw, there are module tests for different conflict situations here: 
http://meego.gitorious.org/meego-platform-security/rpm/blobs/taho_dev-4.9.x/tests/rpmmssf.at
This link points to the old MeeGo repository since I didn't find these tests in 
your repo.

tero
___
Rpm-maint mailing list
Rpm-maint@lists.rpm.org
http://lists.rpm.org/mailman/listinfo/rpm-maint


[Rpm-maint] [PATCH 1/2] Extending rpm plugin interface, part 1

2012-10-17 Thread Elena Reshetova
This change adds a new type of the rpm plugin, called transaction plugin and a 
set of initial hooks for this plugin.
The hooks are:

PLUGINHOOK_TSM_PRE
Pre-transaction hook that is called before an rpm transaction begins
PLUGINHOOK_TSM_POST
Post-transaction hook that is called after an rpm transaction ends
PLUGINHOOK_PSM_PRE
Pre-transaction-element hook that is called before an rpm transaction-element 
is processed
PLUGINHOOK_PSM_POST
Post-transaction-element hook that is called after an rpm transaction-element 
is processed
PLUGINHOOK_SCRIPT_SETUP
Per-script hook that is called once for each rpm mainainers script that is 
present in the package

Each hook is called for every plugin that have this hook registered.
The avaliable transaction plugins can be specified in macros.in via 
transaction_plugins element.
---
 lib/psm.c |3 +-
 lib/rpmplugins.c  |  118 +
 lib/rpmplugins.h  |   64 -
 lib/rpmscript.c   |   17 +---
 lib/rpmscript.h   |2 +-
 lib/rpmte.c   |   14 ++-
 lib/transaction.c |   39 ++
 plugins/plugin.h  |   14 +++
 8 files changed, 260 insertions(+), 11 deletions(-)

diff --git a/lib/psm.c b/lib/psm.c
index 8f5376d..1a0c27e 100644
--- a/lib/psm.c
+++ b/lib/psm.c
@@ -23,6 +23,7 @@
 #include "lib/rpmfi_internal.h" /* XXX replaced/states... */
 #include "lib/rpmte_internal.h"/* XXX internal apis */
 #include "lib/rpmdb_internal.h" /* rpmdbAdd/Remove */
+#include "lib/rpmts_internal.h" /* ts->plugins */
 #include "lib/rpmscript.h"
 
 #include "debug.h"
@@ -421,7 +422,7 @@ static rpmRC runScript(rpmpsm psm, ARGV_const_t prefixes,
 
 rpmswEnter(rpmtsOp(psm->ts, RPMTS_OP_SCRIPTLETS), 0);
 rc = rpmScriptRun(script, arg1, arg2, sfd,
- prefixes, warn_only, selinux);
+ prefixes, warn_only, selinux, psm->ts->plugins);
 rpmswExit(rpmtsOp(psm->ts, RPMTS_OP_SCRIPTLETS), 0);
 
 /* Map warn-only errors to "notfound" for script stop callback */
diff --git a/lib/rpmplugins.c b/lib/rpmplugins.c
index 9098aa5..bb44f34 100644
--- a/lib/rpmplugins.c
+++ b/lib/rpmplugins.c
@@ -110,6 +110,39 @@ rpmRC rpmpluginsAddCollectionPlugin(rpmPlugins plugins, 
const char *name)
 return rc;
 }
 
+rpmRC rpmpluginsAddTransactionPlugin(rpmPlugins plugins, const char *name)
+{
+char *path;
+char *options;
+int rc = RPMRC_FAIL;
+
+path = rpmExpand("%{?__transaction_",name, "}", NULL);
+if (!path || rstreq(path, "")) {
+   rpmlog(RPMLOG_INFO, _("Failed to expand %%__transaction_%s macro\n"), 
name);
+   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 = rpmpluginsAdd(plugins, name, path, options);
+
+  exit:
+_free(path);
+return rc;
+}
+
 rpmPlugins rpmpluginsFree(rpmPlugins plugins)
 {
 int i;
@@ -195,3 +228,88 @@ rpmRC rpmpluginsCallCollectionPreRemove(rpmPlugins 
plugins, const char *name)
 RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_COLL_PRE_REMOVE);
 return hookFunc();
 }
+
+rpmRC rpmpluginsCallTsmPre(rpmPlugins plugins, rpmts ts)
+{
+rpmRC (*hookFunc)(rpmts);
+int i;
+rpmRC rc = RPMRC_OK;
+const char *name = NULL;
+
+for (i = 0; i < plugins->count; i++) {
+   name = plugins->names[i];
+   RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_TSM_PRE);
+   if ( hookFunc(ts) == RPMRC_FAIL )
+   rc = RPMRC_FAIL;
+}
+
+return rc;
+}
+
+rpmRC rpmpluginsCallTsmPost(rpmPlugins plugins, rpmts ts)
+{
+rpmRC (*hookFunc)(rpmts);
+int i;
+rpmRC rc = RPMRC_OK;
+const char *name = NULL;
+
+for (i = 0; i < plugins->count; i++) {
+   name = plugins->names[i];
+   RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_TSM_POST);
+   if ( hookFunc(ts) == RPMRC_FAIL )
+   rc = RPMRC_FAIL;
+}
+
+return rc;
+}
+
+rpmRC rpmpluginsCallPsmPre(rpmPlugins plugins, rpmte te)
+{
+rpmRC (*hookFunc)(rpmte);
+int i;
+rpmRC rc = RPMRC_OK;
+const char *name = NULL;
+
+for (i = 0; i < plugins->count; i++) {
+   name = plugins->names[i];
+   RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_PSM_PRE);
+   if ( hookFunc(te) == RPMRC_FAIL )
+   rc = RPMRC_FAIL;
+}
+
+return rc;
+}
+
+rpmRC rpmpluginsCallPsmPost(rpmPlugins plugins, rpmte te)
+{
+rpmRC (*hookFunc)(rpmte);
+int i;
+rpmRC rc = RPMRC_OK;
+const char *name = NULL;
+
+for (i = 0; i < plugins->count; i++) {
+   name = plugins->names[i];
+   RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_PSM_POST);
+   if ( hookFunc(te) == RPMRC_FAIL )
+   rc = RPMRC_FAIL;
+}
+
+

[Rpm-maint] [PATCH 2/2] Sample plugin example for testing

2012-10-17 Thread Elena Reshetova
This patch contains a simple sample transaction plugin (sampleplugin) with 
empty hooks.
---
 macros.in   |6 ++
 plugins/Makefile.am |5 +
 plugins/sample-plugin.c |   47 +++
 3 files changed, 58 insertions(+)
 create mode 100644 plugins/sample-plugin.c

diff --git a/macros.in b/macros.in
index f55dcbe..bf49c0b 100644
--- a/macros.in
+++ b/macros.in
@@ -1031,6 +1031,12 @@ done \
 %__collection_sepolicy_flags   1
 
 #--
+# Transaction specific macros
+%__transaction_plugins  sampleplugin
+%__plugindir   %{_libdir}/rpm-plugins
+%__transaction_sampleplugin%{__plugindir}/sampleplugin.so
+
+#--
 # Macros for further automated spec %setup and patch application
 
 # default to plain patch
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index a9c962c..838c21e 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -24,3 +24,8 @@ sepolicy_la_LIBADD = $(top_builddir)/lib/librpm.la 
$(top_builddir)/rpmio/librpmi
 
 plugins_LTLIBRARIES += sepolicy.la
 endif
+
+sampleplugin_la_SOURCES = plugin.h sample-plugin.c
+sampleplugin_la_LIBADD = $(top_builddir)/lib/librpm.la 
$(top_builddir)/rpmio/librpmio.la
+
+plugins_LTLIBRARIES += sampleplugin.la
diff --git a/plugins/sample-plugin.c b/plugins/sample-plugin.c
new file mode 100644
index 000..df38960
--- /dev/null
+++ b/plugins/sample-plugin.c
@@ -0,0 +1,47 @@
+#include "plugin.h"
+
+rpmPluginHook PLUGIN_HOOKS = \
+   PLUGINHOOK_INIT | \
+   PLUGINHOOK_CLEANUP | \
+PLUGINHOOK_TSM_PRE | \
+PLUGINHOOK_TSM_POST | \
+PLUGINHOOK_PSM_PRE | \ 
+PLUGINHOOK_PSM_POST | \
+PLUGINHOOK_SCRIPT_SETUP;
+
+rpmRC PLUGINHOOK_INIT_FUNC(rpmts ts, const char *name, const char *opts)
+{
+return RPMRC_OK;
+}
+
+rpmRC PLUGINHOOK_CLEANUP_FUNC(void)
+{
+return RPMRC_OK;
+}
+
+rpmRC PLUGINHOOK_TSM_PRE_FUNC(rpmts ts)
+{
+return RPMRC_OK;
+}
+
+rpmRC PLUGINHOOK_TSM_POST_FUNC(rpmts ts)
+{
+return RPMRC_OK;
+}
+
+rpmRC PLUGINHOOK_PSM_PRE_FUNC(rpmte te)
+{
+return RPMRC_OK;
+}
+
+rpmRC PLUGINHOOK_PSM_POST_FUNC(rpmte te)
+{
+return RPMRC_OK;
+}
+
+rpmRC PLUGINHOOK_SCRIPT_SETUP_FUNC(char* path)
+{
+rpmlog(RPMLOG_INFO, "Executable path: %s\n", path);
+return RPMRC_OK;
+}
+
-- 
1.7.9.5

___
Rpm-maint mailing list
Rpm-maint@lists.rpm.org
http://lists.rpm.org/mailman/listinfo/rpm-maint


[Rpm-maint] [PATCH 0/2] First five rpm transaction plugin hooks

2012-10-17 Thread Elena Reshetova
Hi,

This patch set contains the transaction plugin definition and 
the first set of new plugin hooks. The second patch also has
the test plugin that can be used to verify the new plugin 
and its hooks. The second patch is just for demostration purpose only. 

Best Regards,
Elena.

Elena Reshetova (2):
  Extending rpm plugin interface, part 1
  Sample plugin example for testing

 lib/psm.c   |3 +-
 lib/rpmplugins.c|  118 +++
 lib/rpmplugins.h|   64 -
 lib/rpmscript.c |   17 ---
 lib/rpmscript.h |2 +-
 lib/rpmte.c |   14 +-
 lib/transaction.c   |   39 
 macros.in   |6 +++
 plugins/Makefile.am |5 ++
 plugins/plugin.h|   14 ++
 plugins/sample-plugin.c |   47 +++
 11 files changed, 318 insertions(+), 11 deletions(-)
 create mode 100644 plugins/sample-plugin.c

-- 
1.7.9.5

___
Rpm-maint mailing list
Rpm-maint@lists.rpm.org
http://lists.rpm.org/mailman/listinfo/rpm-maint


Re: [Rpm-maint] First attempt for the patch on extending the plugin interface for rpm

2012-10-17 Thread Panu Matilainen

On 10/17/2012 11:17 AM, Reshetova, Elena wrote:

@Tero, do you still remember the reason why the conflict hook was
done in this way? Why wasn't it better to check the conflicts before
the transaction and fail the whole transaction if conflicts are seen?


I'm not quite sure about the context you are talking about here, but
I'll tell what I remember. File conflict hook is called early inside
rpmtsPrepare when the security plugin doesn't yet know much about the
package. File conflict hook just records the conflict and the decision
to go ahead takes place in the FSM hook. Overwriting the conflicting
file is allowed if package comes from a higher more trusted domain. If

it's not allowed, then FSM hook returns an error and package processing is
canceled.


The problem is that while failure in FSM is always a possibility,
*planning* to fail there is bad as it breaks the one promise rpm gives

about transactions: transaction will not start when there are known
problems. File conflicts need to be handled early, either by resolving them
or aborting the entire transaction before it really even starts.

Otherwise various calculations will be off, and by the time a package ends

ups in the FSM, some scripts have already been run causing modifications to
the system that can't be undone, plus it can cause broken dependencies to
other packages.


Do you happen to remember what information is missing the conflict

resolution stage? I'd guess that would be something internal to the plugin
as from rpm POV, pretty much everything that is known about the packages is
available in rpmtsPrepare().

Thank you Tero for clarifying! This reminded me the actual reason why
decision can't be made in conflict hook for us. I think I just was too tired
yesterday because I miss the obvious thing. The information we are missing
is the package source (we identify it based on package signature). So,
suppose there is a new package X that is about to be installed. It brings
file A that conflicts with the previously installed file from package Y. At
this moment the verify hook for this package hasn't been called yet, so the
plugin doesn't know who signed package X and can't make a decision if it is
ok to overwrite a file or not. I wonder if we can somehow pass the package
signature to this hook then... I will look into this.


Good, this is just the kind of information and understanding I was 
looking for, and it sounds like a solvable problem - signatures have 
long since been read and verified so its more a matter of remembering 
them in some form that can be accessed from here. Whether by remembering 
the signature itself or the signature -> other id (source or whatever) 
mapping done earlier.


It does also sound like something that could use structural changes to 
rpm itself... and here we are back to the ad-hoc nature of the conflict 
hook arguments (which are the way they are because that's all thats 
available from rpm) :)


I mentioned plans to do some pretty fundamental changes to rpm internals 
that would also affect this: one of those things would a unified package 
"object" that can represent both both already installed packages and the 
to-be-installed packages. So where you currently have an rpmte and a 
header, you'd get two objects of the same type, and those package 
objects could (and would) carry information that's not currently present 
in either rpmte and/or header. The details of how all this will end up 
looking are hazy atm, but just so you know...


- Panu -
___
Rpm-maint mailing list
Rpm-maint@lists.rpm.org
http://lists.rpm.org/mailman/listinfo/rpm-maint


Re: [Rpm-maint] First attempt for the patch on extending the plugin interface for rpm

2012-10-17 Thread Panu Matilainen

On 10/16/2012 07:31 PM, Reshetova, Elena wrote:

Hi,


Obviously there needs to be some way of loading the plugins... What kinda
bothers me here is the notion of "security plugin" - except for perhaps the
signature/conflict hooks, there's nothing inherently security-specific here.



The two immediate candidates *are* security-oriented, but they're very, very
different in what they do and how they affect the system. Eg if you disable
SELinux labeling on a system where SELinux is enabled, you'll pretty much
just shoot yourself in the foot (by ending up with a rather screwed up
system) >rather than fundametally bypass system security.
"Transaction plugin" or something to that effect would seem to be more
appropriate as these hooks could be used for all sorts of purposes
(additional logging / interaction with other systems like dbus notifications
for somebody ... whatever).


Ok, let's call it indeed a "transaction plugin" because security plugin can be
considered as a particular case of transaction plugin. I will rename it.


Thanks. That's the way I see it as well: additional security is just one 
possible application for transaction plugins.





The script setup hook is fairly obvious too, just forgot to mention it.
The one question with that is (again) the argument(s) it receives:
currently its ARGV_t, but does it actually need the entire argv or would just
the actual executable path suffice for the setup?


I am fine with just the path, but looking to SELinux code, the rpm_execcon()
func needs the whole argv struct.

@ Stephen, do you know how mandatory for SELinux is to have the whole argv
struct? Is it just because of rpm_execcon() API or?


Like Stephen already replied, the entire argv is only needed for the 
performing the actual exec through rpm_execcon().



Another possibility might be passing an rpmScript "object" (which would need
exporting and probably added interfaces, but that's kinda in the plans anyway
at some point). But perhaps that's best left for later.


Yes, I guess there is always a possibility  to change these things when better
objects/structs are available. I am quite sure I can make these changes later
since I will be responsible for introducing these hooks at the first place :)
I don't just plan to dump this on you once and go away!


Good to hear :)


I dunno... There are s many different options and API flags that affect
these things, attempting to enforce things from the inside of rpm seems
hopelessly futile: practically every aspect of rpm's behavior is overridable
via cli, API and configuration. Including the paths where rpm loads its
configuration >from. You'd need to have a hard-wired list of mandatory
plugins and theirr non-macro paths compiled rpm to enforce anything at all.
And even then, if you have cli access as root, what's to prevent the user
from just replacing the executable/libraries with something that doesn't
enforce anything?


We can prevent user or malicious app from modifying the rpm itself, its
plugins, configuration files by using the MAC (as selinux or smack) in
run-time and integrity protection (as IMA/EVM) for offline protection. Using
librpm directly by user or program actually should be quite safe, because user
or malicious app won't get any powerful permissions in the most restrictive
setup (no classical root, no posix capabilities). There normally would be some
higher level package manager on top of rpm that would have needed permissions
and would execute rpm (which would inherit the permissions in this case) with
a proper set of cli arguments and environment. If everything goes well, then
we don't need to worry that rpm would install smth without a plugin being run.
But what if the system gets damaged somehow (not even necessary attacked) and
plugin binary happen to disappear? In this case given that we are relying on
additional checks for the plugin, it is a very bad idea to proceed without it.
It would indeed make the whole system unsecure and in addition also unusable,
and this is all even without user understanding that system got corrupted. So,
this was the idea behind having this "plugin present" check and stop if failed
in place.  I was looking at it as some kind of analogy to sysinit that can
make checks during the boot process that needed services (example from
security: device lock daemon) are up and if they aren't up, then it can stop
the boot and actually go to some recovery mode.
Does this explanation makes a bit more sense?


So its more of a sanity check than an actual security measure. Nothing 
wrong with sanity checks, and I'm fine with having *any* configured but 
missing transaction plugin abort the transaction.


It's the case of non-configured plugin(s) somehow aborting that I find 
troublesome. The notion of mandatory plugins seems a bit alien to me, 
especially since rpm certainly does not *need* any transaction plugins 
to function as it always has. That's the reason I suggested the reverse 
setup where rpm is just t

Re: [Rpm-maint] First attempt for the patch on extending the plugin interface for rpm

2012-10-17 Thread Reshetova, Elena
>> @Tero, do you still remember the reason why the conflict hook was 
>> done in this way? Why wasn't it better to check the conflicts before 
>> the transaction and fail the whole transaction if conflicts are seen?
>
> I'm not quite sure about the context you are talking about here, but 
> I'll tell what I remember. File conflict hook is called early inside 
> rpmtsPrepare when the security plugin doesn't yet know much about the 
> package. File conflict hook just records the conflict and the decision 
> to go ahead takes place in the FSM hook. Overwriting the conflicting 
> file is allowed if package comes from a higher more trusted domain. If
it's not allowed, then FSM hook returns an error and package processing is
canceled.

>The problem is that while failure in FSM is always a possibility,
>*planning* to fail there is bad as it breaks the one promise rpm gives
about transactions: transaction will not start when there are known
problems. File conflicts need to be handled early, either by resolving them
or aborting the entire transaction before it really even starts. 
>Otherwise various calculations will be off, and by the time a package ends
ups in the FSM, some scripts have already been run causing modifications to
the system that can't be undone, plus it can cause broken dependencies to
other packages.

>Do you happen to remember what information is missing the conflict
resolution stage? I'd guess that would be something internal to the plugin
as from rpm POV, pretty much everything that is known about the packages is
available in rpmtsPrepare().

Thank you Tero for clarifying! This reminded me the actual reason why
decision can't be made in conflict hook for us. I think I just was too tired
yesterday because I miss the obvious thing. The information we are missing
is the package source (we identify it based on package signature). So,
suppose there is a new package X that is about to be installed. It brings
file A that conflicts with the previously installed file from package Y. At
this moment the verify hook for this package hasn't been called yet, so the
plugin doesn't know who signed package X and can't make a decision if it is
ok to overwrite a file or not. I wonder if we can somehow pass the package
signature to this hook then... I will look into this. 

Best Regards,
Elena.


smime.p7s
Description: S/MIME cryptographic signature
___
Rpm-maint mailing list
Rpm-maint@lists.rpm.org
http://lists.rpm.org/mailman/listinfo/rpm-maint


Re: [Rpm-maint] First attempt for the patch on extending the plugin interface for rpm

2012-10-17 Thread Elena Reshetova
>On Tue, Oct 16, 2012 at 7:51 PM, Stephen Smalley  wrote:
>>
>> @ Stephen, do you know how mandatory for SELinux is to have the whole argv
>> struct? Is it just because of rpm_execcon() API or?
>
> It is because presently rpm_execcon() performs the exec call.  If the
> exec call is handled by the caller, then we only need the executable
> path.  Likewise with envp; we do not need it if the caller performs the
> exec.  We would just move the remaining logic to set up the exec context
> from libselinux rpm_execcon() into the rpm selinux plugin code; as rpm
> is the only user of it, there is no real reason for it to live in
> libselinux vs being part of an rpm plugin.

Good, thank you for clarifying this! This is what I was hoping can be
the case. I will change the hook to have only path passed for now.

Best Regards,
Elena.
___
Rpm-maint mailing list
Rpm-maint@lists.rpm.org
http://lists.rpm.org/mailman/listinfo/rpm-maint


Re: [Rpm-maint] First attempt for the patch on extending the plugin interface for rpm

2012-10-17 Thread Panu Matilainen

On 10/17/2012 07:49 AM, Tero Aho wrote:



Ok, that'd be good. I was actually wondering why its done the way it is now -
if there is an actual reason (such insufficient information available at that
point), I'd like to understand it.


My understanding before was that in the current implementation you are able to
skip the installation of conflicting files without failing the whole package,
but now when I think of this it doesn't seem like a right thing to do.  I have
"inherited" these hooks from Tero (in CC now) and while I have done quite some
changes to them (some I actually still need to sync to open repo that you get
to see them too), I haven't touched the conflict hook at all.

@Tero, do you still remember the reason why the conflict hook was done in this
way? Why wasn't it better to check the conflicts before the transaction and
fail the whole transaction if conflicts are seen?


I'm not quite sure about the context you are talking about here, but I'll tell 
what I
remember. File conflict hook is called early inside rpmtsPrepare when the 
security
plugin doesn't yet know much about the package. File conflict hook just records 
the
conflict and the decision to go ahead takes place in the FSM hook. Overwriting 
the
conflicting file is allowed if package comes from a higher more trusted domain. 
If it's
not allowed, then FSM hook returns an error and package processing is canceled.


The problem is that while failure in FSM is always a possibility, 
*planning* to fail there is bad as it breaks the one promise rpm gives 
about transactions: transaction will not start when there are known 
problems. File conflicts need to be handled early, either by resolving 
them or aborting the entire transaction before it really even starts. 
Otherwise various calculations will be off, and by the time a package 
ends ups in the FSM, some scripts have already been run causing 
modifications to the system that can't be undone, plus it can cause 
broken dependencies to other packages.


Do you happen to remember what information is missing the conflict 
resolution stage? I'd guess that would be something internal to the 
plugin as from rpm POV, pretty much everything that is known about the 
packages is available in rpmtsPrepare().


- Panu -
___
Rpm-maint mailing list
Rpm-maint@lists.rpm.org
http://lists.rpm.org/mailman/listinfo/rpm-maint