This list is closed, nobody may subscribe to it.
| 2007 |
Jan
|
Feb
(10) |
Mar
(26) |
Apr
(8) |
May
(3) |
Jun
|
Jul
(26) |
Aug
(10) |
Sep
|
Oct
|
Nov
(2) |
Dec
(4) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2008 |
Jan
|
Feb
(13) |
Mar
(4) |
Apr
(3) |
May
(5) |
Jun
|
Jul
(7) |
Aug
(8) |
Sep
(5) |
Oct
(16) |
Nov
|
Dec
(6) |
| 2009 |
Jan
(2) |
Feb
|
Mar
(3) |
Apr
|
May
|
Jun
(19) |
Jul
(4) |
Aug
|
Sep
(13) |
Oct
(10) |
Nov
(12) |
Dec
(2) |
| 2010 |
Jan
|
Feb
(2) |
Mar
(17) |
Apr
(28) |
May
|
Jun
(17) |
Jul
(11) |
Aug
(12) |
Sep
(2) |
Oct
|
Nov
|
Dec
(1) |
| 2011 |
Jan
|
Feb
|
Mar
(20) |
Apr
(10) |
May
(1) |
Jun
|
Jul
|
Aug
(15) |
Sep
(14) |
Oct
(2) |
Nov
|
Dec
|
| 2012 |
Jan
(1) |
Feb
(53) |
Mar
(15) |
Apr
(4) |
May
(2) |
Jun
(13) |
Jul
|
Aug
|
Sep
(12) |
Oct
|
Nov
|
Dec
(6) |
| 2013 |
Jan
(7) |
Feb
(8) |
Mar
(4) |
Apr
(5) |
May
|
Jun
|
Jul
|
Aug
(5) |
Sep
(6) |
Oct
|
Nov
(5) |
Dec
(8) |
| 2014 |
Jan
(17) |
Feb
(24) |
Mar
(8) |
Apr
(7) |
May
(18) |
Jun
(15) |
Jul
(5) |
Aug
(2) |
Sep
(49) |
Oct
(28) |
Nov
(7) |
Dec
(30) |
| 2015 |
Jan
(40) |
Feb
|
Mar
(9) |
Apr
(2) |
May
(9) |
Jun
(31) |
Jul
(33) |
Aug
(5) |
Sep
(20) |
Oct
|
Nov
(3) |
Dec
(12) |
| 2016 |
Jan
(14) |
Feb
(29) |
Mar
(10) |
Apr
(4) |
May
(4) |
Jun
|
Jul
(5) |
Aug
(19) |
Sep
(21) |
Oct
(2) |
Nov
(36) |
Dec
(30) |
| 2017 |
Jan
(101) |
Feb
(12) |
Mar
(7) |
Apr
(2) |
May
(29) |
Jun
(22) |
Jul
(7) |
Aug
(93) |
Sep
(27) |
Oct
(39) |
Nov
|
Dec
|
|
From: Mimi Z. <zo...@li...> - 2014-12-03 17:41:52
|
On Wed, 2014-12-03 at 17:14 +0200, Dmitry Kasatkin wrote: > On 03/12/14 16:00, Mimi Zohar wrote: > > On Wed, 2014-12-03 at 15:08 +0200, Dmitry Kasatkin wrote: > > For "security.ima" immutable implies not only that the extended > > attribute does not change, but also that the file data can not change. > > > > For EVM, immutable would imply not only that the "security.evm" extended > > attribute, as you're suggesting, does not change, but would also prevent > > any of the other file metadata from changing either. > > This is exactly what patchset is doing. > > At that point the file data and metadata are immutable. The next step > > would be making the file immutable, preventing it from being removed > > and/or replaced. > > This is achieved by setting file immutable bit "chattr +i foo". > Immutable bit needs to be protected. > I posted patch about it > > http://sourceforge.net/p/linux-ima/mailman/message/32893464/ [CC'ing Dave Safford] Yes, using the immutable bit makes files, well, "immutable". :) Being able to piggy-back on the existing immutable bit would be nice, but requiring software updates to first remove the immutable bit, before being able to remove them, doesn't seem feasible. We want the equivalent of the immutable bit, an immutable or "locked" flag, which starts out as disabled and is enabled during boot. Once enabled, the flag cannot be disabled. This would allow software packages to be updated, prior to the "locked" flag being set. > > What are the security implications of removing the i_ino (and iversion) > > from the HMAC calculation? What are the risks associated with it? > > iversion has no any value in EVM protection as it can be arbitrary changed. > > i_no is more tricky. > It prevents pasting of inode from "other" filesystem which uses the > "same" HMAC key. > Between systems HMAC key is different... > From other hand when using signatures, public key is the same. > It looks like pasting of inodes from different filesystems are easy. Or even the same filesystem. > But we should not forget that file is immutable - data and attrs cannot > be changed. > Signer controls the key and what he signs. > Substituting file with another file from the same signer does not seem > to be a big issue... Files, signed by trusted parties, are known to have vulnerabilities. > But there may be a different solution for this. > Leave security.evm with HMAC functioning as it is and add new extended > attribute security.evmsig > which will protect attrs and xattrs additionally with signatures. Let's think about this some. Mimi |
|
From: Dmitry K. <d.k...@sa...> - 2014-12-03 15:16:50
|
On 03/12/14 16:00, Mimi Zohar wrote:
> On Wed, 2014-12-03 at 15:08 +0200, Dmitry Kasatkin wrote:
>> On 02/12/14 17:42, Mimi Zohar wrote:
>>> On Fri, 2014-11-28 at 16:07 +0200, Dmitry Kasatkin wrote:
>>>> On 27/11/14 11:15, Christophe Fillot wrote:
>>>>> On 11/26/2014 11:12 PM, Mimi Zohar wrote:
>>>>>
>>>>>> With commit "8feba3f Add support for signing a file hash", evmctl now
>>>>>> supports signing file hashes. You might want to create a manifest file
>>>>>> containing all the files and their hashes, similar to the .deb md5sums
>>>>>> file, and then sign the files hashes.
>>>>>>
>>>>>> find <dir> -type f -exec sha256sum {} \; >> ./sha256sums
>>>>>> cat ./sha256sums | evmctl sign_hash -a sha256 --key "${PRIVKEY}" > sha256sums.sig
>>>>> Thanks for the tip!
>>>>>
>>>>>>> - At boot, before reading and enabling the IMA policy, the attributes
>>>>>>> are loaded from the attribute file and applied to the TMPFS. Then,
>>>>>>> when the policy is loaded, no appraisal error occurs.
>>>>>> Interesting that the EVM signatures are valid, as the HMAC calculation
>>>>>> includes the i_ino. This means that the extracted files have the same
>>>>>> i_ino as the original version that you signed. I'm not sure that we can
>>>>>> really count on that, nor am I sure how to resolve this problem.
>>>>> In fact I create and restore the EVM signatures, but I don't enable EVM
>>>>> at the moment.
>>>>> I don't see an easy solution for that, if I understand correctly the
>>>>> tmpfs code, it
>>>>> calls get_next_ino() to generate inode numbers, and they will probably
>>>>> be random at
>>>>> each boot.
>>>>>
>>>>> Also, even if tar format (for xattr support) is used instead of cpio to
>>>>> uncompress
>>>>> initramfs into tmpfs FS, we will still have this problem for EVM signatures.
>>> Agreed, the same EVM signature problem exists for any solution. We have
>>> three options:
>>> - including a manifest file as you described
>>> - extending the CPIO format to include xattrs
>>> - adding initramfs tar support
>>>
>>> I've started looking at the 2nd option.
>>>
>>>>> Maybe a solution would be to ignore inode number for specific
>>>>> filesystems during
>>>>> EVM signature calculation (and have an option in evmctl for that too) ?
>>> This sounds like the right direction.
>>>
>>>> I have patches I am working on - Immutable EVM signatures, which will
>>>> not include i_no and iversion.
>>>> It should solve this problem.
>>> In the context of an initramfs, I'm not sure what "immutable" means.
>>> Does "immutable" imply that the file can not be removed? The memory
>>> associated with the rootfs is cleaned up before switching root. Is this
>>> a problem?
>> Immutable == Unreplaceable EVM signatures. Not converted to HMAC.
>> For permanently protecting file xattrs and attr...
>> Immutable is bad word here?
> For "security.ima" immutable implies not only that the extended
> attribute does not change, but also that the file data can not change.
>
> For EVM, immutable would imply not only that the "security.evm" extended
> attribute, as you're suggesting, does not change, but would also prevent
> any of the other file metadata from changing either.
This is exactly what patchset is doing.
> At that point the file data and metadata are immutable. The next step
> would be making the file immutable, preventing it from being removed
> and/or replaced.
This is achieved by setting file immutable bit "chattr +i foo".
Immutable bit needs to be protected.
I posted patch about it
http://sourceforge.net/p/linux-ima/mailman/message/32893464/
> What are the security implications of removing the i_ino (and iversion)
> from the HMAC calculation? What are the risks associated with it?
iversion has no any value in EVM protection as it can be arbitrary changed.
i_no is more tricky.
It prevents pasting of inode from "other" filesystem which uses the
"same" HMAC key.
Between systems HMAC key is different...
>From other hand when using signatures, public key is the same.
It looks like pasting of inodes from different filesystems are easy.
But we should not forget that file is immutable - data and attrs cannot
be changed.
Signer controls the key and what he signs.
Substituting file with another file from the same signer does not seem
to be a big issue...
But there may be a different solution for this.
Leave security.evm with HMAC functioning as it is and add new extended
attribute security.evmsig
which will protect attrs and xattrs additionally with signatures.
- Dmitry
> Mimi
>
>
|
|
From: Mimi Z. <zo...@li...> - 2014-12-03 14:01:29
|
On Wed, 2014-12-03 at 15:08 +0200, Dmitry Kasatkin wrote:
> On 02/12/14 17:42, Mimi Zohar wrote:
> > On Fri, 2014-11-28 at 16:07 +0200, Dmitry Kasatkin wrote:
> >> On 27/11/14 11:15, Christophe Fillot wrote:
> >>> On 11/26/2014 11:12 PM, Mimi Zohar wrote:
> >>>
> >>>> With commit "8feba3f Add support for signing a file hash", evmctl now
> >>>> supports signing file hashes. You might want to create a manifest file
> >>>> containing all the files and their hashes, similar to the .deb md5sums
> >>>> file, and then sign the files hashes.
> >>>>
> >>>> find <dir> -type f -exec sha256sum {} \; >> ./sha256sums
> >>>> cat ./sha256sums | evmctl sign_hash -a sha256 --key "${PRIVKEY}" > sha256sums.sig
> >>> Thanks for the tip!
> >>>
> >>>>> - At boot, before reading and enabling the IMA policy, the attributes
> >>>>> are loaded from the attribute file and applied to the TMPFS. Then,
> >>>>> when the policy is loaded, no appraisal error occurs.
> >>>> Interesting that the EVM signatures are valid, as the HMAC calculation
> >>>> includes the i_ino. This means that the extracted files have the same
> >>>> i_ino as the original version that you signed. I'm not sure that we can
> >>>> really count on that, nor am I sure how to resolve this problem.
> >>> In fact I create and restore the EVM signatures, but I don't enable EVM
> >>> at the moment.
> >>> I don't see an easy solution for that, if I understand correctly the
> >>> tmpfs code, it
> >>> calls get_next_ino() to generate inode numbers, and they will probably
> >>> be random at
> >>> each boot.
> >>>
> >>> Also, even if tar format (for xattr support) is used instead of cpio to
> >>> uncompress
> >>> initramfs into tmpfs FS, we will still have this problem for EVM signatures.
> > Agreed, the same EVM signature problem exists for any solution. We have
> > three options:
> > - including a manifest file as you described
> > - extending the CPIO format to include xattrs
> > - adding initramfs tar support
> >
> > I've started looking at the 2nd option.
> >
> >>> Maybe a solution would be to ignore inode number for specific
> >>> filesystems during
> >>> EVM signature calculation (and have an option in evmctl for that too) ?
> > This sounds like the right direction.
> >
> >> I have patches I am working on - Immutable EVM signatures, which will
> >> not include i_no and iversion.
> >> It should solve this problem.
> > In the context of an initramfs, I'm not sure what "immutable" means.
> > Does "immutable" imply that the file can not be removed? The memory
> > associated with the rootfs is cleaned up before switching root. Is this
> > a problem?
>
> Immutable == Unreplaceable EVM signatures. Not converted to HMAC.
> For permanently protecting file xattrs and attr...
> Immutable is bad word here?
For "security.ima" immutable implies not only that the extended
attribute does not change, but also that the file data can not change.
For EVM, immutable would imply not only that the "security.evm" extended
attribute, as you're suggesting, does not change, but would also prevent
any of the other file metadata from changing either.
At that point the file data and metadata are immutable. The next step
would be making the file immutable, preventing it from being removed
and/or replaced.
What are the security implications of removing the i_ino (and iversion)
from the HMAC calculation? What are the risks associated with it?
Mimi
|
|
From: Dmitry K. <d.k...@sa...> - 2014-12-03 13:09:59
|
On 02/12/14 17:42, Mimi Zohar wrote:
> On Fri, 2014-11-28 at 16:07 +0200, Dmitry Kasatkin wrote:
>> On 27/11/14 11:15, Christophe Fillot wrote:
>>> On 11/26/2014 11:12 PM, Mimi Zohar wrote:
>>>
>>>> With commit "8feba3f Add support for signing a file hash", evmctl now
>>>> supports signing file hashes. You might want to create a manifest file
>>>> containing all the files and their hashes, similar to the .deb md5sums
>>>> file, and then sign the files hashes.
>>>>
>>>> find <dir> -type f -exec sha256sum {} \; >> ./sha256sums
>>>> cat ./sha256sums | evmctl sign_hash -a sha256 --key "${PRIVKEY}" > sha256sums.sig
>>> Thanks for the tip!
>>>
>>>>> - At boot, before reading and enabling the IMA policy, the attributes
>>>>> are loaded from the attribute file and applied to the TMPFS. Then,
>>>>> when the policy is loaded, no appraisal error occurs.
>>>> Interesting that the EVM signatures are valid, as the HMAC calculation
>>>> includes the i_ino. This means that the extracted files have the same
>>>> i_ino as the original version that you signed. I'm not sure that we can
>>>> really count on that, nor am I sure how to resolve this problem.
>>> In fact I create and restore the EVM signatures, but I don't enable EVM
>>> at the moment.
>>> I don't see an easy solution for that, if I understand correctly the
>>> tmpfs code, it
>>> calls get_next_ino() to generate inode numbers, and they will probably
>>> be random at
>>> each boot.
>>>
>>> Also, even if tar format (for xattr support) is used instead of cpio to
>>> uncompress
>>> initramfs into tmpfs FS, we will still have this problem for EVM signatures.
> Agreed, the same EVM signature problem exists for any solution. We have
> three options:
> - including a manifest file as you described
> - extending the CPIO format to include xattrs
> - adding initramfs tar support
>
> I've started looking at the 2nd option.
>
>>> Maybe a solution would be to ignore inode number for specific
>>> filesystems during
>>> EVM signature calculation (and have an option in evmctl for that too) ?
> This sounds like the right direction.
>
>> I have patches I am working on - Immutable EVM signatures, which will
>> not include i_no and iversion.
>> It should solve this problem.
> In the context of an initramfs, I'm not sure what "immutable" means.
> Does "immutable" imply that the file can not be removed? The memory
> associated with the rootfs is cleaned up before switching root. Is this
> a problem?
Immutable == Unreplaceable EVM signatures. Not converted to HMAC.
For permanently protecting file xattrs and attr...
Immutable is bad word here?
- Dmitry
>>>> Are you using an initrd not an initramfs? According to
>>>> Documentation/filesystems/ramfs-rootfs-initramfs.txt, "If CONFIG_TMPFS
>>>> is enabled, rootfs will use tmpfs instead of ramfs by default".
>>>>
>>> Yes, that what I thought too, but it seems that it is not really the
>>> case because
>>> of this test:
>>>
>>> if (IS_ENABLED(CONFIG_TMPFS) && !saved_root_name[0] &&
>>> (!root_fs_names || strstr(root_fs_names, "tmpfs"))) {
>>> err = shmem_init();
>>> is_tmpfs = true;
>>> } else {
>>> err = init_ramfs_fs();
>>> }
> Is "BLK_DEV_RAM" enabled? Without it enabled, with BLK_DEV_INITRD
> enabled, I'm getting a builtin initramfs. Look at init/initramfs.c:
> populate_rootfs().
>
> Mimi
>
>
|
|
From: Mimi Z. <zo...@li...> - 2014-12-02 15:43:05
|
On Fri, 2014-11-28 at 16:07 +0200, Dmitry Kasatkin wrote:
> On 27/11/14 11:15, Christophe Fillot wrote:
> > On 11/26/2014 11:12 PM, Mimi Zohar wrote:
> >
> >> With commit "8feba3f Add support for signing a file hash", evmctl now
> >> supports signing file hashes. You might want to create a manifest file
> >> containing all the files and their hashes, similar to the .deb md5sums
> >> file, and then sign the files hashes.
> >>
> >> find <dir> -type f -exec sha256sum {} \; >> ./sha256sums
> >> cat ./sha256sums | evmctl sign_hash -a sha256 --key "${PRIVKEY}" > sha256sums.sig
> > Thanks for the tip!
> >
> >>> - At boot, before reading and enabling the IMA policy, the attributes
> >>> are loaded from the attribute file and applied to the TMPFS. Then,
> >>> when the policy is loaded, no appraisal error occurs.
> >> Interesting that the EVM signatures are valid, as the HMAC calculation
> >> includes the i_ino. This means that the extracted files have the same
> >> i_ino as the original version that you signed. I'm not sure that we can
> >> really count on that, nor am I sure how to resolve this problem.
> > In fact I create and restore the EVM signatures, but I don't enable EVM
> > at the moment.
> > I don't see an easy solution for that, if I understand correctly the
> > tmpfs code, it
> > calls get_next_ino() to generate inode numbers, and they will probably
> > be random at
> > each boot.
> >
> > Also, even if tar format (for xattr support) is used instead of cpio to
> > uncompress
> > initramfs into tmpfs FS, we will still have this problem for EVM signatures.
Agreed, the same EVM signature problem exists for any solution. We have
three options:
- including a manifest file as you described
- extending the CPIO format to include xattrs
- adding initramfs tar support
I've started looking at the 2nd option.
> > Maybe a solution would be to ignore inode number for specific
> > filesystems during
> > EVM signature calculation (and have an option in evmctl for that too) ?
This sounds like the right direction.
> I have patches I am working on - Immutable EVM signatures, which will
> not include i_no and iversion.
> It should solve this problem.
In the context of an initramfs, I'm not sure what "immutable" means.
Does "immutable" imply that the file can not be removed? The memory
associated with the rootfs is cleaned up before switching root. Is this
a problem?
>
> >> Are you using an initrd not an initramfs? According to
> >> Documentation/filesystems/ramfs-rootfs-initramfs.txt, "If CONFIG_TMPFS
> >> is enabled, rootfs will use tmpfs instead of ramfs by default".
> >>
> > Yes, that what I thought too, but it seems that it is not really the
> > case because
> > of this test:
> >
> > if (IS_ENABLED(CONFIG_TMPFS) && !saved_root_name[0] &&
> > (!root_fs_names || strstr(root_fs_names, "tmpfs"))) {
> > err = shmem_init();
> > is_tmpfs = true;
> > } else {
> > err = init_ramfs_fs();
> > }
Is "BLK_DEV_RAM" enabled? Without it enabled, with BLK_DEV_INITRD
enabled, I'm getting a builtin initramfs. Look at init/initramfs.c:
populate_rootfs().
Mimi
|
|
From: Dmitry K. <d.k...@sa...> - 2014-11-28 14:09:37
|
On 27/11/14 11:15, Christophe Fillot wrote:
> On 11/26/2014 11:12 PM, Mimi Zohar wrote:
>
>> With commit "8feba3f Add support for signing a file hash", evmctl now
>> supports signing file hashes. You might want to create a manifest file
>> containing all the files and their hashes, similar to the .deb md5sums
>> file, and then sign the files hashes.
>>
>> find <dir> -type f -exec sha256sum {} \; >> ./sha256sums
>> cat ./sha256sums | evmctl sign_hash -a sha256 --key "${PRIVKEY}" > sha256sums.sig
> Thanks for the tip!
>
>>> - At boot, before reading and enabling the IMA policy, the attributes
>>> are loaded from the attribute file and applied to the TMPFS. Then,
>>> when the policy is loaded, no appraisal error occurs.
>> Interesting that the EVM signatures are valid, as the HMAC calculation
>> includes the i_ino. This means that the extracted files have the same
>> i_ino as the original version that you signed. I'm not sure that we can
>> really count on that, nor am I sure how to resolve this problem.
> In fact I create and restore the EVM signatures, but I don't enable EVM
> at the moment.
> I don't see an easy solution for that, if I understand correctly the
> tmpfs code, it
> calls get_next_ino() to generate inode numbers, and they will probably
> be random at
> each boot.
>
> Also, even if tar format (for xattr support) is used instead of cpio to
> uncompress
> initramfs into tmpfs FS, we will still have this problem for EVM signatures.
>
> Maybe a solution would be to ignore inode number for specific
> filesystems during
> EVM signature calculation (and have an option in evmctl for that too) ?
I have patches I am working on - Immutable EVM signatures, which will
not include i_no and iversion.
It should solve this problem.
- Dmitry
>> Are you using an initrd not an initramfs? According to
>> Documentation/filesystems/ramfs-rootfs-initramfs.txt, "If CONFIG_TMPFS
>> is enabled, rootfs will use tmpfs instead of ramfs by default".
>>
> Yes, that what I thought too, but it seems that it is not really the
> case because
> of this test:
>
> if (IS_ENABLED(CONFIG_TMPFS) && !saved_root_name[0] &&
> (!root_fs_names || strstr(root_fs_names, "tmpfs"))) {
> err = shmem_init();
> is_tmpfs = true;
> } else {
> err = init_ramfs_fs();
> }
>
> Christophe
>
>
> ------------------------------------------------------------------------------
> Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
> from Actuate! Instantly Supercharge Your Business Reports and Dashboards
> with Interactivity, Sharing, Native Excel Exports, App Integration & more
> Get technology previously reserved for billion-dollar corporations, FREE
> http://pubads.g.doubleclick.net/gampad/clk?id=157005751&iu=/4140/ostg.clktrk
> _______________________________________________
> Linux-ima-user mailing list
> Lin...@li...
> https://lists.sourceforge.net/lists/listinfo/linux-ima-user
>
|
|
From: Christophe F. <cf...@ut...> - 2014-11-27 09:29:40
|
On 11/26/2014 11:12 PM, Mimi Zohar wrote:
> With commit "8feba3f Add support for signing a file hash", evmctl now
> supports signing file hashes. You might want to create a manifest file
> containing all the files and their hashes, similar to the .deb md5sums
> file, and then sign the files hashes.
>
> find <dir> -type f -exec sha256sum {} \; >> ./sha256sums
> cat ./sha256sums | evmctl sign_hash -a sha256 --key "${PRIVKEY}" > sha256sums.sig
Thanks for the tip!
>
>> - At boot, before reading and enabling the IMA policy, the attributes
>> are loaded from the attribute file and applied to the TMPFS. Then,
>> when the policy is loaded, no appraisal error occurs.
> Interesting that the EVM signatures are valid, as the HMAC calculation
> includes the i_ino. This means that the extracted files have the same
> i_ino as the original version that you signed. I'm not sure that we can
> really count on that, nor am I sure how to resolve this problem.
In fact I create and restore the EVM signatures, but I don't enable EVM
at the moment.
I don't see an easy solution for that, if I understand correctly the
tmpfs code, it
calls get_next_ino() to generate inode numbers, and they will probably
be random at
each boot.
Also, even if tar format (for xattr support) is used instead of cpio to
uncompress
initramfs into tmpfs FS, we will still have this problem for EVM signatures.
Maybe a solution would be to ignore inode number for specific
filesystems during
EVM signature calculation (and have an option in evmctl for that too) ?
>
> Are you using an initrd not an initramfs? According to
> Documentation/filesystems/ramfs-rootfs-initramfs.txt, "If CONFIG_TMPFS
> is enabled, rootfs will use tmpfs instead of ramfs by default".
>
Yes, that what I thought too, but it seems that it is not really the
case because
of this test:
if (IS_ENABLED(CONFIG_TMPFS) && !saved_root_name[0] &&
(!root_fs_names || strstr(root_fs_names, "tmpfs"))) {
err = shmem_init();
is_tmpfs = true;
} else {
err = init_ramfs_fs();
}
Christophe
|
|
From: Mimi Z. <zo...@li...> - 2014-11-26 22:12:40
|
On Wed, 2014-11-26 at 19:10 +0100, Christophe Fillot wrote:
> On 11/12/2014 10:20 PM, Mimi Zohar wrote:
>
> Hello,
>
> > Right, a general solution would be to add an initramfs archive format,
> > which supports extended attributes, to the Linux kernel and remove the
> > don't appraise ramfs rules. (The don't measure rule was already removed
> > in commit 08de59e Revert "ima: policy for RAMFS".)
> >
> >> The problem is that after boot, root is able to mount a tmpfs/ramfs FS
> >> and can run binaries from it.
> > For now, the simplest option is to replace the default policy from the
> > initramfs just before pivoting root.
> I tried the following approach that seems to work:
> - Build a classic initramfs image with Debian tool (update-initramfs)
> - Extract the initramfs image into an ext4 filesystem (or any
> filesystem
> that supports xattr).
> - Compute IMA/EVM signatures for all files with evmctl, then read
> security.ima/security.evm attributes (using getfattr) and store them
> in a text file.
With commit "8feba3f Add support for signing a file hash", evmctl now
supports signing file hashes. You might want to create a manifest file
containing all the files and their hashes, similar to the .deb md5sums
file, and then sign the files hashes.
find <dir> -type f -exec sha256sum {} \; >> ./sha256sums
cat ./sha256sums | evmctl sign_hash -a sha256 --key "${PRIVKEY}" > sha256sums.sig
> - At boot, before reading and enabling the IMA policy, the attributes
> are loaded from the attribute file and applied to the TMPFS. Then,
> when the policy is loaded, no appraisal error occurs.
Interesting that the EVM signatures are valid, as the HMAC calculation
includes the i_ino. This means that the extracted files have the same
i_ino as the original version that you signed. I'm not sure that we can
really count on that, nor am I sure how to resolve this problem.
> I had to patch the kernel to force TMPFS use (in init/do_mounts.c) instead
> of RAMFS.
Are you using an initrd not an initramfs? According to
Documentation/filesystems/ramfs-rootfs-initramfs.txt, "If CONFIG_TMPFS
is enabled, rootfs will use tmpfs instead of ramfs by default".
Mimi
> Here is what I used (this is clearly not state-of-the-art scripts...):
>
>
> Initramfs rebuild:
>
> mkdir -p signed_initramfs/extract
> cd signed_initramfs/extract
> gunzip < ~/IMA/initrd.img | cpio -i
>
> # Copy IMA policy and xattr fixup script
> mkdir -p etc/ima
> cp ~/IMA/ima_policy etc/ima/
> cp ~/IMA/apply_xattr.sh bin/
>
> evmctl sign -r -s -k ~/IMA/ima.priv --imasig -t fm
> -u"00000000-0000-0000-0000-000000000000" .
> ~/IMA/collect_xattr.sh . etc/ima/initramfs_xattr.txt
> find . | cpio --create --format='newc' | gzip -9 > ~/IMA/initrd-signed.img
>
>
> collect_xattr.sh:
>
> #!/bin/bash
>
> # Collect IMA/EVM security extended attributes and write them in
> # a text file.
>
> if [ $# -ne 2 ]; then
> echo "Usage: $(basename $0) <directory> <xattr_output_file>"
> exit 1
> fi
>
> xattr_names="security.ima security.evm"
> base_dir=$1
> output_file=$2
>
> > $2
>
> for filename in $(find $base_dir); do
> for attr in $xattr_names; do
> val=$(getfattr -n $attr -e hex -d $filename 2>/dev/null | grep
> $attr | sed -e "s/^${attr}=//")
> if [ -n "$val" ]; then
> fpath=$(echo "${filename}" | sed -e "s/^\.//")
> echo "$fpath $attr $val" >> $2
> fi
> done
> done
>
>
> apply_xattr.sh:
>
> #!/bin/sh
>
> # Apply extended attributes (xattr) to a list of files.
>
> while read filename tag value; do
> echo "XATTR: filename=${filename}, tag=${tag}, value=${value}"
> setfattr -n ${tag} -v ${value} ${filename}
> done
>
> Note: The setfattr needs to be copied by an initramfs hook script.
>
> Christophe
>
|
|
From: Christophe F. <cf...@ut...> - 2014-11-26 18:11:29
|
On 11/12/2014 10:20 PM, Mimi Zohar wrote:
Hello,
> Right, a general solution would be to add an initramfs archive format,
> which supports extended attributes, to the Linux kernel and remove the
> don't appraise ramfs rules. (The don't measure rule was already removed
> in commit 08de59e Revert "ima: policy for RAMFS".)
>
>> The problem is that after boot, root is able to mount a tmpfs/ramfs FS
>> and can run binaries from it.
> For now, the simplest option is to replace the default policy from the
> initramfs just before pivoting root.
>
I tried the following approach that seems to work:
- Build a classic initramfs image with Debian tool (update-initramfs)
- Extract the initramfs image into an ext4 filesystem (or any
filesystem
that supports xattr).
- Compute IMA/EVM signatures for all files with evmctl, then read
security.ima/security.evm attributes (using getfattr) and store them
in a text file.
- At boot, before reading and enabling the IMA policy, the attributes
are loaded from the attribute file and applied to the TMPFS. Then,
when the policy is loaded, no appraisal error occurs.
I had to patch the kernel to force TMPFS use (in init/do_mounts.c) instead
of RAMFS.
Here is what I used (this is clearly not state-of-the-art scripts...):
Initramfs rebuild:
mkdir -p signed_initramfs/extract
cd signed_initramfs/extract
gunzip < ~/IMA/initrd.img | cpio -i
# Copy IMA policy and xattr fixup script
mkdir -p etc/ima
cp ~/IMA/ima_policy etc/ima/
cp ~/IMA/apply_xattr.sh bin/
evmctl sign -r -s -k ~/IMA/ima.priv --imasig -t fm
-u"00000000-0000-0000-0000-000000000000" .
~/IMA/collect_xattr.sh . etc/ima/initramfs_xattr.txt
find . | cpio --create --format='newc' | gzip -9 > ~/IMA/initrd-signed.img
collect_xattr.sh:
#!/bin/bash
# Collect IMA/EVM security extended attributes and write them in
# a text file.
if [ $# -ne 2 ]; then
echo "Usage: $(basename $0) <directory> <xattr_output_file>"
exit 1
fi
xattr_names="security.ima security.evm"
base_dir=$1
output_file=$2
> $2
for filename in $(find $base_dir); do
for attr in $xattr_names; do
val=$(getfattr -n $attr -e hex -d $filename 2>/dev/null | grep
$attr | sed -e "s/^${attr}=//")
if [ -n "$val" ]; then
fpath=$(echo "${filename}" | sed -e "s/^\.//")
echo "$fpath $attr $val" >> $2
fi
done
done
apply_xattr.sh:
#!/bin/sh
# Apply extended attributes (xattr) to a list of files.
while read filename tag value; do
echo "XATTR: filename=${filename}, tag=${tag}, value=${value}"
setfattr -n ${tag} -v ${value} ${filename}
done
Note: The setfattr needs to be copied by an initramfs hook script.
Christophe
|
|
From: Dmitry K. <d.k...@sa...> - 2014-11-14 08:02:49
|
On 12/11/14 23:20, Mimi Zohar wrote: > On Wed, 2014-11-12 at 19:49 +0100, Christophe Fillot wrote: >> Hello all, >> >> I have built a Debian test system in a VM with IMA appraisal, my goal is >> that all binaries/libraries >> on the system must be signed. No user (even root) should be able to run >> an unsigned binary. >> >> I load the IMA policy from an initramfs script and it contains these >> lines (as the default kernel policy): >> >> [...] >> # TMPFS_MAGIC = 0x01021994 >> dont_measure fsmagic=0x01021994 >> dont_appraise fsmagic=0x01021994 >> # RAMFS_MAGIC = 0x858458f6 >> dont_measure fsmagic=0x858458f6 >> dont_appraise fsmagic=0x858458f6 >> [...] >> >> This is required because the initramfs is a cpio archive (without >> support of xattrs) loaded into a ramfs. > Right, a general solution would be to add an initramfs archive format, > which supports extended attributes, to the Linux kernel and remove the > don't appraise ramfs rules. (The don't measure rule was already removed > in commit 08de59e Revert "ima: policy for RAMFS".) > >> The problem is that after boot, root is able to mount a tmpfs/ramfs FS >> and can run binaries from it. > For now, the simplest option is to replace the default policy from the > initramfs just before pivoting root. > >> I would like to have some feedback / suggestions on how people handle >> this case ? > If you're building your own kernel, another option is Dmitry's [PATCH v4 > 0/6] ima: provide signature based 'init' appraisal patch set, which are > available from here: > https://git.kernel.org/cgit/linux/kernel/git/zohar/linux-integrity.git/log/?h=next-init-v4 > > This option requires a bit more effort, but actually works. :) > > Mimi Hi, Right, until we get xattrs support in initramfs, it is not possible to use it. We built in all necessary modules to the kernel and run from rootfs straight away. Shortly I will update IMA wiki to describe how to prepare signed user-space initialization scripts. BR, Dmitry > > ------------------------------------------------------------------------------ > Comprehensive Server Monitoring with Site24x7. > Monitor 10 servers for $9/Month. > Get alerted through email, SMS, voice calls or mobile push notifications. > Take corrective actions from your mobile device. > http://pubads.g.doubleclick.net/gampad/clk?id=154624111&iu=/4140/ostg.clktrk > _______________________________________________ > Linux-ima-user mailing list > Lin...@li... > https://lists.sourceforge.net/lists/listinfo/linux-ima-user > |
|
From: Mimi Z. <zo...@li...> - 2014-11-12 21:21:04
|
On Wed, 2014-11-12 at 19:49 +0100, Christophe Fillot wrote: > Hello all, > > I have built a Debian test system in a VM with IMA appraisal, my goal is > that all binaries/libraries > on the system must be signed. No user (even root) should be able to run > an unsigned binary. > > I load the IMA policy from an initramfs script and it contains these > lines (as the default kernel policy): > > [...] > # TMPFS_MAGIC = 0x01021994 > dont_measure fsmagic=0x01021994 > dont_appraise fsmagic=0x01021994 > # RAMFS_MAGIC = 0x858458f6 > dont_measure fsmagic=0x858458f6 > dont_appraise fsmagic=0x858458f6 > [...] > > This is required because the initramfs is a cpio archive (without > support of xattrs) loaded into a ramfs. Right, a general solution would be to add an initramfs archive format, which supports extended attributes, to the Linux kernel and remove the don't appraise ramfs rules. (The don't measure rule was already removed in commit 08de59e Revert "ima: policy for RAMFS".) > The problem is that after boot, root is able to mount a tmpfs/ramfs FS > and can run binaries from it. For now, the simplest option is to replace the default policy from the initramfs just before pivoting root. > I would like to have some feedback / suggestions on how people handle > this case ? If you're building your own kernel, another option is Dmitry's [PATCH v4 0/6] ima: provide signature based 'init' appraisal patch set, which are available from here: https://git.kernel.org/cgit/linux/kernel/git/zohar/linux-integrity.git/log/?h=next-init-v4 This option requires a bit more effort, but actually works. :) Mimi |
|
From: Christophe F. <cf...@ut...> - 2014-11-12 19:24:12
|
Hello all, I have built a Debian test system in a VM with IMA appraisal, my goal is that all binaries/libraries on the system must be signed. No user (even root) should be able to run an unsigned binary. I load the IMA policy from an initramfs script and it contains these lines (as the default kernel policy): [...] # TMPFS_MAGIC = 0x01021994 dont_measure fsmagic=0x01021994 dont_appraise fsmagic=0x01021994 # RAMFS_MAGIC = 0x858458f6 dont_measure fsmagic=0x858458f6 dont_appraise fsmagic=0x858458f6 [...] This is required because the initramfs is a cpio archive (without support of xattrs) loaded into a ramfs. The problem is that after boot, root is able to mount a tmpfs/ramfs FS and can run binaries from it. I would like to have some feedback / suggestions on how people handle this case ? Thanks in advance, Christophe |
|
From: Fionnuala G. <fi...@li...> - 2014-10-23 21:56:36
|
On 10/23/2014 12:09 PM, Dmitry Kasatkin wrote:
> On 23 October 2014 19:34, Fionnuala Gunter <fi...@li...> wrote:
>>
>>
>> On 10/23/2014 02:24 AM, Dmitry Kasatkin wrote:
>>> On 22/10/14 21:42, Fionnuala Gunter wrote:
>>>>>> @@ -964,12 +993,22 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
>>>>>> if (rc)
>>>>>> *failedFile = xstrdup(fpath);
>>>>>>
>>>>>> - /* get file signatures from header */
>>>>>> - if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) {
>>>>>> + /* sign executable files */
>>>>>> + if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH) && signFiles) {
>>>>>> + digest = rpmtdNextString(&digests);
>>>>>> + sig = signFile(algo, digest, diglen, key);
>>>>> Why do you sign only executables?
>>>>>
>>>>>> + if (!sig) {
>>>>>> + rpmlog(RPMLOG_ERR, _("signFile failed\n"));
>>>>>> + goto exit;
>>>>>> + }
>>>>>> + }
>>>>>> + /* or get file signatures from header */
>>>>>> + else if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) {
>>>>>> sig = rpmtdNextString(&sigs);
>>>>> Also here... It only sets signature for executables??
>>>> Right, I only set signatures for executables, should I set signatures
>>>> for all files?
>>>>> - Dmitry
>>>
>>> I understand that it was a safe bet that binaries can always has signature.
>>> What about libraries or may be some important configuration file which
>>> would have signature..
>>> Files which can be modified should not have a signature.
>>>
>>> Signatures should be set for all files in the package which has a signature.
>>> Package maintainer should be able to select what files to sign or not
>>> to sign...
>>>
>>> I think it has to be addressed before it can be really used.
>> This is a good point, so the files needing signatures should be
>> enumerated by the package maintainer. Perhaps this can be done in the
>> rpm spec.
>>
>> -Fin
>>>
>
> Yes, something like that..
>
> I am not an expert in package managers, but if I take a code snippet from
> ima-evm-utils.spec, then there rules to specify files to include to the package,
> like:
>
> %files
> %defattr(-,root,root,-)
> %{_bindir}/*
> %{_libdir}/libimaevm.*
> %{_includedir}/*
>
> There should be some way to specify it what should be signed, for example
>
> %sign
> %{_etcdir}/path/to/config
> %{_bindir}/*
>
Yes, this is what I had in mind.
>
> But may be RPM maintainers might comment...
>
> Thanks,
> Dmitry
>
>>> - Dmitry
>>>
>>>
>>>> Thanks,
>>>> Fin
>>>>
>>>>
>>>
>>
>> _______________________________________________
>> Rpm-maint mailing list
>> Rpm...@li...
>> http://lists.rpm.org/mailman/listinfo/rpm-maint
>
>
>
|
|
From: Dmitry K. <dmi...@gm...> - 2014-10-23 17:09:27
|
On 23 October 2014 19:34, Fionnuala Gunter <fi...@li...> wrote:
>
>
> On 10/23/2014 02:24 AM, Dmitry Kasatkin wrote:
>> On 22/10/14 21:42, Fionnuala Gunter wrote:
>>>>> @@ -964,12 +993,22 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
>>>>> if (rc)
>>>>> *failedFile = xstrdup(fpath);
>>>>>
>>>>> - /* get file signatures from header */
>>>>> - if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) {
>>>>> + /* sign executable files */
>>>>> + if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH) && signFiles) {
>>>>> + digest = rpmtdNextString(&digests);
>>>>> + sig = signFile(algo, digest, diglen, key);
>>>> Why do you sign only executables?
>>>>
>>>>> + if (!sig) {
>>>>> + rpmlog(RPMLOG_ERR, _("signFile failed\n"));
>>>>> + goto exit;
>>>>> + }
>>>>> + }
>>>>> + /* or get file signatures from header */
>>>>> + else if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) {
>>>>> sig = rpmtdNextString(&sigs);
>>>> Also here... It only sets signature for executables??
>>> Right, I only set signatures for executables, should I set signatures
>>> for all files?
>>>> - Dmitry
>>
>> I understand that it was a safe bet that binaries can always has signature.
>> What about libraries or may be some important configuration file which
>> would have signature..
>> Files which can be modified should not have a signature.
>>
>> Signatures should be set for all files in the package which has a signature.
>> Package maintainer should be able to select what files to sign or not
>> to sign...
>>
>> I think it has to be addressed before it can be really used.
> This is a good point, so the files needing signatures should be
> enumerated by the package maintainer. Perhaps this can be done in the
> rpm spec.
>
> -Fin
>>
Yes, something like that..
I am not an expert in package managers, but if I take a code snippet from
ima-evm-utils.spec, then there rules to specify files to include to the package,
like:
%files
%defattr(-,root,root,-)
%{_bindir}/*
%{_libdir}/libimaevm.*
%{_includedir}/*
There should be some way to specify it what should be signed, for example
%sign
%{_etcdir}/path/to/config
%{_bindir}/*
But may be RPM maintainers might comment...
Thanks,
Dmitry
>> - Dmitry
>>
>>
>>> Thanks,
>>> Fin
>>>
>>>
>>
>
> _______________________________________________
> Rpm-maint mailing list
> Rpm...@li...
> http://lists.rpm.org/mailman/listinfo/rpm-maint
--
Thanks,
Dmitry
|
|
From: Fionnuala G. <fi...@li...> - 2014-10-23 16:40:07
|
On 10/23/2014 02:24 AM, Dmitry Kasatkin wrote:
> On 22/10/14 21:42, Fionnuala Gunter wrote:
>>>> @@ -964,12 +993,22 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
>>>> if (rc)
>>>> *failedFile = xstrdup(fpath);
>>>>
>>>> - /* get file signatures from header */
>>>> - if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) {
>>>> + /* sign executable files */
>>>> + if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH) && signFiles) {
>>>> + digest = rpmtdNextString(&digests);
>>>> + sig = signFile(algo, digest, diglen, key);
>>> Why do you sign only executables?
>>>
>>>> + if (!sig) {
>>>> + rpmlog(RPMLOG_ERR, _("signFile failed\n"));
>>>> + goto exit;
>>>> + }
>>>> + }
>>>> + /* or get file signatures from header */
>>>> + else if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) {
>>>> sig = rpmtdNextString(&sigs);
>>> Also here... It only sets signature for executables??
>> Right, I only set signatures for executables, should I set signatures
>> for all files?
>>> - Dmitry
>
> I understand that it was a safe bet that binaries can always has signature.
> What about libraries or may be some important configuration file which
> would have signature..
> Files which can be modified should not have a signature.
>
> Signatures should be set for all files in the package which has a signature.
> Package maintainer should be able to select what files to sign or not
> to sign...
>
> I think it has to be addressed before it can be really used.
This is a good point, so the files needing signatures should be
enumerated by the package maintainer. Perhaps this can be done in the
rpm spec.
-Fin
>
> - Dmitry
>
>
>> Thanks,
>> Fin
>>
>>
>
|
|
From: Dmitry K. <d.k...@sa...> - 2014-10-23 07:30:42
|
On 22/10/14 21:48, Fionnuala Gunter wrote:
>>> @@ -953,9 +964,17 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
>>> if (rc)
>>> *failedFile = xstrdup(fpath);
>>>
>>> + /* get file signatures from header */
>>> + if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) {
>>> + sig = rpmtdNextString(&sigs);
>> What executable bit means?
> I already replied to your comments on 4/4, but maybe this filtering of
> executable files is unnecessary.
(replied to this as well because first one did not go to the list.. now
I subscribed)
I understand that it was a safe bet that binaries can always has signature.
What about libraries or may be some important configuration file which
would have signature..
Files which can be modified should not have a signature.
Signatures should be set for all files in the package which has a signature.
Package maintainer should be able to select what files to sign or not
to sign...
I think it has to be addressed before it can be really used.
- Dmitry
>>> diff --git a/plugins/ima.c b/plugins/ima.c
>>> new file mode 100644
>>> index 0000000..6b739db
>>> --- /dev/null
>>> +++ b/plugins/ima.c
>>> @@ -0,0 +1,83 @@
>>> +/**
>>> + * Copyright (C) 2014 IBM Corporation
>>> + *
>>> + * Author: Fionnuala Gunter <fi...@li...>
>>> + */
>>> +#include <syslog.h>
>>> +
>>> +#include <sys/types.h>
>>> +#include <sys/xattr.h>
>>> +#include <rpm/rpmts.h>
>>> +#include <rpm/rpmlog.h>
>>> +#include <lib/rpmplugin.h>
>>> +#include <errno.h>
>>> +#include <ctype.h>
>>> +
>>> +#include "debug.h"
>>> +
>>> +#define XATTR_NAME_IMA "security.ima"
>>> +
>>> +static int hex_to_bin(char ch)
>>> +{
>>> + if ((ch >= '0') && (ch <= '9'))
>>> + return ch - '0';
>>> + ch = tolower(ch);
>>> + if ((ch >= 'a') && (ch <= 'f'))
>>> + return ch - 'a' + 10;
>>> + return -1;
>>> +}
>>> +
>>> +static int hex2bin(char *dst, const char *src, size_t count)
>>> +{
>> Does not RPM has any hex conversion facilities yet?
>> It has digests. Does not it uses it somehow?
>>
> Good point, I will check before resubmitting.
>> - Dmitry
>>
> Thanks,
> Fin
>>> + int hi, lo;
>>> +
>>> + while (count--) {
>>> + if (*src == ' ')
>>> + src++;
>>> +
>>> + hi = hex_to_bin(*src++);
>>> + lo = hex_to_bin(*src++);
>>> +
>>> + if ((hi < 0) || (lo < 0))
>>> + return -1;
>>> +
>>> + *dst++ = (hi << 4) | lo;
>>> + }
>>> + return 0;
>>> +}
>>> +
>>> +static rpmRC ima_init(rpmPlugin plugin, rpmts ts)
>>> +{
>>> + return RPMRC_OK;
>>> +}
>>> +
>>> +static void ima_cleanup(rpmPlugin plugin)
>>> +{
>>> +}
>>> +
>>> +static rpmRC ima_fsm_file_post(rpmPlugin plugin, rpmfi fi, const char *path,
>>> + mode_t file_mode, rpmFsmOp op, const char *sig,
>>> + int res)
>>> +{
>>> + rpmRC rc = RPMRC_OK;
>>> + if (sig == NULL) {
>>> + return rc;
>>> + }
>>> +
>>> + int siglen = strlen(sig) + 1;
>>> + char bin[siglen/2];
>>> + hex2bin(bin, sig, siglen);
>>> + rc = lsetxattr(path, XATTR_NAME_IMA, bin, siglen/2, 0);
>>> +
>>> + if (rpmIsDebug())
>>> + rpmlog(RPMLOG_DEBUG, "lsetxattr: (%s) %s\n",
>>> + path, (rc < 0 ? strerror(errno) : ""));
>>> +
>>> + return rc;
>>> +}
>>> +
>>> +struct rpmPluginHooks_s ima_hooks = {
>>> + .init = ima_init,
>>> + .cleanup = ima_cleanup,
>>> + .fsm_file_post = ima_fsm_file_post,
>>> +};
>
|
|
From: Dmitry K. <d.k...@sa...> - 2014-10-23 07:24:53
|
On 22/10/14 21:42, Fionnuala Gunter wrote:
>>> @@ -964,12 +993,22 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
>>> if (rc)
>>> *failedFile = xstrdup(fpath);
>>>
>>> - /* get file signatures from header */
>>> - if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) {
>>> + /* sign executable files */
>>> + if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH) && signFiles) {
>>> + digest = rpmtdNextString(&digests);
>>> + sig = signFile(algo, digest, diglen, key);
>> Why do you sign only executables?
>>
>>> + if (!sig) {
>>> + rpmlog(RPMLOG_ERR, _("signFile failed\n"));
>>> + goto exit;
>>> + }
>>> + }
>>> + /* or get file signatures from header */
>>> + else if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) {
>>> sig = rpmtdNextString(&sigs);
>> Also here... It only sets signature for executables??
> Right, I only set signatures for executables, should I set signatures
> for all files?
>> - Dmitry
I understand that it was a safe bet that binaries can always has signature.
What about libraries or may be some important configuration file which
would have signature..
Files which can be modified should not have a signature.
Signatures should be set for all files in the package which has a signature.
Package maintainer should be able to select what files to sign or not
to sign...
I think it has to be addressed before it can be really used.
- Dmitry
> Thanks,
> Fin
>
>
|
|
From: Fionnuala G. <fi...@li...> - 2014-10-22 18:48:23
|
>> @@ -953,9 +964,17 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
>> if (rc)
>> *failedFile = xstrdup(fpath);
>>
>> + /* get file signatures from header */
>> + if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) {
>> + sig = rpmtdNextString(&sigs);
>
> What executable bit means?
I already replied to your comments on 4/4, but maybe this filtering of
executable files is unnecessary.
>> diff --git a/plugins/ima.c b/plugins/ima.c
>> new file mode 100644
>> index 0000000..6b739db
>> --- /dev/null
>> +++ b/plugins/ima.c
>> @@ -0,0 +1,83 @@
>> +/**
>> + * Copyright (C) 2014 IBM Corporation
>> + *
>> + * Author: Fionnuala Gunter <fi...@li...>
>> + */
>> +#include <syslog.h>
>> +
>> +#include <sys/types.h>
>> +#include <sys/xattr.h>
>> +#include <rpm/rpmts.h>
>> +#include <rpm/rpmlog.h>
>> +#include <lib/rpmplugin.h>
>> +#include <errno.h>
>> +#include <ctype.h>
>> +
>> +#include "debug.h"
>> +
>> +#define XATTR_NAME_IMA "security.ima"
>> +
>> +static int hex_to_bin(char ch)
>> +{
>> + if ((ch >= '0') && (ch <= '9'))
>> + return ch - '0';
>> + ch = tolower(ch);
>> + if ((ch >= 'a') && (ch <= 'f'))
>> + return ch - 'a' + 10;
>> + return -1;
>> +}
>> +
>> +static int hex2bin(char *dst, const char *src, size_t count)
>> +{
>
> Does not RPM has any hex conversion facilities yet?
> It has digests. Does not it uses it somehow?
>
Good point, I will check before resubmitting.
> - Dmitry
>
Thanks,
Fin
>> + int hi, lo;
>> +
>> + while (count--) {
>> + if (*src == ' ')
>> + src++;
>> +
>> + hi = hex_to_bin(*src++);
>> + lo = hex_to_bin(*src++);
>> +
>> + if ((hi < 0) || (lo < 0))
>> + return -1;
>> +
>> + *dst++ = (hi << 4) | lo;
>> + }
>> + return 0;
>> +}
>> +
>> +static rpmRC ima_init(rpmPlugin plugin, rpmts ts)
>> +{
>> + return RPMRC_OK;
>> +}
>> +
>> +static void ima_cleanup(rpmPlugin plugin)
>> +{
>> +}
>> +
>> +static rpmRC ima_fsm_file_post(rpmPlugin plugin, rpmfi fi, const char *path,
>> + mode_t file_mode, rpmFsmOp op, const char *sig,
>> + int res)
>> +{
>> + rpmRC rc = RPMRC_OK;
>> + if (sig == NULL) {
>> + return rc;
>> + }
>> +
>> + int siglen = strlen(sig) + 1;
>> + char bin[siglen/2];
>> + hex2bin(bin, sig, siglen);
>> + rc = lsetxattr(path, XATTR_NAME_IMA, bin, siglen/2, 0);
>> +
>> + if (rpmIsDebug())
>> + rpmlog(RPMLOG_DEBUG, "lsetxattr: (%s) %s\n",
>> + path, (rc < 0 ? strerror(errno) : ""));
>> +
>> + return rc;
>> +}
>> +
>> +struct rpmPluginHooks_s ima_hooks = {
>> + .init = ima_init,
>> + .cleanup = ima_cleanup,
>> + .fsm_file_post = ima_fsm_file_post,
>> +};
>
|
|
From: Fionnuala G. <fi...@li...> - 2014-10-22 18:42:55
|
>> @@ -964,12 +993,22 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
>> if (rc)
>> *failedFile = xstrdup(fpath);
>>
>> - /* get file signatures from header */
>> - if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) {
>> + /* sign executable files */
>> + if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH) && signFiles) {
>> + digest = rpmtdNextString(&digests);
>> + sig = signFile(algo, digest, diglen, key);
>
> Why do you sign only executables?
>
>> + if (!sig) {
>> + rpmlog(RPMLOG_ERR, _("signFile failed\n"));
>> + goto exit;
>> + }
>> + }
>> + /* or get file signatures from header */
>> + else if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) {
>> sig = rpmtdNextString(&sigs);
>
> Also here... It only sets signature for executables??
Right, I only set signatures for executables, should I set signatures
for all files?
>
> - Dmitry
Thanks,
Fin
|
|
From: Fionnuala G. <fi...@li...> - 2014-10-22 18:37:21
|
>> diff --git a/lib/rpmsignfiles.c b/lib/rpmsignfiles.c
>> new file mode 100644
>> index 0000000..9c33103
>> --- /dev/null
>> +++ b/lib/rpmsignfiles.c
>> @@ -0,0 +1,130 @@
>> +/**
>> + * Copyright (C) 2014 IBM Corporation
>> + *
>> + * Author: Fionnuala Gunter <fi...@li...>
>> + */
>> +
>> +#include "system.h"
>> +#include "imaevm.h"
>> +
>> +#include <rpm/rpmlog.h> /* rpmlog */
>> +#include <rpm/rpmstring.h> /* rnibble */
>> +#include <rpm/rpmpgp.h> /* rpmDigestLength */
>> +#include "lib/header.h" /* HEADERGET_MINMEM */
>> +#include "lib/rpmtypes.h" /* rpmRC */
>> +
>> +#include "lib/rpmsignfiles.h"
>> +
>> +static char *rpmDigestAlgo(uint32_t dalgo)
>> +{
>> + switch (dalgo) {
>> + case 0:
>> + case 1: return "md5";
>> + case 2: return "sha1";
>> + case 8: return "sha256";
>> + case 9: return "sha384";
>> + case 10: return "sha512";
>> + default: return NULL;
>> + }
>> +}
>
> This does not match kernel digest algo enumeration...
>
I found the rpm digest algo enumeration in rpmio/rpmpgp.h
typedef enum pgpHashAlgo_e {
PGPHASHALGO_MD5 = 1, /*!< MD5 */
PGPHASHALGO_SHA1 = 2, /*!< SHA1 */
PGPHASHALGO_RIPEMD160 = 3, /*!< RIPEMD160 */
PGPHASHALGO_MD2 = 5, /*!< MD2 */
PGPHASHALGO_TIGER192 = 6, /*!< TIGER192 */
PGPHASHALGO_HAVAL_5_160 = 7, /*!< HAVAL-5-160 */
PGPHASHALGO_SHA256 = 8, /*!< SHA256 */
PGPHASHALGO_SHA384 = 9, /*!< SHA384 */
PGPHASHALGO_SHA512 = 10, /*!< SHA512 */
PGPHASHALGO_SHA224 = 11, /*!< SHA224 */
} pgpHashAlgo;
> http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/hash_info.h
> http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/crypto/hash_info.c
>
> I think you could define hash_algo_name structure as well instead of
> using "switch"...
>
Yes, I will get rid of the switch.
> Actually hash_info.h is since 3.13 and Ubuntu has 3.13 now but there is
> no /usr/include/linux/hash_info.h
> Anyone has any ideas why is that?
>
> - Dmitry
Thanks,
Fin
|
|
From: Mimi Z. <zo...@li...> - 2014-10-22 12:51:33
|
On Tue, 2014-10-21 at 22:57 +0300, Dmitry Kasatkin wrote: > On October 21, 2014 5:51:23 PM EEST, Mimi Zohar <zo...@li...> wrote: > >On Tue, 2014-10-21 at 12:00 +0300, Dmitry Kasatkin wrote: > >> Hi, > >> > >> It is actually very difficult to see the "diff", because patch > >removes > >> file and add new file.. > >> > >> You better do it in 2 steps... > >> > >> 1) rename dh_md5sums to dh_checksums > >> 2) do changes. > >> > >> Then it will be very clear what are your changes.. > > > >As the dh_md5sums is being called manually from numerous packages, the > >next posting will define dh_checksums, but will not remove dh_md5sums. > > > >Mimi > > May be for compatibility you still need to keep it and not rename at all. > Otherwise it will break hundreds of packages. Right, for now at least, we need to leave dh_md5sums alone. As Joey requested, I've opened a bug report. As seems to be the norm for the debhelper mailing list, the patches are attached to the bug report. Bug#766267: debhelper: add file signature support in .deb packages, http://lists.alioth.debian.org/pipermail/debhelper-devel/Week-of-Mon-20141020/000882.html Mimi |
|
From: Dmitry K. <d.k...@sa...> - 2014-10-22 09:16:10
|
On 07/10/14 23:19, fi...@li... wrote:
> From: Fionnuala Gunter <fi...@li...>
>
> It will take some time for distros to adopt the file signing process and
> distribute packages with file signatures, so this patch extends the rpm
> installer to support inline file signing. This patch adds a new option,
> signfiles, to the rpm installer.
>
> rpm -ivh [--signfiles [--fskpath <file signing key>]] PACKAGE_FILE ...
>
> Signed-off-by: Fionnuala Gunter <fi...@li...>
> ---
> doc/rpm.8 | 28 +++++++++++++++++++---------
> lib/fsm.c | 50 +++++++++++++++++++++++++++++++++++++++++++++-----
> lib/poptI.c | 7 +++++++
> lib/rpmcli.h | 2 ++
> lib/rpminstall.c | 10 +++++++++-
> lib/rpmts.c | 15 +++++++++++++++
> lib/rpmts.h | 15 +++++++++++++++
> lib/rpmts_internal.h | 2 ++
> 8 files changed, 114 insertions(+), 15 deletions(-)
>
> diff --git a/doc/rpm.8 b/doc/rpm.8
> index e583009..4079f71 100644
> --- a/doc/rpm.8
> +++ b/doc/rpm.8
> @@ -84,15 +84,14 @@ rpm \- RPM Package Manager
>
>
> [\fB--allfiles\fR] [\fB--badreloc\fR] [\fB--excludepath \fIOLDPATH\fB\fR]
> - [\fB--excludedocs\fR] [\fB--force\fR] [\fB-h,--hash\fR]
> - [\fB--ignoresize\fR] [\fB--ignorearch\fR] [\fB--ignoreos\fR]
> - [\fB--includedocs\fR] [\fB--justdb\fR] [\fB--nocollections\fR]
> - [\fB--nodeps\fR] [\fB--nodigest\fR] [\fB--nosignature\fR]
> - [\fB--noorder\fR] [\fB--noscripts\fR] [\fB--notriggers\fR]
> - [\fB--oldpackage\fR] [\fB--percent\fR] [\fB--prefix \fINEWPATH\fB\fR]
> - [\fB--relocate \fIOLDPATH\fB=\fINEWPATH\fB\fR]
> - [\fB--replacefiles\fR] [\fB--replacepkgs\fR]
> - [\fB--test\fR]
> + [\fB--excludedocs\fR] [\fB--force\fR] [\fB--fskpath \fIKEY\fB\fR]
> + [\fB-h,--hash\fR] [\fB--ignoresize\fR] [\fB--ignorearch\fR]
> + [\fB--ignoreos\fR] [\fB--includedocs\fR] [\fB--justdb\fR]
> + [\fB--nocollections\fR] [\fB--nodeps\fR] [\fB--nodigest\fR]
> + [\fB--nosignature\fR] [\fB--noorder\fR] [\fB--noscripts\fR]
> + [\fB--notriggers\fR] [\fB--oldpackage\fR] [\fB--percent\fR]
> + [\fB--prefix \fINEWPATH\fB\fR] [\fB--relocate \fIOLDPATH\fB=\fINEWPATH\fB\fR]
> + [\fB--replacefiles\fR] [\fB--replacepkgs\fR] [\fB--signfiles] [\fB--test\fR]
>
> .SH "DESCRIPTION"
> .PP
> @@ -232,6 +231,9 @@ Don't install files whose name begins with
> Don't install any files which are marked as documentation
> (which includes man pages and texinfo documents).
> .TP
> +\fB--fskpath \fIKEY\fB\fR
> +Used with \fB--signfiles\fR, use file signing key \fIKEY\fR.
> +.TP
> \fB--force\fR
> Same as using
> \fB--replacepkgs\fR,
> @@ -362,6 +364,13 @@ already installed, packages.
> Install the packages even if some of them are already installed
> on this system.
> .TP
> +\fB--signfiles\fR
> +Sign package files. The macro \fB%_binary_filedigest_algorithm\fR must be set
> +before building the package, and the macro must be set to a supported algorithm:
> +2, 8, 9, or 10, which represent SHA1, SHA256, SHA384, and SHA512, respectively.
> +The file signing key (RSA private key) can be configured on the command line
> +with \fB--fskpath\fR or the macro \fB%_file_signing_key\fR.
> +.TP
> \fB--test\fR
> Do not install the package, simply check for and report
> potential conflicts.
> @@ -875,4 +884,5 @@ what's available.
> Marc Ewing <ma...@re...>
> Jeff Johnson <jb...@re...>
> Erik Troan <ew...@re...>
> +Fionnuala Gunter <fi...@li...>
> .fi
> diff --git a/lib/fsm.c b/lib/fsm.c
> index dbeeaab..05ea230 100644
> --- a/lib/fsm.c
> +++ b/lib/fsm.c
> @@ -21,6 +21,7 @@
> #include "lib/rpmplugins.h" /* rpm plugins hooks */
> #include "lib/rpmug.h"
> #include "lib/rpmlib.h"
> +#include "lib/rpmsignfiles.h" /* getDigestAlgo, getDigestLength, signFile */
>
> #include "debug.h"
>
> @@ -825,8 +826,13 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
> const char *suffix;
> char *fpath = NULL;
> Header h = rpmteHeader(te);
> - struct rpmtd_s sigs;
> - char *sig = NULL;
> + struct rpmtd_s digests, sigs;
> + int signFiles = rpmtsSignFiles(ts);
> + const char *key;
> + const char *algo;
> + const char *digest;
> + const char *sig;
> + int diglen = 0;
>
> if (fi == NULL) {
> rc = RPMERR_BAD_MAGIC;
> @@ -838,7 +844,30 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
> goto exit;
> }
>
> - headerGet(h, RPMTAG_FILESIGNATURES, &sigs, HEADERGET_MINMEM);
> + if (signFiles) {
> + algo = getDigestAlgo(h);
> + if (!algo) {
> + rc = RPMRC_FAIL;
> + goto exit;
> + }
> +
> + diglen = getDigestLength(h);
> + if (diglen < 0) {
> + rc = RPMRC_FAIL;
> + goto exit;
> + }
> +
> + key = rpmExpand("%{_file_signing_key}", NULL);
> + if (rstreq(key, "")) {
> + rc = RPMRC_FAIL;
> + fprintf(stderr, _("You must set \"$$_file_signing_key\" in your macro file or on the command line with --fskpath\n"));
> + rpmlog(RPMLOG_ERR, _("no file signing key provided\n"));
> + }
> +
> + headerGet(h, RPMTAG_FILEDIGESTS, &digests, HEADERGET_MINMEM);
> + } else {
> + headerGet(h, RPMTAG_FILESIGNATURES, &sigs, HEADERGET_MINMEM);
> + }
>
> /* transaction id used for temporary path suffix while installing */
> rasprintf(&tid, ";%08x", (unsigned)rpmtsGetTid(ts));
> @@ -964,12 +993,22 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
> if (rc)
> *failedFile = xstrdup(fpath);
>
> - /* get file signatures from header */
> - if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) {
> + /* sign executable files */
> + if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH) && signFiles) {
> + digest = rpmtdNextString(&digests);
> + sig = signFile(algo, digest, diglen, key);
Why do you sign only executables?
> + if (!sig) {
> + rpmlog(RPMLOG_ERR, _("signFile failed\n"));
> + goto exit;
> + }
> + }
> + /* or get file signatures from header */
> + else if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) {
> sig = rpmtdNextString(&sigs);
Also here... It only sets signature for executables??
- Dmitry
> } else {
> sig = NULL;
> rpmtdNextString(&sigs);
> + rpmtdNextString(&digests);
> }
>
> /* Run fsm file post hook for all plugins */
> @@ -984,6 +1023,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
> exit:
>
> /* No need to bother with close errors on read */
> + rpmtdFreeData(&digests);
> rpmtdFreeData(&sigs);
> headerFree(h);
> rpmfiArchiveClose(fi);
> diff --git a/lib/poptI.c b/lib/poptI.c
> index e21cde1..699c8cd 100644
> --- a/lib/poptI.c
> +++ b/lib/poptI.c
> @@ -16,8 +16,10 @@ struct rpmInstallArguments_s rpmIArgs = {
> 0, /* numRelocations */
> 0, /* noDeps */
> 0, /* incldocs */
> + 0, /* signFiles */
> NULL, /* relocations */
> NULL, /* prefix */
> + NULL, /* fileSigningKey */
> };
>
> #define POPT_RELOCATE -1021
> @@ -146,6 +148,9 @@ struct poptOption rpmInstallPoptTable[] = {
> (INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL),
> N_("upgrade package(s) if already installed"),
> N_("<packagefile>+") },
> + { "fskpath", '\0', POPT_ARG_STRING, &rpmIArgs.fileSigningKey, 0,
> + N_("use file signing key <key>"),
> + N_("<key>") },
> { "hash", 'h', POPT_BIT_SET, &rpmIArgs.installInterfaceFlags, INSTALL_HASH,
> N_("print hash marks as package installs (good with -v)"), NULL},
> { "ignorearch", '\0', POPT_BIT_SET,
> @@ -243,6 +248,8 @@ struct poptOption rpmInstallPoptTable[] = {
> { "replacepkgs", '\0', POPT_BIT_SET,
> &rpmIArgs.probFilter, RPMPROB_FILTER_REPLACEPKG,
> N_("reinstall if the package is already present"), NULL},
> + { "signfiles", '\0', POPT_ARG_NONE, &rpmIArgs.signFiles, 0,
> + N_("sign package files"), NULL},
> { "test", '\0', POPT_BIT_SET, &rpmIArgs.transFlags, RPMTRANS_FLAG_TEST,
> N_("don't install, but tell if it would work or not"), NULL},
> { "upgrade", 'U', POPT_BIT_SET,
> diff --git a/lib/rpmcli.h b/lib/rpmcli.h
> index 48e8250..ff89171 100644
> --- a/lib/rpmcli.h
> +++ b/lib/rpmcli.h
> @@ -339,8 +339,10 @@ struct rpmInstallArguments_s {
> int numRelocations;
> int noDeps;
> int incldocs;
> + int signFiles;
> rpmRelocation * relocations;
> char * prefix;
> + char * fileSigningKey;
> };
>
> /** \ingroup rpmcli
> diff --git a/lib/rpminstall.c b/lib/rpminstall.c
> index 2e7da7d..d98d506 100644
> --- a/lib/rpminstall.c
> +++ b/lib/rpminstall.c
> @@ -11,6 +11,7 @@
> #include <rpm/rpmds.h>
> #include <rpm/rpmts.h>
> #include <rpm/rpmlog.h>
> +#include <rpm/rpmmacro.h>
> #include <rpm/rpmfileutil.h>
>
> #include "lib/rpmgi.h"
> @@ -417,7 +418,14 @@ int rpmInstall(rpmts ts, struct rpmInstallArguments_s * ia, ARGV_t fileArgv)
>
> relocations = ia->relocations;
>
> - setNotifyFlag(ia, ts);
> + setNotifyFlag(ia, ts);
> +
> + rpmtsSetSignFiles(ts, ia->signFiles);
> +
> + if (ia->fileSigningKey) {
> + addMacro(NULL, "_file_signing_key", NULL, ia->fileSigningKey,
> + RMIL_GLOBAL);
> + }
>
> if ((eiu->relocations = relocations) != NULL) {
> while (eiu->relocations->oldPath)
> diff --git a/lib/rpmts.c b/lib/rpmts.c
> index a3b4ed2..6d9eb30 100644
> --- a/lib/rpmts.c
> +++ b/lib/rpmts.c
> @@ -897,6 +897,21 @@ int rpmtsSetNotifyCallback(rpmts ts,
> return 0;
> }
>
> +int rpmtsSignFiles(rpmts ts)
> +{
> + return ts ? ts->signFiles : NULL;
> +}
> +
> +int rpmtsSetSignFiles(rpmts ts, int signFiles)
> +{
> + if (ts == NULL) {
> + return -1;
> + }
> +
> + ts->signFiles = signFiles;
> + return 0;
> +}
> +
> tsMembers rpmtsMembers(rpmts ts)
> {
> return (ts != NULL) ? ts->members : NULL;
> diff --git a/lib/rpmts.h b/lib/rpmts.h
> index 5231c80..5f45972 100644
> --- a/lib/rpmts.h
> +++ b/lib/rpmts.h
> @@ -393,6 +393,21 @@ const char * rpmtsRootDir(rpmts ts);
> */
> int rpmtsSetRootDir(rpmts ts, const char * rootDir);
>
> +/**
> + * Get transaction sign files flag
> + * @param ts transaction set
> + * @return non-zero if package files need to be signed
> + */
> +int rpmtsSignFiles(rpmts ts);
> +
> +/**
> + * Set transaction sign files flag
> + * @param ts transaction set
> + * @param signFiles new sign files flag
> + * @return 0 on success, -1 on error
> + */
> +int rpmtsSetSignFiles(rpmts ts, int signFiles);
> +
> /** \ingroup rpmts
> * Get transaction script file handle, i.e. stdout/stderr on scriptlet execution
> * @param ts transaction set
> diff --git a/lib/rpmts_internal.h b/lib/rpmts_internal.h
> index 0caa7cb..a196932 100644
> --- a/lib/rpmts_internal.h
> +++ b/lib/rpmts_internal.h
> @@ -68,6 +68,8 @@ struct rpmts_s {
> rpmPlugins plugins; /*!< Transaction plugins */
>
> int nrefs; /*!< Reference count. */
> +
> + int signFiles; /*!< Sign package files. */
> };
>
> #ifdef __cplusplus
|
|
From: Dmitry K. <d.k...@sa...> - 2014-10-22 09:13:37
|
On 07/10/14 23:19, fi...@li... wrote:
> From: Fionnuala Gunter <fi...@li...>
>
> This patch creates a new rpm-plugin for IMA and extends the rpm installer.
> When a package with signed files is installed, the file signatures are
> extracted from the package header, and passed to the IMA plugin. The IMA
> plugin labels the security.ima xattr with the file signature.
>
> Signed-off-by: Fionnuala Gunter <fi...@li...>
> ---
> lib/fsm.c | 23 ++++++++++++++-
> macros.in | 1 +
> plugins/Makefile.am | 4 +++
> plugins/ima.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 110 insertions(+), 1 deletion(-)
> create mode 100644 plugins/ima.c
>
> diff --git a/lib/fsm.c b/lib/fsm.c
> index e7c2a3b..dbeeaab 100644
> --- a/lib/fsm.c
> +++ b/lib/fsm.c
> @@ -20,6 +20,7 @@
> #include "lib/rpmte_internal.h" /* XXX rpmfs */
> #include "lib/rpmplugins.h" /* rpm plugins hooks */
> #include "lib/rpmug.h"
> +#include "lib/rpmlib.h"
>
> #include "debug.h"
>
> @@ -823,12 +824,22 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
> char *tid = NULL;
> const char *suffix;
> char *fpath = NULL;
> + Header h = rpmteHeader(te);
> + struct rpmtd_s sigs;
> + char *sig = NULL;
>
> if (fi == NULL) {
> rc = RPMERR_BAD_MAGIC;
> goto exit;
> }
>
> + if (h == NULL) {
> + rc = RPMRC_FAIL;
> + goto exit;
> + }
> +
> + headerGet(h, RPMTAG_FILESIGNATURES, &sigs, HEADERGET_MINMEM);
> +
> /* transaction id used for temporary path suffix while installing */
> rasprintf(&tid, ";%08x", (unsigned)rpmtsGetTid(ts));
>
> @@ -953,9 +964,17 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
> if (rc)
> *failedFile = xstrdup(fpath);
>
> + /* get file signatures from header */
> + if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) {
> + sig = rpmtdNextString(&sigs);
What executable bit means?
> + } else {
> + sig = NULL;
> + rpmtdNextString(&sigs);
> + }
> +
> /* Run fsm file post hook for all plugins */
> rpmpluginsCallFsmFilePost(plugins, fi, fpath,
> - sb.st_mode, action, NULL, rc);
> + sb.st_mode, action, sig, rc);
> fpath = _free(fpath);
> }
>
> @@ -965,6 +984,8 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
> exit:
>
> /* No need to bother with close errors on read */
> + rpmtdFreeData(&sigs);
> + headerFree(h);
> rpmfiArchiveClose(fi);
> rpmfiFree(fi);
> Fclose(payload);
> diff --git a/macros.in b/macros.in
> index 1647104..0b62991 100644
> --- a/macros.in
> +++ b/macros.in
> @@ -1043,6 +1043,7 @@ done \
> %__transaction_systemd_inhibit %{__plugindir}/systemd_inhibit.so
> %__transaction_selinux %{__plugindir}/selinux.so
> %__transaction_syslog %{__plugindir}/syslog.so
> +%__transaction_ima %{__plugindir}/ima.so
>
> #------------------------------------------------------------------------------
> # Macros for further automated spec %setup and patch application
> diff --git a/plugins/Makefile.am b/plugins/Makefile.am
> index 53b2450..18f6170 100644
> --- a/plugins/Makefile.am
> +++ b/plugins/Makefile.am
> @@ -31,3 +31,7 @@ endif
> syslog_la_SOURCES = syslog.c
> syslog_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la
> plugins_LTLIBRARIES += syslog.la
> +
> +ima_la_sources = ima.c
> +ima_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la
> +plugins_LTLIBRARIES += ima.la
> diff --git a/plugins/ima.c b/plugins/ima.c
> new file mode 100644
> index 0000000..6b739db
> --- /dev/null
> +++ b/plugins/ima.c
> @@ -0,0 +1,83 @@
> +/**
> + * Copyright (C) 2014 IBM Corporation
> + *
> + * Author: Fionnuala Gunter <fi...@li...>
> + */
> +#include <syslog.h>
> +
> +#include <sys/types.h>
> +#include <sys/xattr.h>
> +#include <rpm/rpmts.h>
> +#include <rpm/rpmlog.h>
> +#include <lib/rpmplugin.h>
> +#include <errno.h>
> +#include <ctype.h>
> +
> +#include "debug.h"
> +
> +#define XATTR_NAME_IMA "security.ima"
> +
> +static int hex_to_bin(char ch)
> +{
> + if ((ch >= '0') && (ch <= '9'))
> + return ch - '0';
> + ch = tolower(ch);
> + if ((ch >= 'a') && (ch <= 'f'))
> + return ch - 'a' + 10;
> + return -1;
> +}
> +
> +static int hex2bin(char *dst, const char *src, size_t count)
> +{
Does not RPM has any hex conversion facilities yet?
It has digests. Does not it uses it somehow?
- Dmitry
> + int hi, lo;
> +
> + while (count--) {
> + if (*src == ' ')
> + src++;
> +
> + hi = hex_to_bin(*src++);
> + lo = hex_to_bin(*src++);
> +
> + if ((hi < 0) || (lo < 0))
> + return -1;
> +
> + *dst++ = (hi << 4) | lo;
> + }
> + return 0;
> +}
> +
> +static rpmRC ima_init(rpmPlugin plugin, rpmts ts)
> +{
> + return RPMRC_OK;
> +}
> +
> +static void ima_cleanup(rpmPlugin plugin)
> +{
> +}
> +
> +static rpmRC ima_fsm_file_post(rpmPlugin plugin, rpmfi fi, const char *path,
> + mode_t file_mode, rpmFsmOp op, const char *sig,
> + int res)
> +{
> + rpmRC rc = RPMRC_OK;
> + if (sig == NULL) {
> + return rc;
> + }
> +
> + int siglen = strlen(sig) + 1;
> + char bin[siglen/2];
> + hex2bin(bin, sig, siglen);
> + rc = lsetxattr(path, XATTR_NAME_IMA, bin, siglen/2, 0);
> +
> + if (rpmIsDebug())
> + rpmlog(RPMLOG_DEBUG, "lsetxattr: (%s) %s\n",
> + path, (rc < 0 ? strerror(errno) : ""));
> +
> + return rc;
> +}
> +
> +struct rpmPluginHooks_s ima_hooks = {
> + .init = ima_init,
> + .cleanup = ima_cleanup,
> + .fsm_file_post = ima_fsm_file_post,
> +};
|
|
From: Dmitry K. <d.k...@sa...> - 2014-10-22 09:05:30
|
On 07/10/14 23:19, fi...@li... wrote:
> From: Fionnuala Gunter <fi...@li...>
>
> This patch extends the existing rpm signing tool to also sign package files
> and include them in the package header. It defines a tag,
> RPMTAG_FILESIGNATURES, an RPM macro %_file_signing_key, and new options
> fskpath, and signfiles.
>
> rpm --addsign [--signfiles [--fskpath <file signing key>]] PACKAGE_FILE ...
>
> The new option to rpmsign signs all the file digests included in the
> package. When a package is signed with the new option, the file digests are
> signed with libimaevm and the key %file_signing_key. The resulting
> signatures are included in the package header as an RPMTAG_FILESIGNATURES
> tag. Since the header is modified, the SHA1 and MD5 header digests are
> recalculated and inserted in the signature header.
>
> After including file signatures, the package is signed normally.
>
> Signed-off-by: Fionnuala Gunter <fi...@li...>
> ---
> configure.ac | 8 ++
> doc/rpmsign.8 | 22 +++-
> lib/Makefile.am | 3 +-
> lib/rpmsignfiles.c | 130 ++++++++++++++++++++++
> lib/rpmsignfiles.h | 45 ++++++++
> lib/rpmtag.h | 1 +
> rpmpopt.in | 1 +
> rpmsign.c | 14 ++-
> sign/rpmgensig.c | 319 ++++++++++++++++++++++++++++++++++++++++++++++++-----
> sign/rpmsign.h | 7 +-
> 10 files changed, 520 insertions(+), 30 deletions(-)
> create mode 100644 lib/rpmsignfiles.c
> create mode 100644 lib/rpmsignfiles.h
>
> diff --git a/configure.ac b/configure.ac
> index cbb869f..21a6a95 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -658,6 +658,14 @@ AC_SUBST(WITH_SELINUX_LIB)
> AC_SUBST(WITH_SEMANAGE_LIB)
> AM_CONDITIONAL(SELINUX,[test "$with_selinux" = yes])
>
> +# libimaevm
> +with_iamevm=no
> +AC_ARG_WITH(imaevm, [AS_HELP_STRING([--with-imaevm],[build with imaevm support])])
> +if test "$with_imaevm" = yes ; then
> + AC_DEFINE(IMAEVM, 1, [Build with imaevm support?])
> + LIBS="$LIBS -limaevm"
> +fi
> +
> # libcap
> WITH_CAP_LIB=
> AC_ARG_WITH(cap, [AS_HELP_STRING([--with-cap],[build with capability support])],
> diff --git a/doc/rpmsign.8 b/doc/rpmsign.8
> index 53f2d70..b19f172 100644
> --- a/doc/rpmsign.8
> +++ b/doc/rpmsign.8
> @@ -2,11 +2,17 @@
> .SH NAME
> rpmsign \- RPM Package Signing
> .SH SYNOPSIS
> +.SS "SIGNING PACKAGES:"
> +.PP
>
> -\fBrpm\fR \fB--addsign|--resign\fR \fB\fIPACKAGE_FILE\fB\fR\fI ...\fR
> +\fBrpm\fR \fB--addsign|--resign\fR [\fBrpmsign-options\fR] \fB\fIPACKAGE_FILE\fB\fR\fI ...\fR
>
> \fBrpm\fR \fB--delsign\fR \fB\fIPACKAGE_FILE\fB\fR\fI ...\fR
>
> +.SS "rpmsign-options"
> +.PP
> + \fB--fskpath \fIKEY\fB\fR] [\fB--signfiles\fR]
> +
> .SH DESCRIPTION
> .PP
> Both of the \fB--addsign\fR and \fB--resign\fR
> @@ -20,6 +26,19 @@ there is no difference in behavior currently.
> .PP
> Delete all signatures from each package \fIPACKAGE_FILE\fR given.
>
> +.SS "SIGN OPTIONS"
> +.PP
> +.TP
> +\fB--fskpath \fIKEY\fB\fR
> +Used with \fB--signfiles\fR, use file signing key \fIKEY\fR.
> +.TP
> +\fB--signfiles\fR
> +Sign package files. The macro \fB%_binary_filedigest_algorithm\fR must be set
> +before building the package, and the macro must be set to a supported algorithm:
> +2, 8, 9, or 10, which represent SHA1, SHA256, SHA384, and SHA512, respectively.
> +The file signing key (RSA private key) can be configured on the command line
> +with \fB--fskpath\fR or the macro \fB%_file_signing_key\fR.
> +
> .SS "USING GPG TO SIGN PACKAGES"
> .PP
> In order to sign packages using GPG, \fBrpm\fR
> @@ -78,4 +97,5 @@ Marc Ewing <ma...@re...>
> Jeff Johnson <jb...@re...>
> Erik Troan <ew...@re...>
> Panu Matilainen <pma...@re...>
> +Fionnuala Gunter <fi...@li...>
> .fi
> diff --git a/lib/Makefile.am b/lib/Makefile.am
> index a65eb80..f80a47a 100644
> --- a/lib/Makefile.am
> +++ b/lib/Makefile.am
> @@ -38,7 +38,8 @@ librpm_la_SOURCES = \
> verify.c rpmlock.c rpmlock.h misc.h relocation.c \
> rpmscript.h rpmscript.c legacy.c \
> rpmchroot.c rpmchroot.h \
> - rpmplugins.c rpmplugins.h rpmplugin.h rpmug.c rpmug.h
> + rpmplugins.c rpmplugins.h rpmplugin.h rpmug.c rpmug.h \
> + rpmsignfiles.c rpmsignfiles.h
>
> librpm_la_LDFLAGS = -version-info $(rpm_version_info)
>
> diff --git a/lib/rpmsignfiles.c b/lib/rpmsignfiles.c
> new file mode 100644
> index 0000000..9c33103
> --- /dev/null
> +++ b/lib/rpmsignfiles.c
> @@ -0,0 +1,130 @@
> +/**
> + * Copyright (C) 2014 IBM Corporation
> + *
> + * Author: Fionnuala Gunter <fi...@li...>
> + */
> +
> +#include "system.h"
> +#include "imaevm.h"
> +
> +#include <rpm/rpmlog.h> /* rpmlog */
> +#include <rpm/rpmstring.h> /* rnibble */
> +#include <rpm/rpmpgp.h> /* rpmDigestLength */
> +#include "lib/header.h" /* HEADERGET_MINMEM */
> +#include "lib/rpmtypes.h" /* rpmRC */
> +
> +#include "lib/rpmsignfiles.h"
> +
> +static char *rpmDigestAlgo(uint32_t dalgo)
> +{
> + switch (dalgo) {
> + case 0:
> + case 1: return "md5";
> + case 2: return "sha1";
> + case 8: return "sha256";
> + case 9: return "sha384";
> + case 10: return "sha512";
> + default: return NULL;
> + }
> +}
This does not match kernel digest algo enumeration...
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/hash_info.h
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/crypto/hash_info.c
I think you could define hash_algo_name structure as well instead of
using "switch"...
Actually hash_info.h is since 3.13 and Ubuntu has 3.13 now but there is
no /usr/include/linux/hash_info.h
Anyone has any ideas why is that?
- Dmitry
> +
> +char *getDigestAlgo(Header h)
> +{
> + struct rpmtd_s digalgo;
> + uint32_t *dalgo;
> + char *algo;
> +
> + headerGet(h, RPMTAG_FILEDIGESTALGO, &digalgo, HEADERGET_MINMEM);
> + dalgo = rpmtdGetUint32(&digalgo);
> + if (!dalgo) {
> + rpmlog(RPMLOG_ERR, _("rpmtdGetUint32 failed\n"));
> + return NULL;
> + }
> + algo = rpmDigestAlgo(*dalgo);
> + return algo;
> +}
> +
> +int getDigestLength(Header h)
> +{
> + struct rpmtd_s digalgo;
> + uint32_t *dalgo;
> + int diglen;
> +
> + headerGet(h, RPMTAG_FILEDIGESTALGO, &digalgo, HEADERGET_MINMEM);
> + dalgo = rpmtdGetUint32(&digalgo);
> + if (!dalgo) {
> + rpmlog(RPMLOG_ERR, _("rpmtdGetUint32 failed\n"));
> + return -1;
> + }
> +
> + diglen = rpmDigestLength(*dalgo);
> + return diglen;
> +}
> +
> +char *signFile(const char *algo, const char *fdigest, int diglen, const char *key)
> +{
> + char *fsignature;
> + unsigned char digest[BUFSIZ];
> + unsigned char signature[BUFSIZ];
> + int siglen;
> +
> +#ifndef IMAEVM
> + rpmlog(RPMLOG_ERR, _("missing libimaevm\n"));
> + return NULL;
> +#endif
> +
> + /* convert file digest hex to binary */
> + memset(digest, 0, BUFSIZ);
> + for (int i = 0; i < diglen; ++i, fdigest += 2)
> + digest[i] = (rnibble(fdigest[0]) << 4) | rnibble(fdigest[1]);
> +
> + /* prepare file signature */
> + memset(signature, 0, BUFSIZ);
> + signature[0] = '\x03';
> +
> + /* calculate file signature */
> + siglen = sign_hash(algo, digest, diglen, key, signature+1);
> + if (siglen < 0) {
> + rpmlog(RPMLOG_ERR, _("sign_hash failed\n"));
> + return NULL;
> + }
> +
> + /* convert file signature binary to hex */
> + fsignature = pgpHexStr(signature, siglen+1);
> + return fsignature;
> +}
> +
> +rpmRC signFiles(Header h, const char *key)
> +{
> + struct rpmtd_s digests;
> + const char *algo;
> + const char *digest;
> + char *signature;
> + int diglen;
> +
> + algo = getDigestAlgo(h);
> + if (!algo) {
> + rpmlog(RPMLOG_ERR, _("getDigestAlgo failed\n"));
> + return RPMRC_FAIL;
> + }
> +
> + diglen = getDigestLength(h);
> + if (diglen < 0) {
> + rpmlog(RPMLOG_ERR, _("getDigestLength failed\n"));
> + return RPMRC_FAIL;
> + }
> +
> + headerGet(h, RPMTAG_FILEDIGESTS, &digests, HEADERGET_MINMEM);
> + while ((digest = rpmtdNextString(&digests))) {
> + signature = signFile(algo, digest, diglen, key);
> + if (!signature) {
> + rpmlog(RPMLOG_ERR, _("signFile failed\n"));
> + return RPMRC_FAIL;
> + }
> + if (!headerPutString(h, RPMTAG_FILESIGNATURES, signature)) {
> + rpmlog(RPMLOG_ERR, _("headerPutString failed\n"));
> + return RPMRC_FAIL;
> + }
> + }
> + return RPMRC_OK;
> +}
> diff --git a/lib/rpmsignfiles.h b/lib/rpmsignfiles.h
> new file mode 100644
> index 0000000..05459f0
> --- /dev/null
> +++ b/lib/rpmsignfiles.h
> @@ -0,0 +1,45 @@
> +#ifndef H_RPMSIGNFILES
> +#define H_RPMSIGNFILES
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/**
> + * Get file digest algorithm from header
> + * @param header package header
> + * @return file digest algorithm
> + */
> +char *getDigestAlgo(Header h);
> +
> +/**
> + * Get file digest length from header
> + * @param header package header
> + * @return file digest length
> + */
> +int getDigestLength(Header h);
> +
> +/**
> + * Sign a file digest with libimaevm
> + * @param algo file digest algorithm
> + * @param fdigest file digest hex
> + * @param diglen digest length
> + * @param key file signing key
> + * @return file signature hex
> + */
> +char *signFile(const char *algo, const char *fdigest, int diglen,
> + const char *key);
> +
> +/**
> + * Sign file digests in header and store the signatures in header
> + * @param h package header
> + * @param key signing key
> + * @return RPMRC_OK on success
> + */
> +rpmRC signFiles(Header h, const char *key);
> +
> +#ifdef _cplusplus
> +}
> +#endif
> +
> +#endif /* H_RPMSIGNFILES */
> diff --git a/lib/rpmtag.h b/lib/rpmtag.h
> index 58b2479..bd6a36a 100644
> --- a/lib/rpmtag.h
> +++ b/lib/rpmtag.h
> @@ -329,6 +329,7 @@ typedef enum rpmTag_e {
> RPMTAG_SUPPLEMENTNEVRS = 5060, /* s[] extension */
> RPMTAG_ENHANCENEVRS = 5061, /* s[] extension */
> RPMTAG_ENCODING = 5062, /* s */
> + RPMTAG_FILESIGNATURES = 5063, /* s[] */
>
> RPMTAG_FIRSTFREE_TAG /*!< internal */
> } rpmTag;
> diff --git a/rpmpopt.in b/rpmpopt.in
> index 036ab4e..df5e2ec 100644
> --- a/rpmpopt.in
> +++ b/rpmpopt.in
> @@ -162,6 +162,7 @@ rpm alias --httpproxy --define '_httpproxy !#:+'
> rpm exec --addsign rpmsign --addsign
> rpm exec --delsign rpmsign --delsign
> rpm exec --resign rpmsign --resign
> +#rpm exec --signfiles rpmsign --signfiles
> rpm exec --checksig rpmkeys --checksig
> rpm exec -K rpmkeys --checksig
> rpm exec --import rpmkeys --import
> diff --git a/rpmsign.c b/rpmsign.c
> index b8e5598..a2692b9 100644
> --- a/rpmsign.c
> +++ b/rpmsign.c
> @@ -20,6 +20,9 @@ enum modes {
>
> static int mode = 0;
>
> +static int signfiles = 0;
> +static char * fileSigningKey = NULL;
> +
> static struct poptOption signOptsTable[] = {
> { "addsign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_ADDSIGN,
> N_("sign package(s)"), NULL },
> @@ -27,6 +30,11 @@ static struct poptOption signOptsTable[] = {
> N_("sign package(s) (identical to --addsign)"), NULL },
> { "delsign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_DELSIGN,
> N_("delete package signatures"), NULL },
> + { "signfiles", '\0', POPT_ARG_NONE, &signfiles, 0,
> + N_("sign package(s) files"), NULL},
> + { "fskpath", '\0', POPT_ARG_STRING, &fileSigningKey, 0,
> + N_("use file signing key <key>"),
> + N_("<key>") },
> POPT_TABLEEND
> };
>
> @@ -119,6 +127,10 @@ static int doSign(poptContext optCon)
> goto exit;
> }
>
> + if (fileSigningKey && signfiles) {
> + addMacro(NULL, "_file_signing_key", NULL, fileSigningKey, RMIL_GLOBAL);
> + }
> +
> /* XXX FIXME: eliminate obsolete getpass() usage */
> passPhrase = getpass(_("Enter pass phrase: "));
> passPhrase = (passPhrase != NULL) ? rstrdup(passPhrase) : NULL;
> @@ -127,7 +139,7 @@ static int doSign(poptContext optCon)
> fprintf(stderr, _("Pass phrase is good.\n"));
> rc = 0;
> while ((arg = poptGetArg(optCon)) != NULL) {
> - rc += rpmPkgSign(arg, NULL, passPhrase);
> + rc += rpmPkgSign(arg, NULL, passPhrase, signfiles);
> }
> } else {
> fprintf(stderr, _("Pass phrase check failed or gpg key expired\n"));
> diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c
> index 0bd14e3..f07c87e 100644
> --- a/sign/rpmgensig.c
> +++ b/sign/rpmgensig.c
> @@ -1,4 +1,10 @@
> -/** \ingroup rpmcli
> +/**
> + * Copyright (C) 2014 IBM Corporation
> + *
> + * Author: Fionnuala Gunter <fi...@li...>
> + * added support for file signatures
> + *
> + * \ingroup rpmcli
> * \file lib/rpmchecksig.c
> * Verify the signature of a package.
> */
> @@ -8,17 +14,23 @@
> #include <errno.h>
> #include <sys/wait.h>
> #include <popt.h>
> +#include <imaevm.h>
> +#include <ctype.h>
>
> #include <rpm/rpmlib.h> /* RPMSIGTAG & related */
> #include <rpm/rpmmacro.h>
> #include <rpm/rpmpgp.h>
> #include <rpm/rpmsign.h>
> -#include <rpm/rpmfileutil.h> /* rpmMkTemp() */
> +#include <rpm/rpmfileutil.h> /* rpmMkTemp() */
> #include <rpm/rpmlog.h>
> #include <rpm/rpmstring.h>
>
> #include "lib/rpmlead.h"
> #include "lib/signature.h"
> +#include "lib/header.h"
> +#include "lib/cpio.h" /* rpmcpioOpen, rpmcpioTell */
> +#include "lib/rpmsignfiles.h" /* signFiles */
> +#include "rpmio/rpmio_internal.h" /* fdInitDigest, fdFiniDigest */
>
> #include "debug.h"
>
> @@ -88,6 +100,10 @@ static int manageFile(FD_t *fdp, const char *fn, int flags)
>
> /**
> * Copy header+payload, calculating digest(s) on the fly.
> + * @param sfdp source file
> + * @param sfnp source path
> + * @param tfdp destination file
> + * @param tfnp destination path
> */
> static int copyFile(FD_t *sfdp, const char *sfnp,
> FD_t *tfdp, const char *tfnp)
> @@ -121,8 +137,6 @@ static int copyFile(FD_t *sfdp, const char *sfnp,
> rc = 0;
>
> exit:
> - if (*sfdp) (void) closeFile(sfdp);
> - if (*tfdp) (void) closeFile(tfdp);
> return rc;
> }
>
> @@ -458,14 +472,277 @@ static int replaceSignature(Header sigh, sigTarget sigt1, sigTarget sigt2,
> return rc;
> }
>
> +static rpmRC generateSignature(char *SHA1, uint8_t *MD5, rpm_loff_t size,
> + rpm_loff_t payloadSize, FD_t fd)
> +{
> + Header sig = NULL;
> + struct rpmtd_s td;
> + rpmTagVal sizetag;
> + rpmTagVal payloadtag;
> + rpm_tagtype_t typetag;
> + rpmRC rc = RPMRC_OK;
> + char *reservedSpace;
> + int spaceSize = 0;
> +
> + /* Prepare signature */
> + sig = rpmNewSignature();
> +
> + rpmtdReset(&td);
> + td.tag = RPMSIGTAG_SHA1;
> + td.count = 1;
> + td.type = RPM_STRING_TYPE;
> + td.data = SHA1;
> + headerPut(sig, &td, HEADERPUT_DEFAULT);
> +
> + rpmtdReset(&td);
> + td.tag = RPMSIGTAG_MD5;
> + td.count = 16;
> + td.type = RPM_BIN_TYPE;
> + td.data = MD5;
> + headerPut(sig, &td, HEADERPUT_DEFAULT);
> +
> + if (payloadSize < UINT32_MAX) {
> + sizetag = RPMSIGTAG_SIZE;
> + payloadtag = RPMSIGTAG_PAYLOADSIZE;
> + typetag = RPM_INT32_TYPE;
> + } else {
> + sizetag = RPMSIGTAG_LONGSIZE;
> + payloadtag = RPMSIGTAG_LONGARCHIVESIZE;
> + typetag = RPM_INT64_TYPE;
> + }
> +
> + rpmtdReset(&td);
> + td.tag = payloadtag;
> + td.count = 1;
> + td.type = typetag;
> + td.data = &payloadSize;
> + headerPut(sig, &td, HEADERPUT_DEFAULT);
> +
> + rpmtdReset(&td);
> + td.tag = sizetag;
> + td.count = 1;
> + td.type = typetag;
> + td.data = &size;
> + headerPut(sig, &td, HEADERPUT_DEFAULT);
> +
> + spaceSize = rpmExpandNumeric("%{__gpg_reserved_space}");
> + if(spaceSize > 0) {
> + reservedSpace = xcalloc(spaceSize, sizeof(char));
> + rpmtdReset(&td);
> + td.tag = RPMSIGTAG_RESERVEDSPACE;
> + td.count = spaceSize;
> + td.type = RPM_BIN_TYPE;
> + td.data = reservedSpace;
> + headerPut(sig, &td, HEADERPUT_DEFAULT);
> + free(reservedSpace);
> + }
> +
> + /* Reallocate the signature into one contiguous region. */
> + sig = headerReload(sig, RPMTAG_HEADERSIGNATURES);
> + if (sig == NULL) { /* XXX can't happen */
> + rpmlog(RPMLOG_ERR, _("Unable to reload signature header.\n"));
> + rc = RPMRC_FAIL;
> + goto exit;
> + }
> +
> + /* Write the signature section into the package. */
> + if (rpmWriteSignature(fd, sig)) {
> + rc = RPMRC_FAIL;
> + goto exit;
> + }
> +
> +exit:
> + rpmFreeSignature(sig);
> + return rc;
> +}
> +
> +static void unloadImmutableRegion(Header *hdrp, rpmTagVal tag, rpmtd utd)
> +{
> + struct rpmtd_s copytd;
> + Header nh;
> + Header oh;
> + HeaderIterator hi;
> +
> + if (headerGet(*hdrp, tag, utd, HEADERGET_DEFAULT)) {
> + nh = headerNew();
> + oh = headerCopyLoad(utd->data);
> + hi = headerInitIterator(oh);
> +
> + while (headerNext(hi, ©td)) {
> + if (copytd.data)
> + headerPut(nh, ©td, HEADERPUT_DEFAULT);
> + rpmtdFreeData(©td);
> + }
> +
> + headerFreeIterator(hi);
> + headerFree(oh);
> + rpmtdFreeData(utd);
> +
> + *hdrp = headerLink(nh);
> + headerFree(nh);
> + }
> +}
> +
> +/**
> + * Include file signatures in header
> + * @param fd
> + * @param rpm path to package
> + * @param sigp pointer to signature header
> + * @param hdrp pointer to header
> + * @param sigStart signature offset in rpm
> + * @param headerStart header offset in rpm
> + */
> +static rpmRC includeFileSignatures(FD_t fd, const char *rpm,
> + Header *sigp, Header *hdrp,
> + off_t sigStart, off_t headerStart)
> +{
> + FD_t ofd = NULL;
> + struct rpmtd_s td;
> + char *trpm = NULL;
> + const char *key;
> + char *SHA1 = NULL;
> + uint8_t *MD5 = NULL;
> + unsigned char buf[32*BUFSIZ];
> + size_t sha1len;
> + size_t md5len;
> + size_t headerSize;
> + off_t archiveSize;
> + rpmRC rc = RPMRC_OK;
> +
> + unloadImmutableRegion(hdrp, RPMTAG_HEADERIMMUTABLE, &td);
> +
> + key = rpmExpand("%{?_file_signing_key}", NULL);
> + if (rstreq(key, "")) {
> + rc = RPMRC_FAIL;
> + fprintf(stderr, _("You must set \"$$_file_signing_key\" in your macro file or on the command line with --fskpath\n"));
> + rpmlog(RPMLOG_ERR, _("no file signing key provided\n"));
> + goto exit;
> + }
> +
> + rc = signFiles(*hdrp, key);
> + if (rc != RPMRC_OK) {
> + rpmlog(RPMLOG_ERR, _("signFiles failed\n"));
> + goto exit;
> + }
> +
> + *hdrp = headerReload(*hdrp, RPMTAG_HEADERIMMUTABLE);
> + if (*hdrp == NULL) {
> + rc = RPMRC_FAIL;
> + rpmlog(RPMLOG_ERR, _("headerReload failed\n"));
> + goto exit;
> + }
> +
> + ofd = rpmMkTempFile(NULL, &trpm);
> + if (ofd == NULL || Ferror(ofd)) {
> + rc = RPMRC_FAIL;
> + rpmlog(RPMLOG_ERR, _("rpmMkTemp failed\n"));
> + goto exit;
> + }
> +
> + /* Copy archive to temp file */
> + if (copyFile(&fd, rpm, &ofd, trpm)) {
> + rc = RPMRC_FAIL;
> + rpmlog(RPMLOG_ERR, _("copyFile failed\n"));
> + goto exit;
> + }
> +
> + if (Fseek(fd, headerStart, SEEK_SET) < 0) {
> + rc = RPMRC_FAIL;
> + rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"),
> + rpm, Fstrerror(fd));
> + goto exit;
> + }
> +
> + /* Write header to rpm and recalculate SHA1 */
> + fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
> + rc = headerWrite(fd, *hdrp, HEADER_MAGIC_YES);
> + if (rc != RPMRC_OK) {
> + rpmlog(RPMLOG_ERR, _("headerWrite failed\n"));
> + goto exit;
> + }
> + fdFiniDigest(fd, PGPHASHALGO_SHA1, (void **)&SHA1, &sha1len, 1);
> + headerSize = Ftell(fd) - headerStart;
> +
> + /* Copy archive from temp file */
> + if (Fseek(ofd, 0, SEEK_SET) < 0) {
> + rc = RPMRC_FAIL;
> + rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"),
> + rpm, Fstrerror(fd));
> + goto exit;
> + }
> + if (copyFile(&ofd, trpm, &fd, rpm)) {
> + rc = RPMRC_FAIL;
> + rpmlog(RPMLOG_ERR, _("copyFile failed\n"));
> + goto exit;
> + }
> + unlink(trpm);
> +
> + /* Recalculate MD5 digest of header+archive */
> + if (Fseek(fd, headerStart, SEEK_SET) < 0) {
> + rc = RPMRC_FAIL;
> + rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"),
> + rpm, Fstrerror(fd));
> + goto exit;
> + }
> + fdInitDigest(fd, PGPHASHALGO_MD5, 0);
> +
> + while (Fread(buf, sizeof(buf[0]), sizeof(buf), fd) > 0)
> + ;
> + if (Ferror(fd)) {
> + rc = RPMRC_FAIL;
> + rpmlog(RPMLOG_ERR, _("Fread failed in file %s: %s\n"),
> + rpm, Fstrerror(fd));
> + goto exit;
> + }
> + fdFiniDigest(fd, PGPHASHALGO_MD5, (void **)&MD5, &md5len, 0);
> +
> + if (Fseek(fd, sigStart, SEEK_SET) < 0) {
> + rc = RPMRC_FAIL;
> + rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"),
> + rpm, Fstrerror(fd));
> + goto exit;
> + }
> +
> + /* Get payload size from signature tag */
> + archiveSize = headerGetNumber(*sigp, RPMSIGTAG_PAYLOADSIZE);
> + if (!archiveSize) {
> + archiveSize = headerGetNumber(*sigp, RPMSIGTAG_LONGARCHIVESIZE);
> + }
> +
> + /* Replace old digests in signature */
> + rc = generateSignature(SHA1, MD5, headerSize, archiveSize, fd);
> + if (rc != RPMRC_OK) {
> + rpmlog(RPMLOG_ERR, _("insertDigests failed\n"));
> + goto exit;
> + }
> +
> + if (Fseek(fd, sigStart, SEEK_SET) < 0) {
> + rc = RPMRC_FAIL;
> + rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"),
> + rpm, Fstrerror(fd));
> + goto exit;
> + }
> +
> + rc = rpmReadSignature(fd, sigp, RPMSIGTYPE_HEADERSIG, NULL);
> + if (rc != RPMRC_OK) {
> + rpmlog(RPMLOG_ERR, _("rpmReadSignature failed\n"));
> + goto exit;
> + }
> +
> +exit:
> + return rc;
> +}
> +
> /** \ingroup rpmcli
> * Create/modify elements in signature header.
> * @param rpm path to package
> * @param deleting adding or deleting signature?
> * @param passPhrase passPhrase (ignored when deleting)
> + * @param signfiles sign files if non-zero
> * @return 0 on success, -1 on error
> */
> -static int rpmSign(const char *rpm, int deleting, const char *passPhrase)
> +static int rpmSign(const char *rpm, int deleting, const char *passPhrase,
> + int signfiles)
> {
> FD_t fd = NULL;
> FD_t ofd = NULL;
> @@ -516,25 +793,15 @@ static int rpmSign(const char *rpm, int deleting, const char *passPhrase)
> goto exit;
> }
>
> - /* Dump the immutable region (if present). */
> - if (headerGet(sigh, RPMTAG_HEADERSIGNATURES, &utd, HEADERGET_DEFAULT)) {
> - struct rpmtd_s copytd;
> - Header nh = headerNew();
> - Header oh = headerCopyLoad(utd.data);
> - HeaderIterator hi = headerInitIterator(oh);
> - while (headerNext(hi, ©td)) {
> - if (copytd.data)
> - headerPut(nh, ©td, HEADERPUT_DEFAULT);
> - rpmtdFreeData(©td);
> + if (signfiles) {
> + rc = includeFileSignatures(fd, rpm, &sigh, &h, sigStart, headerStart);
> + if (rc != RPMRC_OK) {
> + rpmlog(RPMLOG_ERR, _("includeFileSignatures failed\n"));
> + goto exit;
> }
> - headerFreeIterator(hi);
> - headerFree(oh);
> - rpmtdFreeData(&utd);
> -
> - headerFree(sigh);
> - sigh = headerLink(nh);
> - headerFree(nh);
> }
> +
> + unloadImmutableRegion(&sigh, RPMTAG_HEADERSIGNATURES, &utd);
> origSigSize = headerSizeof(sigh, HEADER_MAGIC_YES);
>
> if (deleting) { /* Nuke all the signature tags. */
> @@ -566,6 +833,7 @@ static int rpmSign(const char *rpm, int deleting, const char *passPhrase)
>
> /* Try to make new signature smaller to have size of original signature */
> rpmtdReset(&utd);
> +
> if (headerGet(sigh, RPMSIGTAG_RESERVEDSPACE, &utd, HEADERGET_MINMEM)) {
> int diff;
> int count;
> @@ -668,7 +936,8 @@ exit:
> }
>
> int rpmPkgSign(const char *path,
> - const struct rpmSignArgs * args, const char *passPhrase)
> + const struct rpmSignArgs * args, const char *passPhrase,
> + int signfiles)
> {
> int rc;
>
> @@ -684,7 +953,7 @@ int rpmPkgSign(const char *path,
> }
> }
>
> - rc = rpmSign(path, 0, passPhrase);
> + rc = rpmSign(path, 0, passPhrase, signfiles);
>
> if (args) {
> if (args->hashalgo) {
> @@ -700,5 +969,5 @@ int rpmPkgSign(const char *path,
>
> int rpmPkgDelSign(const char *path)
> {
> - return rpmSign(path, 1, NULL);
> + return rpmSign(path, 1, NULL, 0);
> }
> diff --git a/sign/rpmsign.h b/sign/rpmsign.h
> index 15b3e0f..0ec37c1 100644
> --- a/sign/rpmsign.h
> +++ b/sign/rpmsign.h
> @@ -11,6 +11,8 @@ extern "C" {
> struct rpmSignArgs {
> char *keyid;
> pgpHashAlgo hashalgo;
> + int signFiles;
> + const char *fileSigningKey;
> /* ... what else? */
> };
>
> @@ -19,10 +21,11 @@ struct rpmSignArgs {
> * @param path path to package
> * @param args signing parameters (or NULL for defaults)
> * @param passPhrase passphrase for the signing key
> + * @param signfiles sign files if non-zero
> * @return 0 on success
> */
> -int rpmPkgSign(const char *path,
> - const struct rpmSignArgs * args, const char *passPhrase);
> +int rpmPkgSign(const char *path, const struct rpmSignArgs * args,
> + const char *passPhrase, int signfiles);
>
> /** \ingroup rpmsign
> * Delete signature(s) from a package
|
|
From: Dmitry K. <dmi...@gm...> - 2014-10-21 19:58:07
|
On October 21, 2014 5:51:23 PM EEST, Mimi Zohar <zo...@li...> wrote: >On Tue, 2014-10-21 at 12:00 +0300, Dmitry Kasatkin wrote: >> Hi, >> >> It is actually very difficult to see the "diff", because patch >removes >> file and add new file.. >> >> You better do it in 2 steps... >> >> 1) rename dh_md5sums to dh_checksums >> 2) do changes. >> >> Then it will be very clear what are your changes.. > >As the dh_md5sums is being called manually from numerous packages, the >next posting will define dh_checksums, but will not remove dh_md5sums. > >Mimi May be for compatibility you still need to keep it and not rename at all. Otherwise it will break hundreds of packages. Dmitry > > >------------------------------------------------------------------------------ >Comprehensive Server Monitoring with Site24x7. >Monitor 10 servers for $9/Month. >Get alerted through email, SMS, voice calls or mobile push >notifications. >Take corrective actions from your mobile device. >http://p.sf.net/sfu/Zoho >_______________________________________________ >Linux-ima-user mailing list >Lin...@li... >https://lists.sourceforge.net/lists/listinfo/linux-ima-user - Dmitry |